class_docstr: Coordinate producer and consumer coroutines.
  
  If maxsize is 0 (the default) the queue size is unbounded.
  
  .. testcode::
  
      from tornado import gen
      from tornado.ioloop import IOLoop
      from tornado.queues import Queue
  
      q = Queue(maxsize=2)
  
      @gen.coroutine
      def consumer():
          while True:
              item = yield q.get()
              try:
                  print('Doing work on %s' % item)
                  yield gen.sleep(0.01)
              finally:
                  q.task_done()
  
      @gen.coroutine
      def producer():
          for item in range(5):
              yield q.put(item)
              print('Put %s' % item)
  
      @gen.coroutine
      def main():
          # Start consumer without waiting (since it never finishes).
          IOLoop.current().spawn_callback(consumer)
          yield producer()     # Wait for producer to put all tasks.
          yield q.join()       # Wait for consumer to finish all tasks.
          print('Done')
  
      IOLoop.current().run_sync(main)
  
  .. testoutput::
  
      Put 0
      Put 1
      Doing work on 0
      Put 2
      Doing work on 1
      Put 3
      Doing work on 2
      Put 4
      Doing work on 3
      Doing work on 4
      Done
  
  In Python 3.5, `Queue` implements the async iterator protocol, so
  ``consumer()`` could be rewritten as::
  
      async def consumer():
          async for item in q:
              try:
                  print('Doing work on %s' % item)
                  yield gen.sleep(0.01)
              finally:
                  q.task_done()
  
  .. versionchanged:: 4.3
     Added ``async for`` support in Python 3.5.
class_docstr_tok: ["Coordinate","producer","and","consumer","coroutines",".","If","maxsize","is","0","(","the","default",")","the","queue","size","is","unbounded",".","..","testcode",":",":","from","tornado","import","gen","from","tornado.ioloop","import","IOLoop","from","tornado.queues","import","Queue","q","=","Queue","(","maxsize=2",")","@","gen.coroutine","def","consumer","(",")",":","while","True",":","item","=","yield","q.get","(",")","try",":","print","(","'Doing","work","on","%","s","'","%","item",")","yield","gen.sleep","(","0.01",")","finally",":","q.task_done","(",")","@","gen.coroutine","def","producer","(",")",":","for","item","in","range","(","5",")",":","yield","q.put","(","item",")","print","(","'Put","%","s","'","%","item",")","@","gen.coroutine","def","main","(",")",":","#","Start","consumer","without","waiting","(","since","it","never","finishes",")",".","IOLoop.current","(",")",".spawn_callback","(","consumer",")","yield","producer","(",")","#","Wait","for","producer","to","put","all","tasks",".","yield","q.join","(",")","#","Wait","for","consumer","to","finish","all","tasks",".","print","(","'Done","'",")","IOLoop.current","(",")",".run_sync","(","main",")","..","testoutput",":",":","Put","0","Put","1","Doing","work","on","0","Put","2","Doing","work","on","1","Put","3","Doing","work","on","2","Put","4","Doing","work","on","3","Doing","work","on","4","Done","In","Python","3.5",",","`","Queue","`","implements","the","async","iterator","protocol",",","so","``","consumer","(",")","``","could","be","rewritten","as",":",":","async","def","consumer","(",")",":","async","for","item","in","q",":","try",":","print","(","'Doing","work","on","%","s","'","%","item",")","yield","gen.sleep","(","0.01",")","finally",":","q.task_done","(",")","..","versionchanged",":",":","4.3","Added","``","async","for","``","support","in","Python","3.5","."]
docstr: Indicate that a formerly enqueued task is complete.
  
  Used by queue consumers. For each `.get` used to fetch a task, a
  subsequent call to `.task_done` tells the queue that the processing
  on the task is complete.
  
  If a `.join` is blocking, it resumes when all items have been
  processed; that is, when every `.put` is matched by a `.task_done`.
  
  Raises `ValueError` if called more times than `.put`.
docstr_tok: ["Indicate","that","a","formerly","enqueued","task","is","complete",".","Used","by","queue","consumers",".","For","each","`",".get","`","used","to","fetch","a","task",",","a","subsequent","call","to","`",".task_done","`","tells","the","queue","that","the","processing","on","the","task","is","complete",".","If","a","`",".join","`","is","blocking",",","it","resumes","when","all","items","have","been","processed",";","that","is",",","when","every","`",".put","`","is","matched","by","a","`",".task_done","`",".","Raises","`","ValueError","`","if","called","more","times","than","`",".put","`","."]
code: def task_done(self):
      """Indicate that a formerly enqueued task is complete.
  
      Used by queue consumers. For each `.get` used to fetch a task, a
      subsequent call to `.task_done` tells the queue that the processing
      on the task is complete.
  
      If a `.join` is blocking, it resumes when all items have been
      processed; that is, when every `.put` is matched by a `.task_done`.
  
      Raises `ValueError` if called more times than `.put`.
      """
      if self._unfinished_tasks <= 0:
          raise ValueError("task_done() called too many times")
      self._unfinished_tasks -= 1
      if self._unfinished_tasks == 0:
          self._finished.set()
  
imports: from __future__ import absolute_import, division, print_function
  import collections
  import heapq
  from tornado import gen, ioloop
  from tornado.concurrent import Future
  from tornado.locks import Event
label_desc: Use image node_id 10 for calling the Queue obj's underlying member method code with example usage: obj.task_done() without return types