class_docstr: A lock that can be acquired a fixed number of times before blocking.
  
  A Semaphore manages a counter representing the number of `.release` calls
  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.
  
  Semaphores limit access to a shared resource. To allow access for two
  workers at a time:
  
  .. testsetup:: semaphore
  
     from collections import deque
  
     from tornado import gen
     from tornado.ioloop import IOLoop
     from tornado.concurrent import Future
  
     inited = False
  
     async def simulator(futures):
         for f in futures:
             # simulate the asynchronous passage of time
             await gen.sleep(0)
             await gen.sleep(0)
             f.set_result(None)
  
     def use_some_resource():
         global inited
         global futures_q
         if not inited:
             inited = True
             # Ensure reliable doctest output: resolve Futures one at a time.
             futures_q = deque([Future() for _ in range(3)])
             IOLoop.current().add_callback(simulator, list(futures_q))
  
         return futures_q.popleft()
  
  .. testcode:: semaphore
  
      import asyncio
      from tornado import gen
      from tornado.locks import Semaphore
  
      sem = Semaphore(2)
  
      async def worker(worker_id):
          await sem.acquire()
          try:
              print("Worker %d is working" % worker_id)
              await use_some_resource()
          finally:
              print("Worker %d is done" % worker_id)
              sem.release()
  
      async def runner():
          # Join all workers.
          await gen.multi([worker(i) for i in range(3)])
  
      asyncio.run(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.
  
  The semaphore can be used as an async context manager::
  
      async def worker(worker_id):
          async with sem:
              print("Worker %d is working" % worker_id)
              await use_some_resource()
  
          # Now the semaphore has been released.
          print("Worker %d is done" % worker_id)
  
  For compatibility with older versions of Python, `.acquire` is a
  context manager, so ``worker`` could also 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)
  
  .. versionchanged:: 4.3
     Added ``async with`` support in Python 3.5.
class_docstr_tok: ["A","lock","that","can","be","acquired","a","fixed","number","of","times","before","blocking",".","A","Semaphore","manages","a","counter","representing","the","number","of","`",".release","`","calls","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",".","Semaphores","limit","access","to","a","shared","resource",".","To","allow","access","for","two","workers","at","a","time",":","..","testsetup",":",":","semaphore","from","collections","import","deque","from","tornado","import","gen","from","tornado.ioloop","import","IOLoop","from","tornado.concurrent","import","Future","inited","=","False","async","def","simulator","(","futures",")",":","for","f","in","futures",":","#","simulate","the","asynchronous","passage","of","time","await","gen.sleep","(","0",")","await","gen.sleep","(","0",")","f.set_result","(","None",")","def","use_some_resource","(",")",":","global","inited","global","futures_q","if","not","inited",":","inited","=","True","#","Ensure","reliable","doctest","output",":","resolve","Futures","one","at","a","time",".","futures_q","=","deque","(","[","Future","(",")","for","_","in","range","(","3",")","]",")","IOLoop.current","(",")",".add_callback","(","simulator",",","list","(","futures_q",")",")","return","futures_q.popleft","(",")","..","testcode",":",":","semaphore","import","asyncio","from","tornado","import","gen","from","tornado.locks","import","Semaphore","sem","=","Semaphore","(","2",")","async","def","worker","(","worker_id",")",":","await","sem.acquire","(",")","try",":","print","(","``","Worker","%","d","is","working","''","%","worker_id",")","await","use_some_resource","(",")","finally",":","print","(","``","Worker","%","d","is","done","''","%","worker_id",")","sem.release","(",")","async","def","runner","(",")",":","#","Join","all","workers",".","await","gen.multi","(","[","worker","(","i",")","for","i","in","range","(","3",")","]",")","asyncio.run","(","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",".","The","semaphore","can","be","used","as","an","async","context","manager",":",":","async","def","worker","(","worker_id",")",":","async","with","sem",":","print","(","``","Worker","%","d","is","working","''","%","worker_id",")","await","use_some_resource","(",")","#","Now","the","semaphore","has","been","released",".","print","(","``","Worker","%","d","is","done","''","%","worker_id",")","For","compatibility","with","older","versions","of","Python",",","`",".acquire","`","is","a","context","manager",",","so","``","worker","``","could","also","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",")","..","versionchanged",":",":","4.3","Added","``","async","with","``","support","in","Python","3.5","."]
code: def __exit__(
      self,
      typ: "Optional[Type[BaseException]]",
      value: Optional[BaseException],
      traceback: Optional[types.TracebackType],
  ) -> None:
      self.__enter__()
  
imports: import collections
  import datetime
  import types
  from tornado import gen, ioloop
  from tornado.concurrent import Future, future_set_result_unless_cancelled
  from typing import Union, Optional, Type, Any, Awaitable
  import typing
label_desc: Use image node_id 6 for calling the Semaphore obj's underlying member method code with example usage: obj.__exit__(typ, value, traceback) without return types