import collections
-from tornado import ioloop
+from tornado import gen, ioloop
from tornado.concurrent import Future
self._waiters = collections.deque(
w for w in self._waiters if not w.done())
-_true_future = Future()
-_true_future.set_result(True)
-
class Event(object):
"""An event blocks coroutines until its internal flag is set to True.
Similar to `threading.Event`.
"""
def __init__(self):
- self._condition = Condition()
- self._flag = False
+ self._future = Future()
def __str__(self):
return '<%s %s>' % (
- self.__class__.__name__, 'set' if self._flag else 'clear')
+ self.__class__.__name__, 'set' if self.is_set() else 'clear')
def is_set(self):
"""Return ``True`` if the internal flag is true."""
- return self._flag
+ return self._future.done()
def set(self):
"""Set the internal flag to ``True``. All waiters are awakened.
Calling `.wait` once the flag is set will not block.
"""
- self._flag = True
- self._condition.notify_all()
+ if not self._future.done():
+ self._future.set_result(None)
def clear(self):
"""Reset the internal flag to ``False``.
Calls to `.wait` will block until `.set` is called.
"""
- self._flag = False
+ self._future = Future()
- def wait(self, deadline=None):
+ def wait(self, timeout=None):
"""Block until the internal flag is true.
- Returns a `.Future` that resolves ``True`` if the condition is notified,
- or ``False`` after a timeout.
+ Returns a Future, which raises :exc:`~tornado.gen.TimeoutError` after a
+ timeout.
"""
- if self._flag:
- return _true_future
+ if timeout is None:
+ return self._future
else:
- return self._condition.wait(deadline)
+ return gen.with_timeout(timeout, self._future)
import unittest
from tornado import gen, locks
+from tornado.gen import TimeoutError
from tornado.testing import gen_test, AsyncTestCase
self.assertFalse('clear' in str(event))
self.assertTrue('set' in str(event))
- @gen.coroutine
- def _test_event(self, n):
+ def test_event(self):
e = locks.Event()
- futures = [e.wait() for _ in range(n)]
+ future_0 = e.wait()
e.set()
+ future_1 = e.wait()
e.clear()
- results = yield futures
- self.assertTrue(all(results))
+ future_2 = e.wait()
- @gen_test
- def test_event_1(self):
- yield self._test_event(1)
-
- @gen_test
- def test_event_200(self):
- yield self._test_event(200)
+ self.assertTrue(future_0.done())
+ self.assertTrue(future_1.done())
+ self.assertFalse(future_2.done())
@gen_test
def test_event_timeout(self):
e = locks.Event()
- result = yield e.wait(deadline=timedelta(seconds=0.01))
- self.assertEqual(False, result)
+ with self.assertRaises(TimeoutError):
+ yield e.wait(timedelta(seconds=0.01))
# After a timed-out waiter, normal operation works.
self.io_loop.add_timeout(timedelta(seconds=0.01), e.set)
- result = yield e.wait(deadline=timedelta(seconds=1))
- self.assertTrue(result)
+ yield e.wait(timedelta(seconds=1))
- @gen_test
- def test_event_nowait(self):
+ def test_event_set_multiple(self):
e = locks.Event()
e.set()
- self.assertEqual(True, e.is_set())
- self.assertTrue(e.wait().result())
+ e.set()
+ self.assertTrue(e.is_set())
if __name__ == '__main__':