Merge lp:~compiz-team/compiz/compiz.fix_1006335 into lp:compiz/0.9.8
- compiz.fix_1006335
- Merge into 0.9.8
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 |
Related bugs: |
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.
Commit message
Description of the change
Fixes needless list copying in event queues
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal | # |
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:
{
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.
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.
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:
windowManag
The change may be correct, but changing logic not related to the bug in question is best avoided.
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.
> 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:/
> Your team Compiz Maintainers is requested to review the proposed merge of lp:~compiz-team/compiz/compiz.fix_1006335 into lp:compiz.
>
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal | # |
windowManager.
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.
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. :/
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.
Sam Spilsbury (smspillaz) wrote : | # |
Done.
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.
Preview Diff
1 | === modified file 'src/privatescreen.h' | |||
2 | --- src/privatescreen.h 2012-05-23 07:37:37 +0000 | |||
3 | +++ src/privatescreen.h 2012-06-05 09:07:25 +0000 | |||
4 | @@ -608,8 +608,27 @@ | |||
5 | 608 | 608 | ||
6 | 609 | }} // namespace compiz::private_screen | 609 | }} // namespace compiz::private_screen |
7 | 610 | 610 | ||
8 | 611 | class FetchXEventInterface | ||
9 | 612 | { | ||
10 | 613 | public: | ||
11 | 614 | |||
12 | 615 | virtual ~FetchXEventInterface () {} | ||
13 | 616 | |||
14 | 617 | virtual bool getNextXEvent (XEvent &) = 0; | ||
15 | 618 | }; | ||
16 | 619 | |||
17 | 620 | class FetchEventInterface | ||
18 | 621 | { | ||
19 | 622 | public: | ||
20 | 623 | |||
21 | 624 | virtual ~FetchEventInterface () {} | ||
22 | 625 | virtual bool getNextEvent (XEvent &) = 0; | ||
23 | 626 | }; | ||
24 | 627 | |||
25 | 611 | class PrivateScreen : | 628 | class PrivateScreen : |
27 | 612 | public CoreOptions | 629 | public CoreOptions, |
28 | 630 | public FetchXEventInterface, | ||
29 | 631 | public FetchEventInterface | ||
30 | 613 | { | 632 | { |
31 | 614 | 633 | ||
32 | 615 | public: | 634 | public: |
33 | @@ -623,7 +642,8 @@ | |||
34 | 623 | 642 | ||
35 | 624 | bool setOption (const CompString &name, CompOption::Value &value); | 643 | bool setOption (const CompString &name, CompOption::Value &value); |
36 | 625 | 644 | ||
38 | 626 | std::list <XEvent> queueEvents (); | 645 | bool getNextEvent (XEvent &); |
39 | 646 | bool getNextXEvent (XEvent &); | ||
40 | 627 | void processEvents (); | 647 | void processEvents (); |
41 | 628 | 648 | ||
42 | 629 | bool triggerButtonPressBindings (CompOption::Vector &options, | 649 | bool triggerButtonPressBindings (CompOption::Vector &options, |
43 | 630 | 650 | ||
44 | === modified file 'src/privatestackdebugger.h' | |||
45 | --- src/privatestackdebugger.h 2011-09-29 03:29:41 +0000 | |||
46 | +++ src/privatestackdebugger.h 2012-06-05 09:07:25 +0000 | |||
47 | @@ -27,20 +27,23 @@ | |||
48 | 27 | * so that this can be come a truly standalone | 27 | * so that this can be come a truly standalone |
49 | 28 | * object */ | 28 | * object */ |
50 | 29 | #include <core/core.h> | 29 | #include <core/core.h> |
51 | 30 | #include <list> | ||
52 | 30 | 31 | ||
53 | 31 | #ifndef _COMPIZ_PRIVATESTACKDEBUGGER_H | 32 | #ifndef _COMPIZ_PRIVATESTACKDEBUGGER_H |
54 | 32 | #define _COMPIZ_PRIVATESTACKDEBUGGER_H | 33 | #define _COMPIZ_PRIVATESTACKDEBUGGER_H |
55 | 33 | 34 | ||
56 | 35 | class FetchXEventInterface; | ||
57 | 36 | |||
58 | 34 | class StackDebugger | 37 | class StackDebugger |
59 | 35 | { | 38 | { |
60 | 36 | public: | 39 | public: |
61 | 37 | 40 | ||
63 | 38 | typedef std::list<XEvent> eventList; | 41 | typedef std::vector<XEvent> eventList; |
64 | 39 | 42 | ||
66 | 40 | StackDebugger (Display *, Window, boost::function<eventList ()> evProc); | 43 | StackDebugger (Display *, Window, FetchXEventInterface *fetchXEvent); |
67 | 41 | ~StackDebugger (); | 44 | ~StackDebugger (); |
68 | 42 | 45 | ||
70 | 43 | eventList loadStack (CompWindowList &serverWindows, bool wait = false); | 46 | void loadStack (CompWindowList &serverWindows, bool wait = false); |
71 | 44 | void windowsChanged (bool change) { mWindowsChanged = change; }; | 47 | void windowsChanged (bool change) { mWindowsChanged = change; }; |
72 | 45 | void serverWindowsChanged (bool change) { mServerWindowsChanged = change; }; | 48 | void serverWindowsChanged (bool change) { mServerWindowsChanged = change; }; |
73 | 46 | bool windowsChanged () { return mWindowsChanged; } | 49 | bool windowsChanged () { return mWindowsChanged; } |
74 | @@ -54,6 +57,7 @@ | |||
75 | 54 | CompWindowList &serverWindows, | 57 | CompWindowList &serverWindows, |
76 | 55 | bool verbose = false); | 58 | bool verbose = false); |
77 | 56 | bool timedOut (); | 59 | bool timedOut (); |
78 | 60 | bool getNextEvent (XEvent &); | ||
79 | 57 | 61 | ||
80 | 58 | bool checkSanity (CompWindowList &serverWindows, bool verbose = false); | 62 | bool checkSanity (CompWindowList &serverWindows, bool verbose = false); |
81 | 59 | 63 | ||
82 | @@ -70,9 +74,10 @@ | |||
83 | 70 | bool mServerWindowsChanged; | 74 | bool mServerWindowsChanged; |
84 | 71 | Window mRoot; | 75 | Window mRoot; |
85 | 72 | Display *mDpy; | 76 | Display *mDpy; |
87 | 73 | boost::function<eventList ()> getEventsProc; | 77 | FetchXEventInterface *mFetchXEvent; |
88 | 74 | bool mTimeoutRequired; | 78 | bool mTimeoutRequired; |
89 | 75 | CompWindowList mLastServerWindows; | 79 | CompWindowList mLastServerWindows; |
90 | 80 | std::list <XEvent> mEvents; | ||
91 | 76 | }; | 81 | }; |
92 | 77 | 82 | ||
93 | 78 | #endif | 83 | #endif |
94 | 79 | 84 | ||
95 | === modified file 'src/screen.cpp' | |||
96 | --- src/screen.cpp 2012-05-25 07:37:42 +0000 | |||
97 | +++ src/screen.cpp 2012-06-05 09:07:25 +0000 | |||
98 | @@ -752,41 +752,48 @@ | |||
99 | 752 | return rv; | 752 | return rv; |
100 | 753 | } | 753 | } |
101 | 754 | 754 | ||
104 | 755 | std::list <XEvent> | 755 | bool |
105 | 756 | PrivateScreen::queueEvents () | 756 | PrivateScreen::getNextXEvent (XEvent &ev) |
106 | 757 | { | 757 | { |
108 | 758 | std::list <XEvent> events; | 758 | if (!XEventsQueued (dpy, QueuedAlready)) |
109 | 759 | return false; | ||
110 | 760 | XNextEvent (dpy, &ev); | ||
111 | 759 | 761 | ||
113 | 760 | while (XPending (dpy)) | 762 | /* Skip to the last MotionNotify |
114 | 763 | * event in this sequence */ | ||
115 | 764 | if (ev.type == MotionNotify) | ||
116 | 761 | { | 765 | { |
123 | 762 | XEvent event, peekEvent; | 766 | XEvent peekEvent; |
124 | 763 | XNextEvent (dpy, &event); | 767 | while (XPending (dpy)) |
119 | 764 | |||
120 | 765 | /* Skip to the last MotionNotify | ||
121 | 766 | * event in this sequence */ | ||
122 | 767 | if (event.type == MotionNotify) | ||
125 | 768 | { | 768 | { |
135 | 769 | while (XPending (dpy)) | 769 | XPeekEvent (dpy, &peekEvent); |
136 | 770 | { | 770 | |
137 | 771 | XPeekEvent (dpy, &peekEvent); | 771 | if (peekEvent.type != MotionNotify) |
138 | 772 | 772 | break; | |
139 | 773 | if (peekEvent.type != MotionNotify) | 773 | |
140 | 774 | break; | 774 | XNextEvent (dpy, &peekEvent); |
132 | 775 | |||
133 | 776 | XNextEvent (dpy, &event); | ||
134 | 777 | } | ||
141 | 778 | } | 775 | } |
147 | 779 | 776 | } | |
148 | 780 | events.push_back (event); | 777 | |
149 | 781 | } | 778 | return true; |
150 | 782 | 779 | } | |
151 | 783 | return events; | 780 | |
152 | 781 | bool | ||
153 | 782 | PrivateScreen::getNextEvent (XEvent &ev) | ||
154 | 783 | { | ||
155 | 784 | StackDebugger *dbg = StackDebugger::Default (); | ||
156 | 785 | |||
157 | 786 | if (StackDebugger::Default ()) | ||
158 | 787 | { | ||
159 | 788 | return dbg->getNextEvent (ev); | ||
160 | 789 | } | ||
161 | 790 | else | ||
162 | 791 | return getNextXEvent (ev); | ||
163 | 784 | } | 792 | } |
164 | 785 | 793 | ||
165 | 786 | void | 794 | void |
166 | 787 | PrivateScreen::processEvents () | 795 | PrivateScreen::processEvents () |
167 | 788 | { | 796 | { |
168 | 789 | std::list <XEvent> events; | ||
169 | 790 | StackDebugger *dbg = StackDebugger::Default (); | 797 | StackDebugger *dbg = StackDebugger::Default (); |
170 | 791 | 798 | ||
171 | 792 | if (pluginManager.isDirtyPluginList ()) | 799 | if (pluginManager.isDirtyPluginList ()) |
172 | @@ -801,14 +808,14 @@ | |||
173 | 801 | { | 808 | { |
174 | 802 | dbg->windowsChanged (false); | 809 | dbg->windowsChanged (false); |
175 | 803 | dbg->serverWindowsChanged (false); | 810 | dbg->serverWindowsChanged (false); |
177 | 804 | events = dbg->loadStack (windowManager.getServerWindows()); | 811 | dbg->loadStack (windowManager.getServerWindows()); |
178 | 805 | } | 812 | } |
179 | 806 | else | ||
180 | 807 | events = queueEvents (); | ||
181 | 808 | 813 | ||
182 | 809 | windowManager.invalidateServerWindows(); | 814 | windowManager.invalidateServerWindows(); |
183 | 810 | 815 | ||
185 | 811 | foreach (XEvent &event, events) | 816 | XEvent event; |
186 | 817 | |||
187 | 818 | while (getNextEvent (event)) | ||
188 | 812 | { | 819 | { |
189 | 813 | switch (event.type) { | 820 | switch (event.type) { |
190 | 814 | case ButtonPress: | 821 | case ButtonPress: |
191 | @@ -4792,7 +4799,7 @@ | |||
192 | 4792 | new StackDebugger ( | 4799 | new StackDebugger ( |
193 | 4793 | dpy (), | 4800 | dpy (), |
194 | 4794 | root (), | 4801 | root (), |
196 | 4795 | boost::bind (&PrivateScreen::queueEvents, &privateScreen))); | 4802 | &privateScreen)); |
197 | 4796 | } | 4803 | } |
198 | 4797 | 4804 | ||
199 | 4798 | return true; | 4805 | return true; |
200 | 4799 | 4806 | ||
201 | === modified file 'src/stackdebugger.cpp' | |||
202 | --- src/stackdebugger.cpp 2011-10-07 11:45:38 +0000 | |||
203 | +++ src/stackdebugger.cpp 2012-06-05 09:07:25 +0000 | |||
204 | @@ -24,6 +24,7 @@ | |||
205 | 24 | */ | 24 | */ |
206 | 25 | 25 | ||
207 | 26 | #include "privatestackdebugger.h" | 26 | #include "privatestackdebugger.h" |
208 | 27 | #include "privatescreen.h" | ||
209 | 27 | #include "privatewindow.h" | 28 | #include "privatewindow.h" |
210 | 28 | #include <poll.h> | 29 | #include <poll.h> |
211 | 29 | 30 | ||
212 | @@ -47,14 +48,14 @@ | |||
213 | 47 | gStackDebugger = dbg; | 48 | gStackDebugger = dbg; |
214 | 48 | } | 49 | } |
215 | 49 | 50 | ||
217 | 50 | StackDebugger::StackDebugger (Display *dpy, Window root, boost::function <eventList ()> evProc) : | 51 | StackDebugger::StackDebugger (Display *dpy, Window root, FetchXEventInterface *fetchXEvent) : |
218 | 51 | mServerNChildren (0), | 52 | mServerNChildren (0), |
219 | 52 | mServerChildren (NULL), | 53 | mServerChildren (NULL), |
220 | 53 | mWindowsChanged (false), | 54 | mWindowsChanged (false), |
221 | 54 | mServerWindowsChanged (false), | 55 | mServerWindowsChanged (false), |
222 | 55 | mRoot (root), | 56 | mRoot (root), |
223 | 56 | mDpy (dpy), | 57 | mDpy (dpy), |
225 | 57 | getEventsProc (evProc) | 58 | mFetchXEvent (fetchXEvent) |
226 | 58 | { | 59 | { |
227 | 59 | } | 60 | } |
228 | 60 | 61 | ||
229 | @@ -118,11 +119,23 @@ | |||
230 | 118 | mLastServerWindows.push_front (tl); | 119 | mLastServerWindows.push_front (tl); |
231 | 119 | } | 120 | } |
232 | 120 | 121 | ||
234 | 121 | StackDebugger::eventList | 122 | bool |
235 | 123 | StackDebugger::getNextEvent (XEvent &ev) | ||
236 | 124 | { | ||
237 | 125 | if (mEvents.empty ()) | ||
238 | 126 | return false; | ||
239 | 127 | |||
240 | 128 | ev = mEvents.front (); | ||
241 | 129 | |||
242 | 130 | mEvents.pop_front (); | ||
243 | 131 | |||
244 | 132 | return true; | ||
245 | 133 | } | ||
246 | 134 | |||
247 | 135 | void | ||
248 | 122 | StackDebugger::loadStack (CompWindowList &serverWindows, bool wait) | 136 | StackDebugger::loadStack (CompWindowList &serverWindows, bool wait) |
249 | 123 | { | 137 | { |
250 | 124 | Window rootRet, parentRet; | 138 | Window rootRet, parentRet; |
251 | 125 | eventList events; | ||
252 | 126 | 139 | ||
253 | 127 | if (mServerChildren) | 140 | if (mServerChildren) |
254 | 128 | XFree (mServerChildren); | 141 | XFree (mServerChildren); |
255 | @@ -132,7 +145,16 @@ | |||
256 | 132 | XQueryTree (mDpy, mRoot, &rootRet, &parentRet, | 145 | XQueryTree (mDpy, mRoot, &rootRet, &parentRet, |
257 | 133 | &mServerChildren, &mServerNChildren); | 146 | &mServerChildren, &mServerNChildren); |
258 | 134 | 147 | ||
260 | 135 | events = getEventsProc (); | 148 | unsigned int n = XEventsQueued (mDpy, QueuedAfterFlush); |
261 | 149 | mEvents.clear (); | ||
262 | 150 | mEvents.resize (n); | ||
263 | 151 | std::list <XEvent>::iterator it = mEvents.begin (); | ||
264 | 152 | |||
265 | 153 | while (it != mEvents.end ()) | ||
266 | 154 | { | ||
267 | 155 | mFetchXEvent->getNextXEvent ((*it)); | ||
268 | 156 | it++; | ||
269 | 157 | } | ||
270 | 136 | 158 | ||
271 | 137 | XSync (mDpy, FALSE); | 159 | XSync (mDpy, FALSE); |
272 | 138 | 160 | ||
273 | @@ -145,7 +167,6 @@ | |||
274 | 145 | 167 | ||
275 | 146 | if (mServerNChildren != serverWindows.size () && wait) | 168 | if (mServerNChildren != serverWindows.size () && wait) |
276 | 147 | { | 169 | { |
277 | 148 | eventList moreEvents; | ||
278 | 149 | struct pollfd pfd; | 170 | struct pollfd pfd; |
279 | 150 | 171 | ||
280 | 151 | pfd.events = POLLIN; | 172 | pfd.events = POLLIN; |
281 | @@ -154,10 +175,10 @@ | |||
282 | 154 | 175 | ||
283 | 155 | poll (&pfd, 1, 300); | 176 | poll (&pfd, 1, 300); |
284 | 156 | 177 | ||
286 | 157 | moreEvents = getEventsProc (); | 178 | XEvent e; |
287 | 158 | 179 | ||
290 | 159 | foreach (XEvent e, moreEvents) | 180 | while (mFetchXEvent->getNextXEvent (e)) |
291 | 160 | events.push_back (e); | 181 | mEvents.push_back (e); |
292 | 161 | 182 | ||
293 | 162 | mTimeoutRequired = true; | 183 | mTimeoutRequired = true; |
294 | 163 | } | 184 | } |
295 | @@ -166,8 +187,6 @@ | |||
296 | 166 | 187 | ||
297 | 167 | XUngrabServer (mDpy); | 188 | XUngrabServer (mDpy); |
298 | 168 | XSync (mDpy, FALSE); | 189 | XSync (mDpy, FALSE); |
299 | 169 | |||
300 | 170 | return events; | ||
301 | 171 | } | 190 | } |
302 | 172 | 191 | ||
303 | 173 | void | 192 | void |
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.