1 |
commit: 46fca763f7d08171d5c08c1c5fd1f40ce340ba56 |
2 |
Author: Zac Medico <zmedico <AT> gentoo <DOT> org> |
3 |
AuthorDate: Mon Dec 31 03:16:11 2012 +0000 |
4 |
Commit: Zac Medico <zmedico <AT> gentoo <DOT> org> |
5 |
CommitDate: Mon Dec 31 03:16:11 2012 +0000 |
6 |
URL: http://git.overlays.gentoo.org/gitweb/?p=proj/portage.git;a=commit;h=46fca763 |
7 |
|
8 |
EventLoop.iteration: no IO blocking if possible |
9 |
|
10 |
Avoid blocking for IO if there are any timeout or idle callback events |
11 |
available to process. This will prevent starvation of the idle |
12 |
callbacks, which are much more common since commit |
13 |
a3100be184ba1cac2f672f0a1cadcf01690c6d3f. We don't want these idle |
14 |
callbacks to be delayed by long periods of IO blocking. |
15 |
|
16 |
--- |
17 |
pym/portage/util/_eventloop/EventLoop.py | 22 ++++++++++++++++++---- |
18 |
1 files changed, 18 insertions(+), 4 deletions(-) |
19 |
|
20 |
diff --git a/pym/portage/util/_eventloop/EventLoop.py b/pym/portage/util/_eventloop/EventLoop.py |
21 |
index b77e819..d2d4963 100644 |
22 |
--- a/pym/portage/util/_eventloop/EventLoop.py |
23 |
+++ b/pym/portage/util/_eventloop/EventLoop.py |
24 |
@@ -182,11 +182,13 @@ class EventLoop(object): |
25 |
event_queue = self._poll_event_queue |
26 |
event_handlers = self._poll_event_handlers |
27 |
events_handled = 0 |
28 |
+ timeouts_checked = False |
29 |
|
30 |
if not event_handlers: |
31 |
with self._thread_condition: |
32 |
if self._run_timeouts(): |
33 |
events_handled += 1 |
34 |
+ timeouts_checked = True |
35 |
if not event_handlers and not events_handled and may_block: |
36 |
# Block so that we don't waste cpu time by looping too |
37 |
# quickly. This makes EventLoop useful for code that needs |
38 |
@@ -205,6 +207,7 @@ class EventLoop(object): |
39 |
self._thread_condition.wait(wait_timeout) |
40 |
if self._run_timeouts(): |
41 |
events_handled += 1 |
42 |
+ timeouts_checked = True |
43 |
|
44 |
# If any timeouts have executed, then return immediately, |
45 |
# in order to minimize latency in termination of iteration |
46 |
@@ -216,6 +219,17 @@ class EventLoop(object): |
47 |
|
48 |
if may_block: |
49 |
timeout = self._get_poll_timeout() |
50 |
+ |
51 |
+ # Avoid blocking for IO if there are any timeout |
52 |
+ # or idle callbacks available to process. |
53 |
+ if timeout != 0 and not timeouts_checked: |
54 |
+ if self._run_timeouts(): |
55 |
+ events_handled += 1 |
56 |
+ timeouts_checked = True |
57 |
+ if events_handled: |
58 |
+ # Minimize latency for loops controlled |
59 |
+ # by timeout or idle callback events. |
60 |
+ timeout = 0 |
61 |
else: |
62 |
timeout = 0 |
63 |
|
64 |
@@ -235,10 +249,10 @@ class EventLoop(object): |
65 |
if not x.callback(f, event, *x.args): |
66 |
self.source_remove(x.source_id) |
67 |
|
68 |
- # Run timeouts last, in order to minimize latency in |
69 |
- # termination of iteration loops that they may control. |
70 |
- if self._run_timeouts(): |
71 |
- events_handled += 1 |
72 |
+ if not timeouts_checked: |
73 |
+ if self._run_timeouts(): |
74 |
+ events_handled += 1 |
75 |
+ timeouts_checked = True |
76 |
|
77 |
return bool(events_handled) |