
    hE                     ,   S SK r S SKrS SKrS SKJrJr  S SKJrJr  S SK	J
r
JrJrJrJr  S SK	r	\	R                  (       a  S SK	JrJr  / SQr " S S5      r " S	 S
\5      r " S S5      r " S S5      r " S S\5      r " S S\5      r " S S5      rg)    N)genioloop)Future"future_set_result_unless_cancelled)UnionOptionalTypeAny	Awaitable)DequeSet)	ConditionEvent	SemaphoreBoundedSemaphoreLockc                   ,    \ rS rSrSrSS jrSS jrSrg)_TimeoutGarbageCollector   zBase 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....')
Nc                 F    [         R                  " 5       U l        SU l        g )Nr   )collectionsdeque_waiters	_timeoutsselfs    `C:\Users\julio\OneDrive\Documentos\Trabajo\Ideas Frescas\venv\Lib\site-packages\tornado/locks.py__init__!_TimeoutGarbageCollector.__init__)   s    #))+    c                     U =R                   S-  sl         U R                   S:  a4  SU l         [        R                  " S U R                   5       5      U l        g g )N   d   r   c              3   R   #    U  H  oR                  5       (       a  M  Uv   M     g 7fN)done).0ws     r   	<genexpr><_TimeoutGarbageCollector._garbage_collect.<locals>.<genexpr>2   s     -WAffhaas   '	')r   r   r   r   r   s    r   _garbage_collect)_TimeoutGarbageCollector._garbage_collect-   sD    !>>CDN'---W-WWDM  r    )r   r   returnN)__name__
__module____qualname____firstlineno____doc__r   r+   __static_attributes__ r    r   r   r      s    Xr    r   c                       \ rS rSrSrS\4S jr SS\\\	\
R                  4      S\\   4S jjrSS\SS4S	 jjrSS
 jrSrg)r   5   a  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::

    import asyncio
    from tornado import gen
    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()])

    asyncio.run(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`.
r.   c                     SU R                   R                   3nU R                  (       a  US[        U R                  5      -  -  nUS-   $ )N<z waiters[%s]>)	__class__r/   r   len)r   results     r   __repr__Condition.__repr__q   sB    T^^,,-.==ns4=='999F|r    Ntimeoutc                   ^ ^^^ [        5       mT R                  R                  T5        U(       aN  SU U4S jjn[        R                  R                  5       mTR                  X5      mTR                  UU4S j5        T$ )z|Wait for `.notify`.

Returns a `.Future` that resolves ``True`` if the condition is notified,
or ``False`` after a timeout.
c                  h   > TR                  5       (       d  [        TS5        T R                  5         g NF)r&   r   r+   r   waiters   r   
on_timeout"Condition.wait.<locals>.on_timeout   s$    {{}}6vuE%%'r    c                 &   > TR                  T5      $ r%   remove_timeout_io_looptimeout_handles    r   <lambda> Condition.wait.<locals>.<lambda>   s    w/E/En/Ur    r-   )r   r   appendr   IOLoopcurrentadd_timeoutadd_done_callbackr   r@   rF   rM   rN   rE   s   `  @@@r   waitCondition.waitw   sc     V$( (
 mm++-G$00EN$$%UVr    nc                     / nU(       ap  U R                   (       a_  U R                   R                  5       nUR                  5       (       d  US-  nUR                  U5        U(       a  U R                   (       a  M_  U H  n[	        US5        M     g)zWake ``n`` waiters.r"   TN)r   popleftr&   rQ   r   )r   rY   waitersrE   s       r   notifyCondition.notify   se    DMM]]**,F;;==Qv&	 DMMM F.vt< r    c                 L    U R                  [        U R                  5      5        g)zWake all waiters.N)r]   r<   r   r   s    r   
notify_allCondition.notify_all   s    C&'r    r5   r%   r"   r-   )r/   r0   r1   r2   r3   strr>   r   r   floatdatetime	timedeltar   boolrW   intr]   r`   r4   r5   r    r   r   r   5   sa    9v#  EIeX-?-?&? @A	4,
= 
=D 
=(r    r   c                       \ rS rSrSrSS jrS\4S jrS\4S jr	SS jr
SS	 jr SS
\\\\R                   4      S\S   4S jjrSrg)r      a6  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::

    import asyncio
    from tornado import gen
    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()])

    asyncio.run(runner())

.. testoutput::

    Waiting for event
    About to set the event
    Not waiting this time
    Done
r.   Nc                 0    SU l         [        5       U l        g rC   )_valuesetr   r   s    r   r   Event.__init__   s    r    c                     SR                  U R                  R                  U R                  5       (       a  S5      $ S5      $ )Nz<{} {}>rm   clear)formatr;   r/   is_setr   s    r   r>   Event.__repr__   s<    NN##[[]]E
 	
(/
 	
r    c                     U R                   $ )z-Return ``True`` if the internal flag is true.rl   r   s    r   rr   Event.is_set   s    {{r    c                     U R                   (       dC  SU l         U R                   H+  nUR                  5       (       a  M  UR                  S5        M-     gg)zsSet the internal flag to ``True``. All waiters are awakened.

Calling `.wait` once the flag is set will not block.
TN)rl   r   r&   
set_result)r   futs     r   rm   	Event.set   s<    
 {{DK}}xxzzNN4( % r    c                     SU l         g)z[Reset the internal flag to ``False``.

Calls to `.wait` will block until `.set` is called.
FNru   r   s    r   rp   Event.clear   s    
 r    r@   c                 (  ^ ^ [        5       mT R                  (       a  TR                  S5        T$ T R                  R	                  T5        TR                  U 4S j5        Uc  T$ [        R                  " UT5      nUR                  U4S j5        U$ )zxBlock until the internal flag is true.

Returns an awaitable, which raises `tornado.util.TimeoutError` after a
timeout.
Nc                 :   > TR                   R                  U 5      $ r%   )r   remove)ry   r   s    r   rO   Event.wait.<locals>.<lambda>   s    $--*>*>s*Cr    c                 R   > TR                  5       (       d  TR                  5       $ S $ r%   )r&   cancel)tfry   s    r   rO   r      s    sxxzz3::<CtCr    )r   rl   rx   r   addrU   r   with_timeout)r   r@   timeout_futry   s   `  @r   rW   
Event.wait   s|     h;;NN4 J#CD?J**7C8K ))C r    )rl   r   r-   r%   )r/   r0   r1   r2   r3   r   rc   r>   rg   rr   rm   rp   r   r   rd   re   rf   r   rW   r4   r5   r    r   r   r      si    %N
# 
 
) EIeX-?-?&? @A	4 r    r   c                   n    \ rS rSrSrS\SS4S jrSS jrSS	S
\\	   S\\
R                     SS4S jrSrg)_ReleasingContextManageri  zReleases a Lock or Semaphore at the end of a "with" statement.

with (yield semaphore.acquire()):
    pass

# Now semaphore.release() has been called.
objr.   Nc                     Xl         g r%   _obj)r   r   s     r   r   !_ReleasingContextManager.__init__  s    	r    c                     g r%   r5   r   s    r   	__enter__"_ReleasingContextManager.__enter__  s    r    exc_typeOptional[Type[BaseException]]exc_valexc_tbc                 8    U R                   R                  5         g r%   )r   release)r   r   r   r   s       r   __exit__!_ReleasingContextManager.__exit__  s     			r    r   r-   )r/   r0   r1   r2   r3   r
   r   r   r   BaseExceptiontypesTracebackTyper   r4   r5   r    r   r   r     sZ    C D 1 -( ,,-	
 
r    r   c                   $  ^  \ rS rSrSrSS\SS4U 4S jjjrS\4U 4S jjrSS jr	 SS	\
\\\R                  4      S\\   4S
 jjrSS jrSSS\
\   S\
\R*                     SS4S jrSS jrSSS\
\   S\
\R*                     SS4S jrSrU =r$ )r   i  a
  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.

valuer.   Nc                 P   > [         TU ]  5         US:  a  [        S5      eXl        g )Nr   z$semaphore initial value must be >= 0)superr   
ValueErrorrl   r   r   r;   s     r   r   Semaphore.__init__  s&    19CDDr    c                    > [         TU ]  5       nU R                  S:X  a  SOSU R                   3nU R                  (       a  U S[	        U R                  5       3nSUSS  SU S	3$ )
Nr   lockedzunlocked,value:z	,waiters:r9   r"   z [z]>)r   r>   rl   r   r<   )r   resextrar;   s      r   r>   Semaphore.__repr__  si    g  KK1,ODKK=2Q==gYs4=='9&:;E3q9+Rwb))r    c                 6   U =R                   S-  sl         U R                  (       as  U R                  R                  5       nUR                  5       (       d0  U =R                   S-  sl         UR	                  [        U 5      5        gU R                  (       a  Mr  gg)*Increment the counter and wake one waiter.r"   N)rl   r   r[   r&   rx   r   rD   s     r   r   Semaphore.release  sf    qmm]]**,F;;==q  !!":4"@A mmmr    r@   c                   ^ ^^^ [        5       mT R                  S:  a1  T =R                  S-  sl        TR                  [        T 5      5        T$ T R                  R                  T5        U(       aN  SU U4S jjn[        R                  R                  5       mTR                  X5      mTR                  UU4S j5        T$ )zDecrement the counter. Returns an awaitable.

Block if the counter is zero and wait for a `.release`. The awaitable
raises `.TimeoutError` after the deadline.
r   r"   c                     > TR                  5       (       d$  TR                  [        R                  " 5       5        T R	                  5         g r%   )r&   set_exceptionr   TimeoutErrorr+   rD   s   r   rF   %Semaphore.acquire.<locals>.on_timeout  s1    !;;==,,S-=-=-?@))+r    c                 &   > TR                  T5      $ r%   rI   rK   s    r   rO   #Semaphore.acquire.<locals>.<lambda>  s    g44^Dr    r-   )r   rl   rx   r   r   rQ   r   rR   rS   rT   rU   rV   s   `  @@@r   acquireSemaphore.acquire  s     ;;?KK1K6t<=  MM  (, ,
 !--//1!(!4!4W!I((D r    c                     [        S5      e)Nz0Use 'async with' instead of 'with' for SemaphoreRuntimeErrorr   s    r   r   Semaphore.__enter__  s    MNNr    typr   	tracebackc                 $    U R                  5         g r%   r   )r   r   r   r   s       r   r   Semaphore.__exit__       	r    c                 @   #    U R                  5       I S h  vN   g  N7fr%   r   r   s    r   
__aenter__Semaphore.__aenter__       lln   tbc                 ,   #    U R                  5         g 7fr%   r   r   r   r   r   s       r   	__aexit__Semaphore.__aexit__        	   ru   rb   r-   r%   )r/   r0   r1   r2   r3   rh   r   rc   r>   r   r   r   rd   re   rf   r   r   r   r   r   r   r   r   r   r   r4   __classcell__r;   s   @r   r   r     s    bHc $  *# *$ EIeX-?-?&? @A	+	,8O, & E//0	
 
, & U(()	
 
 r    r   c                   L   ^  \ rS rSrSrS	S\SS4U 4S jjjrS
U 4S jjrSrU =r	$ )r   i  a&  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.
r   r.   Nc                 ,   > [         TU ]  US9  Xl        g )Nr   )r   r   _initial_valuer   s     r   r   BoundedSemaphore.__init__  s    u%#r    c                 l   > U R                   U R                  :  a  [        S5      e[        TU ]  5         g)r   z!Semaphore released too many timesN)rl   r   r   r   r   )r   r;   s    r   r   BoundedSemaphore.release  s+    ;;$---@AAr    )r   rb   r-   )
r/   r0   r1   r2   r3   rh   r   r   r4   r   r   s   @r   r   r     s*    $c $$ $ $ r    r   c                      \ rS rSrSrSS jrS\4S jr SS\\	\
\R                  4      S\\   4S jjrSS	 jrSS
 jrSSS\\   S\\R(                     SS4S jrSS jrSSS\\   S\\R(                     SS4S jrSrg)r   i  ag  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.

r.   Nc                      [        SS9U l        g )Nr"   r   )r   _blockr   s    r   r   Lock.__init__
  s    &Q/r    c                 P    SU R                   R                   SU R                   S3$ )Nr9   z _block=r:   )r;   r/   r   r   s    r   r>   Lock.__repr__  s&    4>>**+8DKK=BBr    r@   c                 8    U R                   R                  U5      $ )zxAttempt to lock. Returns an awaitable.

Returns an awaitable, which raises `tornado.util.TimeoutError` after a
timeout.
)r   r   )r   r@   s     r   r   Lock.acquire  s     {{""7++r    c                 l     U R                   R                  5         g! [         a    [        S5      ef = f)zrUnlock.

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

If not locked, raise a `RuntimeError`.
zrelease unlocked lockN)r   r   r   r   r   s    r   r   Lock.release  s2    	8KK! 	8677	8s    3c                     [        S5      e)Nz+Use `async with` instead of `with` for Lockr   r   s    r   r   Lock.__enter__&  s    HIIr    r   r   r   r   c                 $    U R                  5         g r%   r   r   s       r   r   Lock.__exit__)  r   r    c                 @   #    U R                  5       I S h  vN   g  N7fr%   r   r   s    r   r   Lock.__aenter__1  r   r   c                 ,   #    U R                  5         g 7fr%   r   r   s       r   r   Lock.__aexit__4  r   r   )r   r-   r%   )r/   r0   r1   r2   r3   r   rc   r>   r   r   rd   re   rf   r   r   r   r   r   r   r   r   r   r   r   r4   r5   r    r   r   r     s    "H0C# C EI,eX-?-?&? @A,	+	,,
8J, & U(()	
 
, & U(()	
 
r    r   )r   re   r   tornador   r   tornado.concurrentr   r   typingr   r   r	   r
   r   TYPE_CHECKINGr   r   __all__r   r   r   r   r   r   r   r5   r    r   <module>r      s        I 8 8 	!
IX X,f(( f(Ra aH 0t( tny (U Ur    