Merge lp:~compiz-team/compiz/compiz.fix_1006335 into lp:compiz/0.9.8

Proposed by Sam Spilsbury
Status: Merged
Merged at revision: 3243
Proposed branch: lp:~compiz-team/compiz/compiz.fix_1006335
Merge into: lp:compiz/0.9.8
Diff against target: 303 lines (+98/-47)
4 files modified
src/privatescreen.h (+22/-2)
src/privatestackdebugger.h (+9/-4)
src/screen.cpp (+37/-30)
src/stackdebugger.cpp (+30/-11)
To merge this branch: bzr merge lp:~compiz-team/compiz/compiz.fix_1006335
Reviewer Review Type Date Requested Status
Daniel van Vugt Approve
Compiz Maintainers Pending
Review via email: mp+108706@code.launchpad.net

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

Description of the change

Fixes needless list copying in event queues

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

There's a risk of crashing, by assuming there are still only XEventsQueued by the time we consume them all. The server might have more events ready by then. More than we sized the event vector for, so either:
        XNextEvent (dpy, &(*it));
or
        it++
will crash. Because it is now past the end of the vector.

But it's a simple fix. Just use reserve() instead of resize() and push_back instead of writing to *it.

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

Also I'm still concerned by the use of the heap on every single event:

void
PrivateScreen::processEvents ()
{
    std::vector <XEvent> events;

The solution I had in mind for this bug didn't require that. Maybe I'll prototype it to see if it works.

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

OK, my first comment is mistaken. But I'd like to see a solution that bypasses the heap for most events.

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

That's a lot more complicated than the solution I had in mind, but if it works...

Also, I recommend not changing unrelated logic like the location of:
    windowManager.removeDestroyed ();
The change may be correct, but changing logic not related to the bug in question is best avoided.

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

On Fri, 1 Jun 2012, Daniel van Vugt wrote:

> Review: Needs Fixing
>
> That's a lot more complicated than the solution I had in mind, but if it works...
>
> Also, I recommend not changing unrelated logic like the location of:
> windowManager.removeDestroyed ();
> The change may be correct, but changing logic not related to the bug in question is best avoided.

Actually I changed it because we should be removing destroyed windows at
the end of every event processed. Without that change, we might never do
it.

Could you clarify what else needs fixing?

> --
> https://code.launchpad.net/~compiz-team/compiz/compiz.fix_1006335/+merge/107953
> Your team Compiz Maintainers is requested to review the proposed merge of lp:~compiz-team/compiz/compiz.fix_1006335 into lp:compiz.
>

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

windowManager.removeDestroyed ();

is what needs fixing. Your reasoning for moving it sounds correct but it's not related to bug 1006335 so please remove it from the proposal.

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

Sorry, I just noticed:
    std::deque
should be:
    std::list

Because std::deque introduces extra complexity to implement random access. It's actually implemented as a red-black tree like std::map or std::set. But since we're not using random access and only need head/tail insertion and removal, a simple doubly linked list (std::list) will be faster and smaller.

This proposal is still much larger than it should be. It's an itch I have to scratch but I'm trying not to push the point too much. :/

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

Thanks, recompiling.

I don't think that the proposal is too large, however it does optimize bits that are only really used in debug mode, which pushed up the size a bit.

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

Done.

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

Looks OK and no obvious regressions.

I can't do a realistic comparative profile with callgrind right now because I've switched drivers and it would change my normal expected results. But this appears to solve the bug.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'src/privatescreen.h'
--- src/privatescreen.h 2012-05-23 07:37:37 +0000
+++ src/privatescreen.h 2012-06-05 09:07:25 +0000
@@ -608,8 +608,27 @@
608608
609}} // namespace compiz::private_screen609}} // namespace compiz::private_screen
610610
611class FetchXEventInterface
612{
613 public:
614
615 virtual ~FetchXEventInterface () {}
616
617 virtual bool getNextXEvent (XEvent &) = 0;
618};
619
620class FetchEventInterface
621{
622 public:
623
624 virtual ~FetchEventInterface () {}
625 virtual bool getNextEvent (XEvent &) = 0;
626};
627
611class PrivateScreen :628class PrivateScreen :
612 public CoreOptions629 public CoreOptions,
630 public FetchXEventInterface,
631 public FetchEventInterface
613{632{
614633
615 public:634 public:
@@ -623,7 +642,8 @@
623642
624 bool setOption (const CompString &name, CompOption::Value &value);643 bool setOption (const CompString &name, CompOption::Value &value);
625644
626 std::list <XEvent> queueEvents ();645 bool getNextEvent (XEvent &);
646 bool getNextXEvent (XEvent &);
627 void processEvents ();647 void processEvents ();
628648
629 bool triggerButtonPressBindings (CompOption::Vector &options,649 bool triggerButtonPressBindings (CompOption::Vector &options,
630650
=== modified file 'src/privatestackdebugger.h'
--- src/privatestackdebugger.h 2011-09-29 03:29:41 +0000
+++ src/privatestackdebugger.h 2012-06-05 09:07:25 +0000
@@ -27,20 +27,23 @@
27 * so that this can be come a truly standalone27 * so that this can be come a truly standalone
28 * object */28 * object */
29#include <core/core.h>29#include <core/core.h>
30#include <list>
3031
31#ifndef _COMPIZ_PRIVATESTACKDEBUGGER_H32#ifndef _COMPIZ_PRIVATESTACKDEBUGGER_H
32#define _COMPIZ_PRIVATESTACKDEBUGGER_H33#define _COMPIZ_PRIVATESTACKDEBUGGER_H
3334
35class FetchXEventInterface;
36
34class StackDebugger37class StackDebugger
35{38{
36 public:39 public:
3740
38 typedef std::list<XEvent> eventList;41 typedef std::vector<XEvent> eventList;
3942
40 StackDebugger (Display *, Window, boost::function<eventList ()> evProc);43 StackDebugger (Display *, Window, FetchXEventInterface *fetchXEvent);
41 ~StackDebugger ();44 ~StackDebugger ();
4245
43 eventList loadStack (CompWindowList &serverWindows, bool wait = false);46 void loadStack (CompWindowList &serverWindows, bool wait = false);
44 void windowsChanged (bool change) { mWindowsChanged = change; };47 void windowsChanged (bool change) { mWindowsChanged = change; };
45 void serverWindowsChanged (bool change) { mServerWindowsChanged = change; };48 void serverWindowsChanged (bool change) { mServerWindowsChanged = change; };
46 bool windowsChanged () { return mWindowsChanged; }49 bool windowsChanged () { return mWindowsChanged; }
@@ -54,6 +57,7 @@
54 CompWindowList &serverWindows,57 CompWindowList &serverWindows,
55 bool verbose = false);58 bool verbose = false);
56 bool timedOut ();59 bool timedOut ();
60 bool getNextEvent (XEvent &);
5761
58 bool checkSanity (CompWindowList &serverWindows, bool verbose = false);62 bool checkSanity (CompWindowList &serverWindows, bool verbose = false);
5963
@@ -70,9 +74,10 @@
70 bool mServerWindowsChanged;74 bool mServerWindowsChanged;
71 Window mRoot;75 Window mRoot;
72 Display *mDpy;76 Display *mDpy;
73 boost::function<eventList ()> getEventsProc;77 FetchXEventInterface *mFetchXEvent;
74 bool mTimeoutRequired;78 bool mTimeoutRequired;
75 CompWindowList mLastServerWindows;79 CompWindowList mLastServerWindows;
80 std::list <XEvent> mEvents;
76};81};
7782
78#endif83#endif
7984
=== modified file 'src/screen.cpp'
--- src/screen.cpp 2012-05-25 07:37:42 +0000
+++ src/screen.cpp 2012-06-05 09:07:25 +0000
@@ -752,41 +752,48 @@
752 return rv;752 return rv;
753}753}
754754
755std::list <XEvent>755bool
756PrivateScreen::queueEvents ()756PrivateScreen::getNextXEvent (XEvent &ev)
757{757{
758 std::list <XEvent> events;758 if (!XEventsQueued (dpy, QueuedAlready))
759 return false;
760 XNextEvent (dpy, &ev);
759761
760 while (XPending (dpy))762 /* Skip to the last MotionNotify
763 * event in this sequence */
764 if (ev.type == MotionNotify)
761 {765 {
762 XEvent event, peekEvent;766 XEvent peekEvent;
763 XNextEvent (dpy, &event);767 while (XPending (dpy))
764
765 /* Skip to the last MotionNotify
766 * event in this sequence */
767 if (event.type == MotionNotify)
768 {768 {
769 while (XPending (dpy))769 XPeekEvent (dpy, &peekEvent);
770 {770
771 XPeekEvent (dpy, &peekEvent);771 if (peekEvent.type != MotionNotify)
772772 break;
773 if (peekEvent.type != MotionNotify)773
774 break;774 XNextEvent (dpy, &peekEvent);
775
776 XNextEvent (dpy, &event);
777 }
778 }775 }
779776 }
780 events.push_back (event);777
781 }778 return true;
782779}
783 return events;780
781bool
782PrivateScreen::getNextEvent (XEvent &ev)
783{
784 StackDebugger *dbg = StackDebugger::Default ();
785
786 if (StackDebugger::Default ())
787 {
788 return dbg->getNextEvent (ev);
789 }
790 else
791 return getNextXEvent (ev);
784}792}
785793
786void794void
787PrivateScreen::processEvents ()795PrivateScreen::processEvents ()
788{796{
789 std::list <XEvent> events;
790 StackDebugger *dbg = StackDebugger::Default ();797 StackDebugger *dbg = StackDebugger::Default ();
791798
792 if (pluginManager.isDirtyPluginList ())799 if (pluginManager.isDirtyPluginList ())
@@ -801,14 +808,14 @@
801 {808 {
802 dbg->windowsChanged (false);809 dbg->windowsChanged (false);
803 dbg->serverWindowsChanged (false);810 dbg->serverWindowsChanged (false);
804 events = dbg->loadStack (windowManager.getServerWindows());811 dbg->loadStack (windowManager.getServerWindows());
805 }812 }
806 else
807 events = queueEvents ();
808813
809 windowManager.invalidateServerWindows();814 windowManager.invalidateServerWindows();
810815
811 foreach (XEvent &event, events)816 XEvent event;
817
818 while (getNextEvent (event))
812 {819 {
813 switch (event.type) {820 switch (event.type) {
814 case ButtonPress:821 case ButtonPress:
@@ -4792,7 +4799,7 @@
4792 new StackDebugger (4799 new StackDebugger (
4793 dpy (),4800 dpy (),
4794 root (),4801 root (),
4795 boost::bind (&PrivateScreen::queueEvents, &privateScreen)));4802 &privateScreen));
4796 }4803 }
47974804
4798 return true;4805 return true;
47994806
=== modified file 'src/stackdebugger.cpp'
--- src/stackdebugger.cpp 2011-10-07 11:45:38 +0000
+++ src/stackdebugger.cpp 2012-06-05 09:07:25 +0000
@@ -24,6 +24,7 @@
24 */24 */
2525
26#include "privatestackdebugger.h"26#include "privatestackdebugger.h"
27#include "privatescreen.h"
27#include "privatewindow.h"28#include "privatewindow.h"
28#include <poll.h>29#include <poll.h>
2930
@@ -47,14 +48,14 @@
47 gStackDebugger = dbg;48 gStackDebugger = dbg;
48}49}
4950
50StackDebugger::StackDebugger (Display *dpy, Window root, boost::function <eventList ()> evProc) :51StackDebugger::StackDebugger (Display *dpy, Window root, FetchXEventInterface *fetchXEvent) :
51 mServerNChildren (0),52 mServerNChildren (0),
52 mServerChildren (NULL),53 mServerChildren (NULL),
53 mWindowsChanged (false),54 mWindowsChanged (false),
54 mServerWindowsChanged (false),55 mServerWindowsChanged (false),
55 mRoot (root),56 mRoot (root),
56 mDpy (dpy),57 mDpy (dpy),
57 getEventsProc (evProc)58 mFetchXEvent (fetchXEvent)
58{59{
59}60}
6061
@@ -118,11 +119,23 @@
118 mLastServerWindows.push_front (tl);119 mLastServerWindows.push_front (tl);
119}120}
120121
121StackDebugger::eventList122bool
123StackDebugger::getNextEvent (XEvent &ev)
124{
125 if (mEvents.empty ())
126 return false;
127
128 ev = mEvents.front ();
129
130 mEvents.pop_front ();
131
132 return true;
133}
134
135void
122StackDebugger::loadStack (CompWindowList &serverWindows, bool wait)136StackDebugger::loadStack (CompWindowList &serverWindows, bool wait)
123{137{
124 Window rootRet, parentRet;138 Window rootRet, parentRet;
125 eventList events;
126139
127 if (mServerChildren)140 if (mServerChildren)
128 XFree (mServerChildren);141 XFree (mServerChildren);
@@ -132,7 +145,16 @@
132 XQueryTree (mDpy, mRoot, &rootRet, &parentRet,145 XQueryTree (mDpy, mRoot, &rootRet, &parentRet,
133 &mServerChildren, &mServerNChildren);146 &mServerChildren, &mServerNChildren);
134147
135 events = getEventsProc ();148 unsigned int n = XEventsQueued (mDpy, QueuedAfterFlush);
149 mEvents.clear ();
150 mEvents.resize (n);
151 std::list <XEvent>::iterator it = mEvents.begin ();
152
153 while (it != mEvents.end ())
154 {
155 mFetchXEvent->getNextXEvent ((*it));
156 it++;
157 }
136158
137 XSync (mDpy, FALSE);159 XSync (mDpy, FALSE);
138160
@@ -145,7 +167,6 @@
145167
146 if (mServerNChildren != serverWindows.size () && wait)168 if (mServerNChildren != serverWindows.size () && wait)
147 {169 {
148 eventList moreEvents;
149 struct pollfd pfd;170 struct pollfd pfd;
150171
151 pfd.events = POLLIN;172 pfd.events = POLLIN;
@@ -154,10 +175,10 @@
154175
155 poll (&pfd, 1, 300);176 poll (&pfd, 1, 300);
156177
157 moreEvents = getEventsProc ();178 XEvent e;
158179
159 foreach (XEvent e, moreEvents)180 while (mFetchXEvent->getNextXEvent (e))
160 events.push_back (e);181 mEvents.push_back (e);
161182
162 mTimeoutRequired = true;183 mTimeoutRequired = true;
163 }184 }
@@ -166,8 +187,6 @@
166187
167 XUngrabServer (mDpy);188 XUngrabServer (mDpy);
168 XSync (mDpy, FALSE);189 XSync (mDpy, FALSE);
169
170 return events;
171}190}
172191
173void192void

Subscribers

People subscribed via source and target branches