Changes in Version 1.0.1

Bug fix in RWLock: when max_readers > 1 release_read() must release one reader in case acquire_read() was called at least once:

def coro():
    lock = toro.RWLock(max_readers=10)
    assert not lock.locked()

    yield lock.acquire_read()

But, in old version release_read() raises RuntimeException if a lock in unlocked state, even if acquire_read() was already called several times.

Patch by Alexander Gridnev.

Changes in Version 1.0

This is the final release of Toro. Its features are merged into Tornado 4.2. Further development of locks and queues for Tornado coroutines will continue in Tornado.

For more information on the end of Toro, read my article. The Tornado changelog has comprehensive instructions on porting from Toro’s locks and queues to Tornado 4.2 locks and queues.

Toro 1.0 has one new feature, an RWLock contributed by Alexander Gridnev. RWLock has not been merged into Tornado.

Changes in Version 0.8

Don’t depend on “nose” for tests. Improve test quality and coverage. Delete unused method in internal _TimeoutFuture class.

Changes in Version 0.7

Bug fix in Semaphore: after a call to acquire(), wait() should block until another coroutine calls release():

def coro():
    sem = toro.Semaphore(1)
    assert not sem.locked()

    # A semaphore with initial value of 1 can be acquired once,
    # then it's locked.
    assert sem.locked()

    # Wait for another coroutine to release the semaphore.
    yield sem.wait()

However, there was a bug and wait() returned immediately if the semaphore had ever been unlocked. I’m grateful to “abing” on GitHub for noticing the bug and contributing a fix.

Changes in Version 0.6

Queue now supports floating-point numbers for maxsize. A maxsize of 1.3 is now equivalent to a maxsize of 2. Before, it had been treated as infinite.

This feature is not intended to be useful, but to maintain an API similar to asyncio and the standard library Queue.

Changes in Version 0.5

Rewritten for Tornado 3.

Dropped support for Tornado 2 and Python 2.5.

Added support for Tornado 3’s Futures:
  • All Toro methods that took callbacks no longer take callbacks but return Futures.

  • All Toro methods that took optional callbacks have been split into two methods: one that returns a Future, and a “nowait” method that returns immediately or raises an exception.

  • All Toro methods that return Futures accept an optional deadline parameter. Whereas before each Toro class had different behavior after a timeout, all now return a Future that raises toro.Timeout after the deadline.

Toro’s API aims to be very similar to Tulip, since Tulip will evolve into the Python 3.4 standard library:

  • Toro’s API has been updated to closely match the locks and queues in Tulip.
  • The requirement has been dropped that a coroutine that calls put() resumes only after any coroutine it awakens. Similar for get(). The order in which the two coroutines resume is now unspecified.
  • A Queue with maxsize 0 (the default) is no longer a “channel” as in Gevent but is an unbounded Queue as in Tulip and the standard library. None is no longer a valid maxsize.
  • The initial argument to Queue() was removed.
  • maxsize can no longer be changed after a Queue is created.

The chief differences between Toro and Tulip are that Toro uses yield instead of yield from, and that Toro uses absolute deadlines instead of relative timeouts. Additionally, Toro’s Lock and Semaphore aren’t context managers (they can’t be used with a with statement); instead, the Futures returned from acquire() and acquire() are context managers.

Changes in Version 0.3

Increasing the maxsize of a Queue unblocks callbacks waiting on put().

Travis integration.

Changes in Version 0.2

Python 3 support.

Bugfix in Semaphore: release() shouldn’t wake callbacks registered with wait() unless no one is waiting for acquire().

Fixed error in the “Wait-Notify” table.

Added Lock example - graceful shutdown to docs.

Changes in Version 0.1.1

Fixed the docs to render correctly in PyPI.

Version 0.1

First release.