]> git.ipfire.org Git - thirdparty/tornado.git/commitdiff
Document locks.Semaphore. 1401/head
authorA. Jesse Jiryu Davis <jesse@mongodb.com>
Tue, 31 Mar 2015 02:41:05 +0000 (22:41 -0400)
committerA. Jesse Jiryu Davis <jesse@mongodb.com>
Tue, 31 Mar 2015 02:41:05 +0000 (22:41 -0400)
docs/locks.rst
tornado/locks.py

index c9fd275c3a80e0d338f140de002005144240946c..c0ad500543ccdb206ee801ead751a22f94f12c70 100644 (file)
@@ -11,7 +11,7 @@ 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
 multithreaded app.)*
 
-.. testsetup::
+.. testsetup:: *
 
     from tornado import ioloop, gen, locks
     io_loop = ioloop.IOLoop.current()
@@ -108,3 +108,66 @@ multithreaded app.)*
         About to set the event
         Not waiting this time
         Done
+
+   Semaphore
+   ---------
+   .. autoclass:: Semaphore
+    :members:
+
+    Semaphores limit access to a shared resource. To allow access for two
+    workers at a time:
+
+    .. testsetup:: semaphore
+
+       from tornado import gen
+
+       # Ensure reliable doctest output.
+       waits = [0.1, 0.2, 0.1]
+
+       @gen.coroutine
+       def use_some_resource():
+           yield gen.sleep(waits.pop())
+
+    .. testcode:: semaphore
+
+        sem = locks.Semaphore(2)
+
+        @gen.coroutine
+        def worker(worker_id):
+            yield sem.acquire()
+            try:
+                print("Worker %d is working" % worker_id)
+                yield use_some_resource()
+            finally:
+                print("Worker %d is done" % worker_id)
+                sem.release()
+
+        @gen.coroutine
+        def runner():
+            # Join all workers.
+            yield [worker(i) for i in range(3)]
+
+        io_loop.run_sync(runner)
+
+    .. testoutput:: semaphore
+
+        Worker 0 is working
+        Worker 1 is working
+        Worker 0 is done
+        Worker 2 is working
+        Worker 1 is done
+        Worker 2 is done
+
+    Workers 0 and 1 are allowed to run concurrently, but worker 2 waits until
+    the semaphore has been released once, by worker 0.
+
+    `.acquire` is a context manager, so ``worker`` could be written as::
+
+        @gen.coroutine
+        def worker(worker_id):
+            with (yield sem.acquire()):
+                print("Worker %d is working" % worker_id)
+                yield use_some_resource()
+
+            # Now the semaphore has been released.
+            print("Worker %d is done" % worker_id)
index bdf15a2c274ce013899ab23b3e7ff42a82ead6a4..10a40f4ce512910afe82c4af2d22b6387fbb7ed9 100644 (file)
@@ -165,18 +165,6 @@ class Semaphore(_TimeoutGarbageCollector):
     minus the number of `.acquire` calls, plus an initial value. The `.acquire`
     method blocks if necessary until it can return without making the counter
     negative.
-
-    `.acquire` supports the context manager protocol:
-
-    >>> from tornado import gen, locks
-    >>> semaphore = locks.Semaphore()
-    >>> @gen.coroutine
-    ... def f():
-    ...    with (yield semaphore.acquire()):
-    ...        # Do something holding the semaphore.
-    ...        pass
-    ...
-    ...    # Now the semaphore is released.
     """
     def __init__(self, value=1):
         super(Semaphore, self).__init__()