ó
¨œž[c           @` s  d  d l  m Z m Z m Z d  d l Z d  d l m Z d  d l m Z m	 Z	 d  d l
 m Z m Z d d d d	 d
 g Z d e f d „  ƒ  YZ d e f d „  ƒ  YZ d e f d „  ƒ  YZ d e f d „  ƒ  YZ d e f d „  ƒ  YZ d	 e f d „  ƒ  YZ d
 e f d „  ƒ  YZ d S(   i    (   t   absolute_importt   divisiont   print_functionN(   t   CancelledError(   t   gent   ioloop(   t   Futuret"   future_set_result_unless_cancelledt	   Conditiont   Eventt	   Semaphoret   BoundedSemaphoret   Lockt   _TimeoutGarbageCollectorc           B` s    e  Z d  Z d „  Z d „  Z RS(   sá   Base class for objects that periodically clean up timed-out waiters.

    Avoids memory leak in a common pattern like:

        while True:
            yield condition.wait(short_timeout)
            print('looping....')
    c         C` s   t  j ƒ  |  _ d |  _ d  S(   Ni    (   t   collectionst   dequet   _waiterst	   _timeouts(   t   self(    (    s,   lib/python2.7/site-packages/tornado/locks.pyt   __init__#   s    c         C` sM   |  j  d 7_  |  j  d k rI d |  _  t j d „  |  j Dƒ ƒ |  _ n  d  S(   Ni   id   i    c         s` s!   |  ] } | j  ƒ  s | Vq d  S(   N(   t   done(   t   .0t   w(    (    s,   lib/python2.7/site-packages/tornado/locks.pys	   <genexpr>-   s    (   R   R   R   R   (   R   (    (    s,   lib/python2.7/site-packages/tornado/locks.pyt   _garbage_collect'   s
    	(   t   __name__t
   __module__t   __doc__R   R   (    (    (    s,   lib/python2.7/site-packages/tornado/locks.pyR      s   	c           B` sA   e  Z d  Z d „  Z d „  Z d d „ Z d d „ Z d „  Z RS(   sÂ  A condition allows one or more coroutines to wait until notified.

    Like a standard `threading.Condition`, but does not need an underlying lock
    that is acquired and released.

    With a `Condition`, coroutines can wait to be notified by other coroutines:

    .. testcode::

        from tornado import gen
        from tornado.ioloop import IOLoop
        from tornado.locks import Condition

        condition = Condition()

        async def waiter():
            print("I'll wait right here")
            await condition.wait()
            print("I'm done waiting")

        async def notifier():
            print("About to notify")
            condition.notify()
            print("Done notifying")

        async def runner():
            # Wait for waiter() and notifier() in parallel
            await gen.multi([waiter(), notifier()])

        IOLoop.current().run_sync(runner)

    .. testoutput::

        I'll wait right here
        About to notify
        Done notifying
        I'm done waiting

    `wait` takes an optional ``timeout`` argument, which is either an absolute
    timestamp::

        io_loop = IOLoop.current()

        # Wait up to 1 second for a notification.
        await condition.wait(timeout=io_loop.time() + 1)

    ...or a `datetime.timedelta` for a timeout relative to the current time::

        # Wait up to 1 second.
        await condition.wait(timeout=datetime.timedelta(seconds=1))

    The method returns False if there's no notification before the deadline.

    .. versionchanged:: 5.0
       Previously, waiters could be notified synchronously from within
       `notify`. Now, the notification will always be received on the
       next iteration of the `.IOLoop`.
    c         C` s)   t  t |  ƒ j ƒ  t j j ƒ  |  _ d  S(   N(   t   superR   R   R   t   IOLoopt   currentt   io_loop(   R   (    (    s,   lib/python2.7/site-packages/tornado/locks.pyR   l   s    c         C` s>   d |  j  j f } |  j r6 | d t |  j ƒ 7} n  | d S(   Ns   <%ss    waiters[%s]t   >(   t	   __class__R   R   t   len(   R   t   result(    (    s,   lib/python2.7/site-packages/tornado/locks.pyt   __repr__p   s    	c         ` sr   t  ƒ  ‰ ˆ j j ˆ ƒ | rn ‡ ‡ f d †  } t j j ƒ  ‰  ˆ  j | | ƒ ‰ ˆ j ‡  ‡ f d †  ƒ n  ˆ S(   s”   Wait for `.notify`.

        Returns a `.Future` that resolves ``True`` if the condition is notified,
        or ``False`` after a timeout.
        c           ` s*   ˆ j  ƒ  s t ˆ t ƒ n  ˆ  j ƒ  d  S(   N(   R   R   t   FalseR   (    (   R   t   waiter(    s,   lib/python2.7/site-packages/tornado/locks.pyt
   on_timeout   s    c         ` s   ˆ  j  ˆ ƒ S(   N(   t   remove_timeout(   t   _(   R   t   timeout_handle(    s,   lib/python2.7/site-packages/tornado/locks.pyt   <lambda>†   s    (   R   R   t   appendR   R   R   t   add_timeoutt   add_done_callback(   R   t   timeoutR&   (    (   R   R   R)   R%   s,   lib/python2.7/site-packages/tornado/locks.pyt   waitv   s    	i   c         C` ss   g  } xH | rP |  j  rP |  j  j ƒ  } | j ƒ  s	 | d 8} | j | ƒ q	 q	 Wx | D] } t | t ƒ qX Wd S(   s   Wake ``n`` waiters.i   N(   R   t   popleftR   R+   R   t   True(   R   t   nt   waitersR%   (    (    s,   lib/python2.7/site-packages/tornado/locks.pyt   notify‰   s    
c         C` s   |  j  t |  j ƒ ƒ d S(   s   Wake all waiters.N(   R4   R!   R   (   R   (    (    s,   lib/python2.7/site-packages/tornado/locks.pyt
   notify_all•   s    N(	   R   R   R   R   R#   t   NoneR/   R4   R5   (    (    (    s,   lib/python2.7/site-packages/tornado/locks.pyR   0   s   :		c           B` sG   e  Z d  Z d „  Z d „  Z d „  Z d „  Z d „  Z d d „ Z	 RS(   s½  An event blocks coroutines until its internal flag is set to True.

    Similar to `threading.Event`.

    A coroutine can wait for an event to be set. Once it is set, calls to
    ``yield event.wait()`` will not block unless the event has been cleared:

    .. testcode::

        from tornado import gen
        from tornado.ioloop import IOLoop
        from tornado.locks import Event

        event = Event()

        async def waiter():
            print("Waiting for event")
            await event.wait()
            print("Not waiting this time")
            await event.wait()
            print("Done")

        async def setter():
            print("About to set the event")
            event.set()

        async def runner():
            await gen.multi([waiter(), setter()])

        IOLoop.current().run_sync(runner)

    .. testoutput::

        Waiting for event
        About to set the event
        Not waiting this time
        Done
    c         C` s   t  |  _ t ƒ  |  _ d  S(   N(   R$   t   _valuet   setR   (   R   (    (    s,   lib/python2.7/site-packages/tornado/locks.pyR   Á   s    	c         C` s&   d |  j  j |  j ƒ  r d n d f S(   Ns   <%s %s>R8   t   clear(   R    R   t   is_set(   R   (    (    s,   lib/python2.7/site-packages/tornado/locks.pyR#   Å   s    c         C` s   |  j  S(   s-   Return ``True`` if the internal flag is true.(   R7   (   R   (    (    s,   lib/python2.7/site-packages/tornado/locks.pyR:   É   s    c         C` sI   |  j  sE t |  _  x0 |  j D]" } | j ƒ  s | j d ƒ q q Wn  d S(   sƒ   Set the internal flag to ``True``. All waiters are awakened.

        Calling `.wait` once the flag is set will not block.
        N(   R7   R1   R   R   t
   set_resultR6   (   R   t   fut(    (    s,   lib/python2.7/site-packages/tornado/locks.pyR8   Í   s
    		c         C` s   t  |  _ d S(   sk   Reset the internal flag to ``False``.

        Calls to `.wait` will block until `.set` is called.
        N(   R$   R7   (   R   (    (    s,   lib/python2.7/site-packages/tornado/locks.pyR9   Ù   s    c         ` s’   t  ƒ  ‰  ˆ j r# ˆ  j d ƒ ˆ  Sˆ j j ˆ  ƒ ˆ  j ‡ f d †  ƒ | d k rY ˆ  St j | ˆ  d t	 f ƒ} | j ‡  f d †  ƒ | Sd S(   sŒ   Block until the internal flag is true.

        Returns a Future, which raises `tornado.util.TimeoutError` after a
        timeout.
        c         ` s   ˆ  j  j |  ƒ S(   N(   R   t   remove(   R<   (   R   (    s,   lib/python2.7/site-packages/tornado/locks.pyR*   ë   s    t   quiet_exceptionsc         ` s   ˆ  j  ƒ  s ˆ  j ƒ  Sd  S(   N(   R   t   cancelR6   (   t   tf(   R<   (    s,   lib/python2.7/site-packages/tornado/locks.pyR*   ó   s    N(
   R   R7   R;   R6   R   t   addR-   R   t   with_timeoutR   (   R   R.   t   timeout_fut(    (   R<   R   s,   lib/python2.7/site-packages/tornado/locks.pyR/   à   s    		N(
   R   R   R   R   R#   R:   R8   R9   R6   R/   (    (    (    s,   lib/python2.7/site-packages/tornado/locks.pyR	   š   s   &					t   _ReleasingContextManagerc           B` s)   e  Z d  Z d „  Z d „  Z d „  Z RS(   s³   Releases a Lock or Semaphore at the end of a "with" statement.

        with (yield semaphore.acquire()):
            pass

        # Now semaphore.release() has been called.
    c         C` s   | |  _  d  S(   N(   t   _obj(   R   t   obj(    (    s,   lib/python2.7/site-packages/tornado/locks.pyR   ÿ   s    c         C` s   d  S(   N(    (   R   (    (    s,   lib/python2.7/site-packages/tornado/locks.pyt	   __enter__  s    c         C` s   |  j  j ƒ  d  S(   N(   RE   t   release(   R   t   exc_typet   exc_valt   exc_tb(    (    s,   lib/python2.7/site-packages/tornado/locks.pyt   __exit__  s    (   R   R   R   R   RG   RL   (    (    (    s,   lib/python2.7/site-packages/tornado/locks.pyRD   ÷   s   		c           B` sk   e  Z d  Z d d „ Z d „  Z d „  Z d	 d „ Z d „  Z e Z	 e
 j d „  ƒ Z e
 j d „  ƒ Z RS(
   sS  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

       # Ensure reliable doctest output: resolve Futures one at a time.
       futures_q = deque([Future() for _ in range(3)])

       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)

       IOLoop.current().add_callback(simulator, list(futures_q))

       def use_some_resource():
           return futures_q.popleft()

    .. testcode:: semaphore

        from tornado import gen
        from tornado.ioloop import IOLoop
        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)])

        IOLoop.current().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.

    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.

    i   c         C` s;   t  t |  ƒ j ƒ  | d k  r. t d ƒ ‚ n  | |  _ d  S(   Ni    s$   semaphore initial value must be >= 0(   R   R
   R   t
   ValueErrorR7   (   R   t   value(    (    s,   lib/python2.7/site-packages/tornado/locks.pyR   h  s    c         C` sz   t  t |  ƒ j ƒ  } |  j d k r* d n d j |  j ƒ } |  j rc d j | t |  j ƒ ƒ } n  d j | d d !| ƒ S(   Ni    t   lockeds   unlocked,value:{0}s   {0},waiters:{1}s   <{0} [{1}]>i   iÿÿÿÿ(   R   R
   R#   R7   t   formatR   R!   (   R   t   rest   extra(    (    s,   lib/python2.7/site-packages/tornado/locks.pyR#   o  s    	c         C` sd   |  j  d 7_  xN |  j r_ |  j j ƒ  } | j ƒ  s |  j  d 8_  | j t |  ƒ ƒ Pq q Wd S(   s*   Increment the counter and wake one waiter.i   N(   R7   R   R0   R   R;   RD   (   R   R%   (    (    s,   lib/python2.7/site-packages/tornado/locks.pyRH   w  s    c         ` s¦   t  ƒ  ‰ ˆ j d k r= ˆ j d 8_ ˆ j t ˆ ƒ ƒ ne ˆ j j ˆ ƒ | r¢ ‡ ‡ f d †  } t j j ƒ  ‰  ˆ  j	 | | ƒ ‰ ˆ j
 ‡  ‡ f d †  ƒ n  ˆ S(   s°   Decrement the counter. Returns a Future.

        Block if the counter is zero and wait for a `.release`. The Future
        raises `.TimeoutError` after the deadline.
        i    i   c           ` s0   ˆ j  ƒ  s" ˆ j t j ƒ  ƒ n  ˆ  j ƒ  d  S(   N(   R   t   set_exceptionR   t   TimeoutErrorR   (    (   R   R%   (    s,   lib/python2.7/site-packages/tornado/locks.pyR&   •  s    c         ` s   ˆ  j  ˆ ƒ S(   N(   R'   (   R(   (   R   R)   (    s,   lib/python2.7/site-packages/tornado/locks.pyR*   œ  s    (   R   R7   R;   RD   R   R+   R   R   R   R,   R-   (   R   R.   R&   (    (   R   R   R)   R%   s,   lib/python2.7/site-packages/tornado/locks.pyt   acquireˆ  s    	c         C` s   t  d ƒ ‚ d  S(   NsP   Use Semaphore like 'with (yield semaphore.acquire())', not like 'with semaphore'(   t   RuntimeError(   R   (    (    s,   lib/python2.7/site-packages/tornado/locks.pyRG   Ÿ  s    c         c` s   |  j  ƒ  Vd  S(   N(   RU   (   R   (    (    s,   lib/python2.7/site-packages/tornado/locks.pyt
   __aenter__¦  s    c         C` s   |  j  ƒ  d  S(   N(   RH   (   R   t   typRN   t   tb(    (    s,   lib/python2.7/site-packages/tornado/locks.pyt	   __aexit__ª  s    N(   R   R   R   R   R#   RH   R6   RU   RG   RL   R   t	   coroutineRW   RZ   (    (    (    s,   lib/python2.7/site-packages/tornado/locks.pyR
   	  s   ^			c           B` s#   e  Z d  Z d d „ Z d „  Z RS(   s:  A semaphore that prevents release() being called too many times.

    If `.release` would increment the semaphore's value past the initial
    value, it raises `ValueError`. Semaphores are mostly used to guard
    resources with limited capacity, so a semaphore released too many times
    is a sign of a bug.
    i   c         C` s&   t  t |  ƒ j d | ƒ | |  _ d  S(   NRN   (   R   R   R   t   _initial_value(   R   RN   (    (    s,   lib/python2.7/site-packages/tornado/locks.pyR   ·  s    c         C` s8   |  j  |  j k r! t d ƒ ‚ n  t t |  ƒ j ƒ  d S(   s*   Increment the counter and wake one waiter.s!   Semaphore released too many timesN(   R7   R\   RM   R   R   RH   (   R   (    (    s,   lib/python2.7/site-packages/tornado/locks.pyRH   »  s    (   R   R   R   R   RH   (    (    (    s,   lib/python2.7/site-packages/tornado/locks.pyR   ¯  s   c           B` sh   e  Z d  Z d „  Z d „  Z d d „ Z d „  Z d „  Z e Z	 e
 j d „  ƒ Z e
 j d „  ƒ Z RS(	   sÏ  A lock for coroutines.

    A Lock begins unlocked, and `acquire` locks it immediately. While it is
    locked, a coroutine that yields `acquire` waits until another coroutine
    calls `release`.

    Releasing an unlocked lock raises `RuntimeError`.

    A Lock can be used as an async context manager with the ``async
    with`` statement:

    >>> from tornado import locks
    >>> lock = locks.Lock()
    >>>
    >>> async def f():
    ...    async with lock:
    ...        # Do something holding the lock.
    ...        pass
    ...
    ...    # Now the lock is released.

    For compatibility with older versions of Python, the `.acquire`
    method asynchronously returns a regular context manager:

    >>> async def f2():
    ...    with (yield lock.acquire()):
    ...        # Do something holding the lock.
    ...        pass
    ...
    ...    # Now the lock is released.

    .. versionchanged:: 4.3
       Added ``async with`` support in Python 3.5.

    c         C` s   t  d d ƒ |  _ d  S(   NRN   i   (   R   t   _block(   R   (    (    s,   lib/python2.7/site-packages/tornado/locks.pyR   æ  s    c         C` s   d |  j  j |  j f S(   Ns   <%s _block=%s>(   R    R   R]   (   R   (    (    s,   lib/python2.7/site-packages/tornado/locks.pyR#   é  s    	c         C` s   |  j  j | ƒ S(   sˆ   Attempt to lock. Returns a Future.

        Returns a Future, which raises `tornado.util.TimeoutError` after a
        timeout.
        (   R]   RU   (   R   R.   (    (    s,   lib/python2.7/site-packages/tornado/locks.pyRU   î  s    c         C` s5   y |  j  j ƒ  Wn t k
 r0 t d ƒ ‚ n Xd S(   sŠ   Unlock.

        The first coroutine in line waiting for `acquire` gets the lock.

        If not locked, raise a `RuntimeError`.
        s   release unlocked lockN(   R]   RH   RM   RV   (   R   (    (    s,   lib/python2.7/site-packages/tornado/locks.pyRH   ö  s    c         C` s   t  d ƒ ‚ d  S(   Ns7   Use Lock like 'with (yield lock)', not like 'with lock'(   RV   (   R   (    (    s,   lib/python2.7/site-packages/tornado/locks.pyRG     s    c         c` s   |  j  ƒ  Vd  S(   N(   RU   (   R   (    (    s,   lib/python2.7/site-packages/tornado/locks.pyRW     s    c         C` s   |  j  ƒ  d  S(   N(   RH   (   R   RX   RN   RY   (    (    s,   lib/python2.7/site-packages/tornado/locks.pyRZ     s    N(   R   R   R   R   R#   R6   RU   RH   RG   RL   R   R[   RW   RZ   (    (    (    s,   lib/python2.7/site-packages/tornado/locks.pyR   Â  s   #				(   t
   __future__R    R   R   R   t   concurrent.futuresR   t   tornadoR   R   t   tornado.concurrentR   R   t   __all__t   objectR   R   R	   RD   R
   R   R   (    (    (    s,   lib/python2.7/site-packages/tornado/locks.pyt   <module>   s   j]¦