toro: Synchronization primitives for Tornado coroutines¶
Toro logo by Musho Rodney Alan Greenblat
With Tornado’s gen module, you can turn Python generators into full-featured coroutines, but coordination among these coroutines is difficult without mutexes, semaphores, and queues.
Toro provides to Tornado coroutines a set of locking primitives and queues analogous to those that Gevent provides to Greenlets, or that the standard library provides to threads.
Important
Toro is completed and deprecated; its features have been merged into Tornado. Development of locks and queues for Tornado coroutines continues in Tornado itself.
The Wait / Notify Pattern¶
Toro’s primitives follow a “wait / notify pattern”: one
coroutine waits to be notified by another. Let’s take Condition
as an
example:
>>> import toro
>>> from tornado import ioloop, gen
>>> loop = ioloop.IOLoop.current()
>>> condition = toro.Condition()
>>> @gen.coroutine
... def waiter():
... print "I'll wait right here"
... yield condition.wait() # Yield a Future
... print "I'm done waiting"
...
>>> @gen.coroutine
... def notifier():
... print "About to notify"
... condition.notify()
... print "Done notifying"
...
>>> @gen.coroutine
... def runner():
... # Yield two Futures; wait for waiter() and notifier() to finish
... yield [waiter(), notifier()]
... loop.stop()
...
>>> future = runner(); loop.start()
I'll wait right here
About to notify
Done notifying
I'm done waiting
Wait-methods take an optional deadline
argument, which is either an
absolute timestamp:
loop = ioloop.IOLoop.current()
# Wait up to 1 second for a notification
yield condition.wait(deadline=loop.time() + 1)
...or a datetime.timedelta
for a deadline relative to the current time:
# Wait up to 1 second
yield condition.wait(deadline=datetime.timedelta(seconds=1))
If there’s no notification before the deadline, the Toro-specific
Timeout
exception is raised.
The Get / Put Pattern¶
Queue
and its subclasses support methods Queue.get()
and
Queue.put()
. These methods are each both a wait-method and a
notify-method:
Queue.get()
waits until there is an available item in the queue, and may notify a coroutine waiting to put an item.Queue.put()
waits until the queue has a free slot, and may notify a coroutine waiting to get an item.
Queue.get()
and Queue.put()
accept deadlines and raise
Timeout
if the deadline passes.
See the Producer-consumer example.
Additionally, JoinableQueue
supports
the wait-method JoinableQueue.join()
and the notify-method JoinableQueue.task_done()
.
Source¶
Is on GitHub: https://github.com/ajdavis/toro
Bug Reports and Feature Requests¶
Also on GitHub: https://github.com/ajdavis/toro/issues