summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZac Medico <zmedico@gentoo.org>2012-12-30 19:16:11 -0800
committerZac Medico <zmedico@gentoo.org>2012-12-30 19:16:11 -0800
commit46fca763f7d08171d5c08c1c5fd1f40ce340ba56 (patch)
tree8106bd838ef715e48aaa2e105f78030aad36aa6b
parenta3100be184ba1cac2f672f0a1cadcf01690c6d3f (diff)
downloadportage-46fca763f7d08171d5c08c1c5fd1f40ce340ba56.tar.gz
portage-46fca763f7d08171d5c08c1c5fd1f40ce340ba56.tar.bz2
portage-46fca763f7d08171d5c08c1c5fd1f40ce340ba56.zip
EventLoop.iteration: no IO blocking if possible
Avoid blocking for IO if there are any timeout or idle callback events available to process. This will prevent starvation of the idle callbacks, which are much more common since commit a3100be184ba1cac2f672f0a1cadcf01690c6d3f. We don't want these idle callbacks to be delayed by long periods of IO blocking.
-rw-r--r--pym/portage/util/_eventloop/EventLoop.py22
1 files changed, 18 insertions, 4 deletions
diff --git a/pym/portage/util/_eventloop/EventLoop.py b/pym/portage/util/_eventloop/EventLoop.py
index b77e8191b..d2d49636d 100644
--- a/pym/portage/util/_eventloop/EventLoop.py
+++ b/pym/portage/util/_eventloop/EventLoop.py
@@ -182,11 +182,13 @@ class EventLoop(object):
event_queue = self._poll_event_queue
event_handlers = self._poll_event_handlers
events_handled = 0
+ timeouts_checked = False
if not event_handlers:
with self._thread_condition:
if self._run_timeouts():
events_handled += 1
+ timeouts_checked = True
if not event_handlers and not events_handled and may_block:
# Block so that we don't waste cpu time by looping too
# quickly. This makes EventLoop useful for code that needs
@@ -205,6 +207,7 @@ class EventLoop(object):
self._thread_condition.wait(wait_timeout)
if self._run_timeouts():
events_handled += 1
+ timeouts_checked = True
# If any timeouts have executed, then return immediately,
# in order to minimize latency in termination of iteration
@@ -216,6 +219,17 @@ class EventLoop(object):
if may_block:
timeout = self._get_poll_timeout()
+
+ # Avoid blocking for IO if there are any timeout
+ # or idle callbacks available to process.
+ if timeout != 0 and not timeouts_checked:
+ if self._run_timeouts():
+ events_handled += 1
+ timeouts_checked = True
+ if events_handled:
+ # Minimize latency for loops controlled
+ # by timeout or idle callback events.
+ timeout = 0
else:
timeout = 0
@@ -235,10 +249,10 @@ class EventLoop(object):
if not x.callback(f, event, *x.args):
self.source_remove(x.source_id)
- # Run timeouts last, in order to minimize latency in
- # termination of iteration loops that they may control.
- if self._run_timeouts():
- events_handled += 1
+ if not timeouts_checked:
+ if self._run_timeouts():
+ events_handled += 1
+ timeouts_checked = True
return bool(events_handled)