diff options
author | Victor Stinner <victor.stinner@gmail.com> | 2014-11-21 04:26:35 +0100 |
---|---|---|
committer | Victor Stinner <victor.stinner@gmail.com> | 2014-11-21 04:26:35 +0100 |
commit | ec500753679a69831d22c538d6850a68eeedfbc5 (patch) | |
tree | f72ba0494f138083300364045f699fd370a00d0f | |
parent | ea24997de038d20c1b98496cc8abbdc595d460ca (diff) | |
download | aioeventlet-ec500753679a69831d22c538d6850a68eeedfbc5.tar.gz |
Add the link_future() function
-rw-r--r-- | README | 27 | ||||
-rw-r--r-- | aiogreen.py | 55 | ||||
-rw-r--r-- | tests/test_eventlet.py | 26 |
3 files changed, 68 insertions, 40 deletions
@@ -75,7 +75,7 @@ Hello World:: Use a greenthread in a coroutine -------------------------------- -Use the ``wrap_greenthread()`` function to wrap a greenthread into a Future +Use the ``wrap_greenthread(gt)`` function to wrap a greenthread into a Future object. The Future object waits for the completion of a greenthread. Example with asyncio:: @@ -96,11 +96,32 @@ logged to sys.stderr by eventlet, even if it is correctly copied to the Future object. +Use a coroutine in a greenthread +-------------------------------- + +Use the ``link_future(future)`` function to wait for a future or a task from a +greenthread. The function returns the result or raise the exception of the +future. + +Example with asyncio:: + + def coro_slow_sum(x, y): + yield from asyncio.sleep(1.0) + return x + y + + def green_sum(): + task = asyncio.async(coro_slow_sum(1, 2)) + value = aiogreen.link_future(task) + return value + + API === Functions which are not in asyncio: +* ``link_future(future)``: wait for a future (or a task) from a greenthread, + return the result or raise the exception of the future * ``wrap_greenthread(gt)``: wrap a greenthread into a Future object @@ -171,7 +192,9 @@ only call the callback once per loop iteration. Changes: -* Add the ``wrap_greenthread()`` function to wrap a greenthread into a Future +* Add the ``link_future(future)`` function: wait for a future from a + greenthread. +* Add the ``wrap_greenthread(gt)`` function: wrap a greenthread into a Future * Support also eventlet 0.14, not only eventlet 0.15 or newer * Support eventlet with monkey-patching * Rewrite the code handling file descriptors to ensure that the listener is diff --git a/aiogreen.py b/aiogreen.py index e7558c3..9ec1912 100644 --- a/aiogreen.py +++ b/aiogreen.py @@ -68,24 +68,6 @@ class _TpoolExecutor(object): self._tpool.killall() -def wrap_greenthread(gt, loop=None): - """Wrap an eventlet greenthread into a Future object.""" - if loop is None: - loop = asyncio.get_event_loop() - fut = asyncio.Future(loop=loop) - - def copy_result(gt): - try: - value = gt.wait() - except Exception as exc: - loop.call_soon(fut.set_exception, exc) - else: - loop.call_soon(fut.set_result, value) - - gt.link(copy_result) - return fut - - class _Selector(asyncio.selectors._BaseSelectorImpl): def __init__(self, loop, hub): super(_Selector, self).__init__() @@ -240,3 +222,40 @@ class EventLoop(asyncio.SelectorEventLoop): class EventLoopPolicy(asyncio.DefaultEventLoopPolicy): _loop_factory = EventLoop + + +def wrap_greenthread(gt, loop=None): + """Wrap an eventlet greenthread into a Future object.""" + if loop is None: + loop = asyncio.get_event_loop() + fut = asyncio.Future(loop=loop) + + def copy_result(gt): + try: + value = gt.wait() + except Exception as exc: + loop.call_soon(fut.set_exception, exc) + else: + loop.call_soon(fut.set_result, value) + + gt.link(copy_result) + return fut + + +def link_future(future): + """Wait for a future. + + Wait for a future or a task from a greenthread. + Return the result or raise the exception of the future. + """ + event = eventlet.event.Event() + def done(fut): + try: + result = fut.result() + except Exception as exc: + event.send_exception(exc) + else: + event.send(result) + + future.add_done_callback(done) + return event.wait() diff --git a/tests/test_eventlet.py b/tests/test_eventlet.py index 4ff9e8c..c702b86 100644 --- a/tests/test_eventlet.py +++ b/tests/test_eventlet.py @@ -131,33 +131,19 @@ except ImportError: raise ValueError("error") -def link_task(task): - event = eventlet.event.Event() - def done(fut): - try: - result = fut.result() - except Exception as exc: - # FIXME - event.send_exception(exc) - else: - event.send(result) - - task.add_done_callback(done) - return event.wait() - -def greenthread_link_task(result, loop): +def greenthread_link_future(result, loop): try: t1 = asyncio.async(coro_slow_append(result, 1, 0.2), loop=loop) - value = link_task(t1) + value = aiogreen.link_future(t1) result.append(value) t2 = asyncio.async(coro_slow_append(result, 2, 0.1), loop=loop) - value = link_task(t2) + value = aiogreen.link_future(t2) result.append(value) t3 = asyncio.async(coro_slow_error(0.001), loop=loop) try: - value = link_task(t3) + value = aiogreen.link_future(t3) except ValueError as exc: result.append(str(exc)) @@ -216,10 +202,10 @@ class EventletTests(tests.TestCase): result = self.loop.run_until_complete(coro_wrap_greenthread()) self.assertEqual(result, [1, 10, 2, 20, 'error', 4]) - def test_greenthread_link_task(self): + def test_greenthread_link_future(self): result = [] self.loop.call_soon(eventlet.spawn, - greenthread_link_task, result, self.loop) + greenthread_link_future, result, self.loop) self.loop.run_forever() self.assertEqual(result, [1, 10, 2, 20, 'error', 4]) |