summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVictor Stinner <victor.stinner@gmail.com>2014-11-21 04:26:35 +0100
committerVictor Stinner <victor.stinner@gmail.com>2014-11-21 04:26:35 +0100
commitec500753679a69831d22c538d6850a68eeedfbc5 (patch)
treef72ba0494f138083300364045f699fd370a00d0f
parentea24997de038d20c1b98496cc8abbdc595d460ca (diff)
downloadaioeventlet-ec500753679a69831d22c538d6850a68eeedfbc5.tar.gz
Add the link_future() function
-rw-r--r--README27
-rw-r--r--aiogreen.py55
-rw-r--r--tests/test_eventlet.py26
3 files changed, 68 insertions, 40 deletions
diff --git a/README b/README
index 5d0dc60..400d02c 100644
--- a/README
+++ b/README
@@ -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])