Merge lp://qastaging/~smspillaz/compiz-core/compiz-core.fix_969108.2 into lp://qastaging/compiz-core

Proposed by Sam Spilsbury
Status: Superseded
Proposed branch: lp://qastaging/~smspillaz/compiz-core/compiz-core.fix_969108.2
Merge into: lp://qastaging/compiz-core
Diff against target: 1329 lines (+1119/-7)
12 files modified
include/core/screen.h (+1/-0)
plugins/CMakeLists.txt (+1/-0)
plugins/move/src/move.cpp (+48/-5)
plugins/move/src/move.h (+32/-2)
src/CMakeLists.txt (+5/-0)
src/queues/CMakeLists.txt (+61/-0)
src/queues/include/core/queues.h (+362/-0)
src/queues/src/queues.cpp (+113/-0)
src/queues/tests/CMakeLists.txt (+18/-0)
src/queues/tests/queues/src/test-queues.cpp (+231/-0)
src/queues/tests/test-queues.cpp (+34/-0)
src/queues/tests/test-queues.h (+213/-0)
To merge this branch: bzr merge lp://qastaging/~smspillaz/compiz-core/compiz-core.fix_969108.2
Reviewer Review Type Date Requested Status
Daniel van Vugt Needs Fixing
Review via email: mp+100542@code.qastaging.launchpad.net

This proposal supersedes a proposal from 2012-04-02.

This proposal has been superseded by a proposal from 2012-04-04.

Description of the change

== Problem ==

moveHandleMotionEvent could cause the window geometry to be updated several times a second which would have run-on effects in calling moveNotify a lot in the plugins. This would cause an unnessary performance hit.

== Solution ==

Added a new releasable queue structure, which allows observers to lock the queue and trigger releases at a later point and an accumulator to accumulate values to release in the future. Use this in order to queue up motion on windows and release in synchronization with repaints so that we only update the geometries where it matters.

== Tests ==

Test Suite included.

To post a comment you must log in.
Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

Again, I can't endorse a major rewrite of critical functionality this late.

review: Abstain
Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

Also, this 1000 lines of code seems to be aimed at solving a problem that I planned on solving myself in only a dozen or so lines. Is it really necessary to introduce such vast complexity?

Revision history for this message
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal

1) This isn't a rewrite
2) The only functional changes are in the form of

42 if (state & CompAction::StateCancel)
43 - ms->w->move (ms->savedX - ms->w->geometry ().x (),
44 - ms->savedY - ms->w->geometry ().y (), false);
45 + ms->addMovement (MoveWindow::get (ms->w), CompPoint (ms->savedX - ms->w->geometry ().x (),
46 + ms->savedY - ms->w->geometry ().y ()));
47
48 ms->w->syncPosition ();
49
50 @@ -484,8 +486,7 @@
51
52 if (dx || dy)
53 {
54 - w->move (wX + dx - w->geometry ().x (),
55 - wY + dy - w->geometry ().y (), false);
56 + ms->addMovement (MoveWindow::get (w), CompPoint (dx, dy));
62
63 bool
64 +MoveWindow::doRelease (const CompPoint &d)
65 +{
66 + window->move (d.x (), d.y (), false);
67 + return true;
68 +}
69 +
70 +void
71 +MoveScreen::dispatchDamage (compiz::queues::QueueReleaseInterface *releasable)
72 +{
73 + MoveWindow *mw = static_cast <MoveWindow *> (releasable);
74 + mw->cWindow->addDamage ();
75 +}
76 +
77 +bool
78 MoveScreen::registerPaintHandler(compiz::composite::PaintHandler *pHnd)
79 {
80 hasCompositing = true;
81 @@ -677,9 +692,27 @@
82 MoveScreen::unregisterPaintHandler()
83 {
84 hasCompositing = false;
85 + queueLock.reset ();
86 cScreen->unregisterPaintHandler ();
87 }
88
89 +void
90 +MoveScreen::preparePaint (int ms)
91 +{
92 + if (queueLock)
93 + queueLock->unlock ();
94 +
95 + cScreen->preparePaint (ms);
96 + cScreen->preparePaintSetEnabled (this, false);
97 +}
98 +
99 +void
100 +MoveScreen::addMovement (MoveWindow *mw, const CompPoint &d)
101 +{
102 + cScreen->preparePaintSetEnabled (this, true);
103 + pendingMovements->addPending (d, mw);
104 +}
105 +
113 - yConstrained (false)
114 + yConstrained (false),
115 + pendingMovementsStorage (new compiz::queues::impl::AccumulatedMapStorage <CompPoint> ()),
116 + pendingMovements (new compiz::queues::impl::Queue <CompPoint> (boost::shared_static_cast <compiz::queues::QueueStorageInterface <CompPoint> > (pendingMovementsStorage)))
123 CompositeScreenInterface::setHandler (cScreen);
124 + queueLock = pendingMovements->obtainLock (boost::bind (&MoveScreen::dispatchDamage, this, _1));
125 + cScreen->preparePaintSetEnabled (this, false);

That's fairly small

3) The reason the diff is so large is because 100 of 1200 lines are cmake and 600 of the 1200 lines are tests
4) This solution is aimed at making releasable queues more generic
5) Its blocking other work

Plenty of good reasons to merge this before precise.

Revision history for this message
Tim Penhey (thumper) wrote : Posted in a previous version of this proposal

Making destructors pure virtual is only really necessary if there are no other pure virtual methods and you want to make the class abstract. Other than that they are just a PITA.

Revision history for this message
Mikkel Kamstrup Erlandsen (kamstrup) wrote : Posted in a previous version of this proposal

I don't know the compiz coding standards, but for abstract code like this I'd expect at the very least 2 comments: 1) In queue.cpp/h explaining what the general idea behind all the interfaces are, 2) in the move.cpp explaining what it is using the clever queues for (ie. why a bog standard list is not good enough)

Revision history for this message
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

It isn't obvious what contracts the template interfaces QueueStorageInterface, QueueInterface, and QueueLockInterface represent. E.g. I'd expect a lock to have "lock()" and "unlock()" methods or similar. Do they need to be templates?

The pure destructors and NVPI clutter up the code.

In MoveScreen the new variables pendingMovementsStorage, pendingMovements and queueLock could be private. (I suspect others could too - what is it with compiz and public data members?)

I don't see why pendingMovementsStorage is a member variable - it's only use is in initalizing pendingMovements. In any case, it should be of the usage type - shared_ptr<QueueStorageInterface> not the implementation type.

There is no need for pendingMovements to be allocated on the heap instead of being a member variable. (The same change for pendingMovementsStorage which would require a signature change for compiz::queues::impl::Queue::Queue - but that's minor.)

Revision history for this message
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal

> It isn't obvious what contracts the template interfaces QueueStorageInterface,
> QueueInterface, and QueueLockInterface represent. E.g. I'd expect a lock to
> have "lock()" and "unlock()" methods or similar. Do they need to be
> templates?

QueueReleaseInterface, QueueInterface and QueueStorageInterface need to know the type that is being stored. As such, they are templates.

QueueLockInterface takes a lock on a QueueUnlockableInterface on construction. Eg, the very act of constructing a QueueLockInterface means that it will receive callbacks and block dispatching of the queue items until the client calls unlock () on it, at which point will call a method in QueueUnlockableInterface to decrement the lock count.

QueueStorageInterface is the abstraction of how queued items are stored.

QueueInterface is the interface to the Queue itself, eg, pushing data into the queue.

>
> The pure destructors and NVPI clutter up the code.
>
> In MoveScreen the new variables pendingMovementsStorage, pendingMovements and
> queueLock could be private. (I suspect others could too - what is it with
> compiz and public data members?)

Ack, although I believe we're using this from MoveWindow.

>
> I don't see why pendingMovementsStorage is a member variable - it's only use
> is in initalizing pendingMovements. In any case, it should be of the usage
> type - shared_ptr<QueueStorageInterface> not the implementation type.

You are correct.

I believe the reason I made it a member was merely for convenience, without that, this line

pendingMovements (new compiz::queues::impl::Queue <CompPoint> (boost::shared_static_cast <compiz::queues::QueueStorageInterface <CompPoint> > (pendingMovementsStorage)))

would look something like

pendingMovements (new compiz::queues::impl::Queue <CompPoint> (boost::shared_static_cast <compiz::queues::QueueStorageInterface <CompPoint> > (compiz::queues::impl::AccumulatedMapStorage <CompPoint>::Ptr ((new compiz::queues::impl::AccumulatedMapStorage <CompPoint> ()))))

(which is a bit of a monstrosity :( )

>
> There is no need for pendingMovements to be allocated on the heap instead of
> being a member variable. (The same change for pendingMovementsStorage which
> would require a signature change for compiz::queues::impl::Queue::Queue - but
> that's minor.)

I think the reason why I had it on the heap was because if it was on the stack then this would mean we'd pass QueueStorageInterface by const reference and we'd have to copy the temporary into the member variable inside of ::Queue . That would mean adding copying semantics to something which shouldn't really be copied anyways (QueueStorageInterface describes /how/ the queue data should be stored, it isn't a value type in itself).

pendingMovements on the other hand could be on the stack.

Revision history for this message
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal

> I don't know the compiz coding standards, but for abstract code like this I'd
> expect at the very least 2 comments: 1) In queue.cpp/h explaining what the
> general idea behind all the interfaces are, 2) in the move.cpp explaining what
> it is using the clever queues for (ie. why a bog standard list is not good
> enough)

Yes, I will add such comments. Thanks Mikkel

Revision history for this message
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal

> Making destructors pure virtual is only really necessary if there are no other
> pure virtual methods and you want to make the class abstract. Other than that
> they are just a PITA.

Ack

Revision history for this message
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

> > It isn't obvious what contracts the template interfaces
> QueueStorageInterface,
> > QueueInterface, and QueueLockInterface represent. E.g. I'd expect a lock to
> > have "lock()" and "unlock()" methods or similar. Do they need to be
> > templates?
>
> QueueReleaseInterface, QueueInterface and QueueStorageInterface need to know
> the type that is being stored. As such, they are templates.

Yes, but they are only instantiated on one type in real code. (And another in the tests.)

> >
> > The pure destructors and NVPI clutter up the code.
> >
> > In MoveScreen the new variables pendingMovementsStorage, pendingMovements
> and
> > queueLock could be private. (I suspect others could too - what is it with
> > compiz and public data members?)
>
> Ack, although I believe we're using this from MoveWindow.

Not in the code I see.

> > I don't see why pendingMovementsStorage is a member variable - it's only use
> > is in initalizing pendingMovements. In any case, it should be of the usage
> > type - shared_ptr<QueueStorageInterface> not the implementation type.
>
> You are correct.
>
> I believe the reason I made it a member was merely for convenience, without
> that, this line
>
> pendingMovements (new compiz::queues::impl::Queue <CompPoint>
> (boost::shared_static_cast <compiz::queues::QueueStorageInterface <CompPoint>
> > (pendingMovementsStorage)))
>
> would look something like
>
> pendingMovements (new compiz::queues::impl::Queue <CompPoint>
> (boost::shared_static_cast <compiz::queues::QueueStorageInterface <CompPoint>
> > (compiz::queues::impl::AccumulatedMapStorage <CompPoint>::Ptr ((new
> compiz::queues::impl::AccumulatedMapStorage <CompPoint> ()))))

Or without the pointless cast...

pendingMovements (new compiz::queues::impl::Queue <CompPoint> (compiz::queues::impl::QueueStorageInterface <CompPoint>::Ptr ((new compiz::queues::impl::AccumulatedMapStorage <CompPoint> ())))

And if you don't repeat compiz::queues::impl:: all the time.

pendingMovements (new cqi::Queue <CompPoint> (cqi::QueueStorageInterface <CompPoint>::Ptr ((new cqi::AccumulatedMapStorage <CompPoint> ())))

> > There is no need for pendingMovements to be allocated on the heap instead of
> > being a member variable. (The same change for pendingMovementsStorage which
> > would require a signature change for compiz::queues::impl::Queue::Queue -
> but
> > that's minor.)
>
> I think the reason why I had it on the heap was because if it was on the stack
> then this would mean we'd pass QueueStorageInterface by const reference and
> we'd have to copy the temporary into the member variable inside of ::Queue .
> That would mean adding copying semantics to something which shouldn't really
> be copied anyways (QueueStorageInterface describes /how/ the queue data should
> be stored, it isn't a value type in itself).

I think there's a misunderstanding. But that's moot in view of the above discussion.

> pendingMovements on the other hand could be on the stack.

A data member. Then the "monsterous" line becomes:

pendingMovements (cqi::QueueStorageInterface <CompPoint>::Ptr ((new cqi::AccumulatedMapStorage <CompPoint> ()))

Revision history for this message
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal

Code cleaned up. Resubmitted ... though it looks like I have more to do. Fun.

Revision history for this message
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal

> QueueReleaseInterface, QueueInterface and QueueStorageInterface need to know
> the type that is being stored. As such, they are templates.

> Yes, but they are only instantiated on one type in real code. (And another in the tests.)

I plan to use this in other parts of the code. It was almost generic as it was, and is quite useful as a separate mechanism IMO

Will use namespace aliases as recommended

Revision history for this message
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal

Code cleaned up and resubmitted again

Revision history for this message
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

Seems to work. And the functionality seems a good idea.

But, now we can read what they do, the names of the queues classes seem a bit awkward...

"QueueInterface" does only a small subset of what I'd expect a queue to do and adding "Interface" to the name seems verbose (not that I like Microsoft's "I" prefix either). "Appender" may be better?

"QueueLockInterface" this doesn't behave as I expect from a lock. It is a pre-release callback to request permission to release the queue.

(I find the other names problematic too - but don't want to go on too much.)

On the design side, I don't like the fact that downcasts are required by the code using these classes. As a general principle templates should allow this to be avoided by propagating type information.

Revision history for this message
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal

> Seems to work. And the functionality seems a good idea.
>
> But, now we can read what they do, the names of the queues classes seem a bit
> awkward...
>
> "QueueInterface" does only a small subset of what I'd expect a queue to do and
> adding "Interface" to the name seems verbose (not that I like Microsoft's "I"
> prefix either). "Appender" may be better?

The I/Interface/Whatever discussion needs to be had somewhere else.

>
> "QueueLockInterface" this doesn't behave as I expect from a lock. It is a
> pre-release callback to request permission to release the queue.

QueueHoldInterface ?

>
> (I find the other names problematic too - but don't want to go on too much.)
>
> On the design side, I don't like the fact that downcasts are required by the
> code using these classes. As a general principle templates should allow this
> to be avoided by propagating type information.

550 + mItems[static_cast <QueueReleaseInterface *> (i)] += t;
551 +
552 + return true;
553 + }
554 +
555 + void doRelease ()
556 + {
557 + typename std::map <QueueReleaseInterface *, T>::iterator it = mItems.begin ();
558 +
559 + for (; it != mItems.end (); it++)
560 + {
561 + QueueReleasableInterface <T> *releasable = static_cast <QueueReleasableInterface <T> *> (it->first);

These two are avoidable. I'll try something else. As for the downcast to MoveWindow, it should be possible to avoid that one by changing the boost::function to another interface like a QueueItemReadyCallback or perhaps adding an notifyItemReady (); to QueueReleaseInterface

Revision history for this message
Sam Spilsbury (smspillaz) wrote :

Resubmitted again. Can we get this merged soon if the only remaining changes are purely regarding class names ? This is blocking other stuff ...

Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

> Resubmitted again. Can we get this merged soon if the only remaining changes
> are purely regarding class names ? This is blocking other stuff ...

Are you suggesting that good names are not important?

Revision history for this message
Sam Spilsbury (smspillaz) wrote :

> > Resubmitted again. Can we get this merged soon if the only remaining changes
> > are purely regarding class names ? This is blocking other stuff ...
>
> Are you suggesting that good names are not important?

Good names are important, but can be a topic for later refactoring if we've got writers block.

Revision history for this message
Daniel van Vugt (vanvugt) wrote :

Tested this branch merged with lp:~smspillaz/compiz-core/compiz-core.work_923683
For some reason, it makes window movement worse, not better. Now much of the time, windows do not move at all when dragged.

I believe this branch is intended to fix the problem with work_923683, instead of making it worse. :(

review: Needs Fixing
Revision history for this message
Sam Spilsbury (smspillaz) wrote :

> Tested this branch merged with lp:~smspillaz/compiz-core/compiz-
> core.work_923683
> For some reason, it makes window movement worse, not better. Now much of the
> time, windows do not move at all when dragged.
>
> I believe this branch is intended to fix the problem with work_923683, instead
> of making it worse. :(

One of the recent refactorings may have broken something unintentionally. I wasn't able to test at teh time due to not having a working graphics driver (fixed now). I'll re-check when I get back.

Revision history for this message
Daniel van Vugt (vanvugt) wrote :

By contrast, using this simple optimization I could get the work_923683 branch performing better:
https://code.launchpad.net/~vanvugt/compiz-core/lastMotionTime/+merge/100742

Revision history for this message
Sam Spilsbury (smspillaz) wrote :

Missing motion events will cause subtle bugs in edge detection

Revision history for this message
Daniel van Vugt (vanvugt) wrote :

In theory, yes, but only if you set the max_motion_rate much much lower than your monitor's frame rate. Which it will never be.

Also, if that were a real issue then the old motion deduplication code should be removed for the same reason.

3088. By Sam Spilsbury

Actually hook up to itemPending

Unmerged revisions

3088. By Sam Spilsbury

Actually hook up to itemPending

3087. By Sam Spilsbury

Remove downcasts where possible

3086. By Sam Spilsbury

Also notify interested data receivers they have data pending

3085. By Sam Spilsbury

Remove the shared static cast

3084. By Sam Spilsbury

Namespace alias

3083. By Sam Spilsbury

Removed AccumulatedMapStorage member

3082. By Sam Spilsbury

Made pendingMovements not a shared ptr

3081. By Sam Spilsbury

Made pendingMovements private

3080. By Sam Spilsbury

Removed virtual destructors

3079. By Sam Spilsbury

Added documentation for the contract provided by queues

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
The diff is not available at this time. You can reload the page or download it.

Subscribers

People subscribed via source and target branches