Skip to content

Commit

Permalink
EventLoop: add run_until_complete method (bug 591760)
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
zmedico committed Aug 23, 2016
1 parent d54a795 commit 995f0f9
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 10 deletions.
23 changes: 14 additions & 9 deletions 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
Expand All @@ -16,6 +16,7 @@
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
Expand Down Expand Up @@ -140,19 +141,23 @@ def exit_command_callback():
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)
17 changes: 16 additions & 1 deletion 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
Expand Down Expand Up @@ -577,6 +577,21 @@ def source_remove(self, reg_id):
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():
Expand Down

0 comments on commit 995f0f9

Please sign in to comment.