]> git.ipfire.org Git - thirdparty/tornado.git/commitdiff
locks: Update docs
authorBen Darnell <ben@bendarnell.com>
Sun, 30 Dec 2018 19:03:06 +0000 (14:03 -0500)
committerBen Darnell <ben@bendarnell.com>
Sun, 30 Dec 2018 20:14:37 +0000 (15:14 -0500)
docs/locks.rst
tornado/locks.py
tornado/queues.py
tornado/test/locks_test.py

index 9f991880c390e878018f72fe7bbe39509743560c..df30351ceaf84924b0c421809cccabd3cdf9f5b9 100644 (file)
@@ -10,9 +10,10 @@ similar to those provided in the standard library's `asyncio package
 
 .. warning::
 
-   Note that these primitives 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 a single-threaded app, not to protect shared objects in a
+   Note that these primitives are not actually thread-safe and cannot
+   be used in place of those from the standard library's `threading`
+   module--they are meant to coordinate Tornado coroutines in a
+   single-threaded app, not to protect shared objects in a
    multithreaded app.
 
 .. automodule:: tornado.locks
index 0da19766c45bbdbd4d0a3581ef67b701aa5729d7..8b1a5341091d1cb86bd7657f228327cb40059c80 100644 (file)
@@ -20,7 +20,7 @@ import types
 from tornado import gen, ioloop
 from tornado.concurrent import Future, future_set_result_unless_cancelled
 
-from typing import Union, Optional, Type, Any
+from typing import Union, Optional, Type, Any, Awaitable
 import typing
 
 if typing.TYPE_CHECKING:
@@ -121,7 +121,7 @@ class Condition(_TimeoutGarbageCollector):
             result += " waiters[%s]" % len(self._waiters)
         return result + ">"
 
-    def wait(self, timeout: Union[float, datetime.timedelta] = None) -> "Future[bool]":
+    def wait(self, timeout: Union[float, datetime.timedelta] = None) -> Awaitable[bool]:
         """Wait for `.notify`.
 
         Returns a `.Future` that resolves ``True`` if the condition is notified,
@@ -231,10 +231,10 @@ class Event(object):
         """
         self._value = False
 
-    def wait(self, timeout: Union[float, datetime.timedelta] = None) -> "Future[None]":
+    def wait(self, timeout: Union[float, datetime.timedelta] = None) -> Awaitable[None]:
         """Block until the internal flag is true.
 
-        Returns a Future, which raises `tornado.util.TimeoutError` after a
+        Returns an awaitable, which raises `tornado.util.TimeoutError` after a
         timeout.
         """
         fut = Future()  # type: Future[None]
@@ -413,10 +413,10 @@ class Semaphore(_TimeoutGarbageCollector):
 
     def acquire(
         self, timeout: Union[float, datetime.timedelta] = None
-    ) -> "Future[_ReleasingContextManager]":
-        """Decrement the counter. Returns a Future.
+    ) -> Awaitable[_ReleasingContextManager]:
+        """Decrement the counter. Returns an awaitable.
 
-        Block if the counter is zero and wait for a `.release`. The Future
+        Block if the counter is zero and wait for a `.release`. The awaitable
         raises `.TimeoutError` after the deadline.
         """
         waiter = Future()  # type: Future[_ReleasingContextManager]
@@ -440,10 +440,7 @@ class Semaphore(_TimeoutGarbageCollector):
         return waiter
 
     def __enter__(self) -> None:
-        raise RuntimeError(
-            "Use Semaphore like 'with (yield semaphore.acquire())', not like"
-            " 'with semaphore'"
-        )
+        raise RuntimeError("Use 'async with' instead of 'with' for Semaphore")
 
     def __exit__(
         self,
@@ -530,10 +527,10 @@ class Lock(object):
 
     def acquire(
         self, timeout: Union[float, datetime.timedelta] = None
-    ) -> "Future[_ReleasingContextManager]":
-        """Attempt to lock. Returns a Future.
+    ) -> Awaitable[_ReleasingContextManager]:
+        """Attempt to lock. Returns an awaitable.
 
-        Returns a Future, which raises `tornado.util.TimeoutError` after a
+        Returns an awaitable, which raises `tornado.util.TimeoutError` after a
         timeout.
         """
         return self._block.acquire(timeout)
@@ -551,7 +548,7 @@ class Lock(object):
             raise RuntimeError("release unlocked lock")
 
     def __enter__(self) -> None:
-        raise RuntimeError("Use Lock like 'with (yield lock)', not like 'with lock'")
+        raise RuntimeError("Use `async with` instead of `with` for Lock")
 
     def __exit__(
         self,
index 6c4fbd75561dded721015c651acdc57addab4caa..726477560dc77a142af9fc2470a9b381e630e4de 100644 (file)
@@ -277,7 +277,7 @@ class Queue(Generic[_T]):
         if self._unfinished_tasks == 0:
             self._finished.set()
 
-    def join(self, timeout: Union[float, datetime.timedelta] = None) -> "Future[None]":
+    def join(self, timeout: Union[float, datetime.timedelta] = None) -> Awaitable[None]:
         """Block until all items in the queue are processed.
 
         Returns a Future, which raises `tornado.util.TimeoutError` after a
index 787bfca31400a866b893aac911d8798b1c1672cb..7f88ab34b6cd0e84ee810c1e6c67d16f46d21284 100644 (file)
@@ -10,6 +10,7 @@
 # License for the specific language governing permissions and limitations
 # under the License.
 
+import asyncio
 from datetime import timedelta
 import typing  # noqa: F401
 import unittest
@@ -164,7 +165,7 @@ class ConditionTest(AsyncTestCase):
         c = locks.Condition()
 
         # Three waiters.
-        futures = [c.wait() for _ in range(3)]
+        futures = [asyncio.ensure_future(c.wait()) for _ in range(3)]
 
         # First and second futures resolved. Second future reenters notify(),
         # resolving third future.
@@ -180,7 +181,7 @@ class ConditionTest(AsyncTestCase):
         for _ in range(101):
             c.wait(timedelta(seconds=0.01))
 
-        future = c.wait()
+        future = asyncio.ensure_future(c.wait())
         self.assertEqual(102, len(c._waiters))
 
         # Let first 101 waiters time out, triggering a collection.
@@ -204,11 +205,11 @@ class EventTest(AsyncTestCase):
 
     def test_event(self):
         e = locks.Event()
-        future_0 = e.wait()
+        future_0 = asyncio.ensure_future(e.wait())
         e.set()
-        future_1 = e.wait()
+        future_1 = asyncio.ensure_future(e.wait())
         e.clear()
-        future_2 = e.wait()
+        future_2 = asyncio.ensure_future(e.wait())
 
         self.assertTrue(future_0.done())
         self.assertTrue(future_1.done())
@@ -232,9 +233,9 @@ class EventTest(AsyncTestCase):
 
     def test_event_wait_clear(self):
         e = locks.Event()
-        f0 = e.wait()
+        f0 = asyncio.ensure_future(e.wait())
         e.clear()
-        f1 = e.wait()
+        f1 = asyncio.ensure_future(e.wait())
         e.set()
         self.assertTrue(f0.done())
         self.assertTrue(f1.done())
@@ -256,13 +257,13 @@ class SemaphoreTest(AsyncTestCase):
 
     def test_acquire(self):
         sem = locks.Semaphore()
-        f0 = sem.acquire()
+        f0 = asyncio.ensure_future(sem.acquire())
         self.assertTrue(f0.done())
 
         # Wait for release().
-        f1 = sem.acquire()
+        f1 = asyncio.ensure_future(sem.acquire())
         self.assertFalse(f1.done())
-        f2 = sem.acquire()
+        f2 = asyncio.ensure_future(sem.acquire())
         sem.release()
         self.assertTrue(f1.done())
         self.assertFalse(f2.done())
@@ -271,7 +272,7 @@ class SemaphoreTest(AsyncTestCase):
 
         sem.release()
         # Now acquire() is instant.
-        self.assertTrue(sem.acquire().done())
+        self.assertTrue(asyncio.ensure_future(sem.acquire()).done())
         self.assertEqual(0, len(sem._waiters))
 
     @gen_test
@@ -286,7 +287,7 @@ class SemaphoreTest(AsyncTestCase):
             yield acquire
 
         sem.acquire()
-        f = sem.acquire()
+        f = asyncio.ensure_future(sem.acquire())
         self.assertFalse(f.done())
         sem.release()
         self.assertTrue(f.done())
@@ -309,18 +310,21 @@ class SemaphoreTest(AsyncTestCase):
         sem.release()
 
         # Now the counter is 3. We can acquire three times before blocking.
-        self.assertTrue(sem.acquire().done())
-        self.assertTrue(sem.acquire().done())
-        self.assertTrue(sem.acquire().done())
-        self.assertFalse(sem.acquire().done())
+        self.assertTrue(asyncio.ensure_future(sem.acquire()).done())
+        self.assertTrue(asyncio.ensure_future(sem.acquire()).done())
+        self.assertTrue(asyncio.ensure_future(sem.acquire()).done())
+        self.assertFalse(asyncio.ensure_future(sem.acquire()).done())
 
     @gen_test
     def test_garbage_collection(self):
         # Test that timed-out waiters are occasionally cleaned from the queue.
         sem = locks.Semaphore(value=0)
-        futures = [sem.acquire(timedelta(seconds=0.01)) for _ in range(101)]
+        futures = [
+            asyncio.ensure_future(sem.acquire(timedelta(seconds=0.01)))
+            for _ in range(101)
+        ]
 
-        future = sem.acquire()
+        future = asyncio.ensure_future(sem.acquire())
         self.assertEqual(102, len(sem._waiters))
 
         # Let first 101 waiters time out, triggering a collection.
@@ -345,7 +349,7 @@ class SemaphoreContextManagerTest(AsyncTestCase):
             self.assertTrue(yielded is None)
 
         # Semaphore was released and can be acquired again.
-        self.assertTrue(sem.acquire().done())
+        self.assertTrue(asyncio.ensure_future(sem.acquire()).done())
 
     @gen_test
     def test_context_manager_async_await(self):
@@ -359,7 +363,7 @@ class SemaphoreContextManagerTest(AsyncTestCase):
         yield f()
 
         # Semaphore was released and can be acquired again.
-        self.assertTrue(sem.acquire().done())
+        self.assertTrue(asyncio.ensure_future(sem.acquire()).done())
 
     @gen_test
     def test_context_manager_exception(self):
@@ -369,7 +373,7 @@ class SemaphoreContextManagerTest(AsyncTestCase):
                 1 / 0
 
         # Semaphore was released and can be acquired again.
-        self.assertTrue(sem.acquire().done())
+        self.assertTrue(asyncio.ensure_future(sem.acquire()).done())
 
     @gen_test
     def test_context_manager_timeout(self):
@@ -378,7 +382,7 @@ class SemaphoreContextManagerTest(AsyncTestCase):
             pass
 
         # Semaphore was released and can be acquired again.
-        self.assertTrue(sem.acquire().done())
+        self.assertTrue(asyncio.ensure_future(sem.acquire()).done())
 
     @gen_test
     def test_context_manager_timeout_error(self):
@@ -388,7 +392,7 @@ class SemaphoreContextManagerTest(AsyncTestCase):
                 pass
 
         # Counter is still 0.
-        self.assertFalse(sem.acquire().done())
+        self.assertFalse(asyncio.ensure_future(sem.acquire()).done())
 
     @gen_test
     def test_context_manager_contended(self):
@@ -433,7 +437,7 @@ class BoundedSemaphoreTest(AsyncTestCase):
         # Value is 0.
         sem.acquire()
         # Block on acquire().
-        future = sem.acquire()
+        future = asyncio.ensure_future(sem.acquire())
         self.assertFalse(future.done())
         sem.release()
         self.assertTrue(future.done())
@@ -452,8 +456,8 @@ class LockTests(AsyncTestCase):
 
     def test_acquire_release(self):
         lock = locks.Lock()
-        self.assertTrue(lock.acquire().done())
-        future = lock.acquire()
+        self.assertTrue(asyncio.ensure_future(lock.acquire()).done())
+        future = asyncio.ensure_future(lock.acquire())
         self.assertFalse(future.done())
         lock.release()
         self.assertTrue(future.done())
@@ -461,7 +465,7 @@ class LockTests(AsyncTestCase):
     @gen_test
     def test_acquire_fifo(self):
         lock = locks.Lock()
-        self.assertTrue(lock.acquire().done())
+        self.assertTrue(asyncio.ensure_future(lock.acquire()).done())
         N = 5
         history = []
 
@@ -481,7 +485,7 @@ class LockTests(AsyncTestCase):
         # Repeat the above test using `async with lock:`
         # instead of `with (yield lock.acquire()):`.
         lock = locks.Lock()
-        self.assertTrue(lock.acquire().done())
+        self.assertTrue(asyncio.ensure_future(lock.acquire()).done())
         N = 5
         history = []
 
@@ -502,7 +506,7 @@ class LockTests(AsyncTestCase):
             yield lock.acquire(timeout=timedelta(seconds=0.01))
 
         # Still locked.
-        self.assertFalse(lock.acquire().done())
+        self.assertFalse(asyncio.ensure_future(lock.acquire()).done())
 
     def test_multi_release(self):
         lock = locks.Lock()