added spawn_link function (with tests)
This commit is contained in:
@@ -236,6 +236,35 @@ class event(object):
|
|||||||
# the arguments and the same as for greenlet.throw
|
# the arguments and the same as for greenlet.throw
|
||||||
return self.send(None, args)
|
return self.send(None, args)
|
||||||
|
|
||||||
|
|
||||||
|
class async_result(object):
|
||||||
|
|
||||||
|
def __init__(self, greenlet, event):
|
||||||
|
self.greenlet = greenlet
|
||||||
|
self.event = event
|
||||||
|
|
||||||
|
def wait(self):
|
||||||
|
return self.event.wait()
|
||||||
|
|
||||||
|
def kill(self):
|
||||||
|
return api.kill(self.greenlet)
|
||||||
|
|
||||||
|
def _wrap_result_in_event(event, func, *args, **kwargs):
|
||||||
|
try:
|
||||||
|
result = func(*args, **kwargs)
|
||||||
|
except api.GreenletExit, ex:
|
||||||
|
event.send(ex)
|
||||||
|
except:
|
||||||
|
event.send_exception(*sys.exc_info())
|
||||||
|
else:
|
||||||
|
event.send(result)
|
||||||
|
|
||||||
|
def spawn_link(func, *args, **kwargs):
|
||||||
|
result = event()
|
||||||
|
g = api.spawn(_wrap_result_in_event, result, func, *args, **kwargs)
|
||||||
|
return async_result(g, result)
|
||||||
|
|
||||||
|
|
||||||
class semaphore(object):
|
class semaphore(object):
|
||||||
"""Classic semaphore implemented with a counter and an event.
|
"""Classic semaphore implemented with a counter and an event.
|
||||||
Optionally initialize with a resource count, then acquire() and release()
|
Optionally initialize with a resource count, then acquire() and release()
|
||||||
|
@@ -1,8 +1,9 @@
|
|||||||
import unittest
|
import unittest
|
||||||
from eventlet.coros import event
|
import sys
|
||||||
from eventlet.api import spawn, sleep
|
from eventlet.coros import event, spawn_link
|
||||||
|
from eventlet.api import spawn, sleep, GreenletExit
|
||||||
|
|
||||||
class Test(unittest.TestCase):
|
class TestEvent(unittest.TestCase):
|
||||||
|
|
||||||
def test_send_exc(self):
|
def test_send_exc(self):
|
||||||
log = []
|
log = []
|
||||||
@@ -20,6 +21,40 @@ class Test(unittest.TestCase):
|
|||||||
sleep(0)
|
sleep(0)
|
||||||
assert log == [('catched', 'Exception')], log
|
assert log == [('catched', 'Exception')], log
|
||||||
|
|
||||||
|
|
||||||
|
class TestSpawnLink(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_simple_return(self):
|
||||||
|
res = spawn_link(lambda: 25).wait()
|
||||||
|
assert res==25, res
|
||||||
|
|
||||||
|
def test_exception(self):
|
||||||
|
try:
|
||||||
|
spawn_link(sys.exit, 'bye').wait()
|
||||||
|
except SystemExit, ex:
|
||||||
|
assert ex.args == ('bye', )
|
||||||
|
else:
|
||||||
|
assert False, "Shouldn't get there"
|
||||||
|
|
||||||
|
def _test_kill(self, sync):
|
||||||
|
def func():
|
||||||
|
sleep(0.1)
|
||||||
|
return 101
|
||||||
|
res = spawn_link(func)
|
||||||
|
if sync:
|
||||||
|
res.kill()
|
||||||
|
else:
|
||||||
|
spawn(res.kill)
|
||||||
|
wait_result = res.wait()
|
||||||
|
assert isinstance(wait_result, GreenletExit), `wait_result`
|
||||||
|
|
||||||
|
def test_kill_sync(self):
|
||||||
|
return self._test_kill(True)
|
||||||
|
|
||||||
|
def test_kill_async(self):
|
||||||
|
return self._test_kill(False)
|
||||||
|
|
||||||
|
|
||||||
if __name__=='__main__':
|
if __name__=='__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user