1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
|
=======================================================
toro: Synchronization primitives for Tornado coroutines
=======================================================
.. module:: toro
.. image:: _static/toro.png
:align: center
.. getting the caption italicized with a hyperlink in it requires some RST hackage
*Toro logo by* |musho|_
.. _musho: http://whimsyload.com
.. |musho| replace:: *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.
.. _gen: http://www.tornadoweb.org/en/stable/gen.html
.. _the-wait-notify-pattern:
The Wait / Notify Pattern
=========================
Toro's :ref:`primitives <primitives>` follow a "wait / notify pattern": one
coroutine waits to be notified by another. Let's take :class:`Condition` as an
example:
.. doctest::
>>> 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
:class:`Timeout` exception is raised.
.. _the-get-put-pattern:
The Get / Put Pattern
=====================
:class:`Queue` and its subclasses support methods :meth:`Queue.get` and
:meth:`Queue.put`. These methods are each both a wait-method **and** a
notify-method:
* :meth:`Queue.get` waits until there is an available item in the queue, and
may notify a coroutine waiting to put an item.
* :meth:`Queue.put` waits until the queue has a free slot, and may notify a
coroutine waiting to get an item.
:meth:`Queue.get` and :meth:`Queue.put` accept deadlines and raise
:exc:`Timeout` if the deadline passes.
See the :doc:`examples/producer_consumer_example`.
Additionally, :class:`JoinableQueue` supports
the wait-method :meth:`JoinableQueue.join`
and the notify-method :meth:`JoinableQueue.task_done`.
Contents
========
.. toctree::
examples/index
classes
faq
changelog
Source
======
Is on GitHub: https://github.com/ajdavis/toro
Bug Reports and Feature Requests
================================
Also on GitHub: https://github.com/ajdavis/toro/issues
Indices and tables
==================
* :ref:`genindex`
* :ref:`search`
|