diff options
author | Zac Medico <zmedico@gentoo.org> | 2016-08-20 14:59:55 -0700 |
---|---|---|
committer | Zac Medico <zmedico@gentoo.org> | 2016-08-23 09:33:47 -0700 |
commit | 995f0f983386e2a82dbce65d4366ee7f58f59138 (patch) | |
tree | 704c82fbbbbb90d81f31b1424e28ebccbc7b8889 | |
parent | Scheduler._terminate_tasks: purge _running_tasks (bug 425554) (diff) | |
download | portage-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.py | 23 | ||||
-rw-r--r-- | pym/portage/util/_eventloop/EventLoop.py | 17 |
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(): |