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.
(Note that these primitives and queues are not actually thread-safe and cannot be used in place of those from the standard library–they are meant to coordinate Tornado coroutines in single-threaded apps, not to protect shared objects in multithreaded apps.)
>>> 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.
See the Producer-consumer example.