aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZac Medico <zmedico@gentoo.org>2016-08-20 14:59:55 -0700
committerZac Medico <zmedico@gentoo.org>2016-08-23 09:33:47 -0700
commit995f0f983386e2a82dbce65d4366ee7f58f59138 (patch)
tree704c82fbbbbb90d81f31b1424e28ebccbc7b8889
parentScheduler._terminate_tasks: purge _running_tasks (bug 425554) (diff)
downloadportage-995f0f98.tar.gz
portage-995f0f98.tar.bz2
portage-995f0f98.zip
EventLoop: add run_until_complete method (bug 591760)
This emulates the asyncio.AbstractEventLoop.run_until_complete(future) interface, which will make it possible to reduce latency in situations where it is desirable for a loop to exit at the earliest opportunity. The most tangible benefit of this change is that it provides a migration path to asyncio, which will allow us to rely on a standard library instead of our own internal event loop implementation. In order to migrate to asyncio, more work is planned: * Migrate all internal use of the EventLoop.iteration method to the new run_until_complete(future) method, and remove the EventLoop.iteration method (or make it private as long as it's needed to implement run_until_complete for older python versions). * Implement all EventLoop methods using asyncio.AbstractEventLoop methods (but keep existing implementations for use with older python). X-Gentoo-bug: 591760 X-Gentoo-bug-url: https://bugs.gentoo.org/show_bug.cgi?id=591760 Acked-by: Alexander Berntsen <bernalex@gentoo.org>
-rw-r--r--pym/portage/tests/ebuild/test_ipc_daemon.py23
-rw-r--r--pym/portage/util/_eventloop/EventLoop.py17
2 files changed, 30 insertions, 10 deletions
diff --git a/pym/portage/tests/ebuild/test_ipc_daemon.py b/pym/portage/tests/ebuild/test_ipc_daemon.py
index 835f51f80..68f139aa4 100644
--- a/pym/portage/tests/ebuild/test_ipc_daemon.py
+++ b/pym/portage/tests/ebuild/test_ipc_daemon.py
@@ -1,4 +1,4 @@
-# Copyright 2010-2015 Gentoo Foundation
+# Copyright 2010-2016 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
import tempfile
@@ -16,6 +16,7 @@ from portage.util import ensure_dirs
from portage.util._async.ForkProcess import ForkProcess
from portage.util._async.TaskScheduler import TaskScheduler
from portage.util._eventloop.global_event_loop import global_event_loop
+from portage.util.futures.futures import Future
from _emerge.SpawnProcess import SpawnProcess
from _emerge.EbuildBuildDir import EbuildBuildDir
from _emerge.EbuildIpcDaemon import EbuildIpcDaemon
@@ -140,19 +141,23 @@ class IpcDaemonTestCase(TestCase):
build_dir.unlock()
shutil.rmtree(tmpdir)
- def _timeout_callback(self):
- self._timed_out = True
+ def _timeout_callback(self, task_scheduler):
+ task_scheduler.cancel()
+ self._exit_callback(task_scheduler)
+
+ def _exit_callback(self, task_scheduler):
+ if not self._run_done.done():
+ self._run_done.set_result(True)
def _run(self, event_loop, task_scheduler, timeout):
- self._timed_out = False
- timeout_id = event_loop.timeout_add(timeout, self._timeout_callback)
+ self._run_done = Future()
+ timeout_id = event_loop.timeout_add(timeout,
+ self._timeout_callback, task_scheduler)
+ task_scheduler.addExitListener(self._exit_callback)
try:
task_scheduler.start()
- while not self._timed_out and task_scheduler.poll() is None:
- event_loop.iteration()
- if self._timed_out:
- task_scheduler.cancel()
+ event_loop.run_until_complete(self._run_done)
task_scheduler.wait()
finally:
event_loop.source_remove(timeout_id)
diff --git a/pym/portage/util/_eventloop/EventLoop.py b/pym/portage/util/_eventloop/EventLoop.py
index 809540023..8f13de377 100644
--- a/pym/portage/util/_eventloop/EventLoop.py
+++ b/pym/portage/util/_eventloop/EventLoop.py
@@ -1,4 +1,4 @@
-# Copyright 1999-2014 Gentoo Foundation
+# Copyright 1999-2016 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
from __future__ import division
@@ -577,6 +577,21 @@ class EventLoop(object):
del self._poll_event_handlers[f]
return True
+ def run_until_complete(self, future):
+ """
+ Run until the Future is done.
+
+ @type future: asyncio.Future
+ @param future: a Future to wait for
+ @rtype: object
+ @return: the Future's result
+ @raise: the Future's exception
+ """
+ while not future.done():
+ self.iteration()
+
+ return future.result()
+
_can_poll_device = None
def can_poll_device():