
    MhlC                     D   d dl Z d dlZd dlZd dlmZmZ d dlmZmZ d dl	m
Z
mZmZmZmZ d dl	Z	e	j        rd dl	mZmZ g dZ G d d          Z G d	 d
e          Z G d d          Z G d d          Z G d de          Z G d de          Z G d d          ZdS )    N)genioloop)Future"future_set_result_unless_cancelled)UnionOptionalTypeAny	Awaitable)DequeSet)	ConditionEvent	SemaphoreBoundedSemaphoreLockc                   "    e Zd ZdZddZddZdS )_TimeoutGarbageCollectorzBase 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....')
    returnNc                 D    t          j                    | _        d| _        d S )Nr   )collectionsdeque_waiters	_timeoutsselfs    M/var/www/html/test/jupyter/venv/lib/python3.11/site-packages/tornado/locks.py__init__z!_TimeoutGarbageCollector.__init__)   s    #)++    c                     | xj         dz  c_         | j         dk    r1d| _         t          j        d | j        D                       | _        d S d S )N   d   r   c              3   B   K   | ]}|                                 |V  d S N)done).0ws     r   	<genexpr>z<_TimeoutGarbageCollector._garbage_collect.<locals>.<genexpr>2   s/      -W-WAaffhh-Wa-W-W-W-W-W-Wr   )r   r   r   r   r   s    r   _garbage_collectz)_TimeoutGarbageCollector._garbage_collect-   sU    !>CDN'--W-W-W-W-WWWDMMM  r   r   N)__name__
__module____qualname____doc__r   r)    r   r   r   r      sL            X X X X X Xr   r   c                   ~    e Zd ZdZdefdZ	 ddeeee	j
        f                  dee         fdZddeddfd	Zdd
ZdS )r   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                 l    d| j         j         }| j        r|dt          | j                  z  z  }|dz   S )N<z waiters[%s]>)	__class__r+   r   len)r   results     r   __repr__zCondition.__repr__q   sA    .T^,..= 	:ns4='9'999F|r   Ntimeoutc                 
    t                       j                                       |rTd fd}t          j                                                            ||                              fd           S )zWait for `.notify`.

        Returns a `.Future` that resolves ``True`` if the condition is notified,
        or ``False`` after a timeout.
        r   Nc                  x                                     st          d                                             d S NF)r%   r   r)   r   waiters   r   
on_timeoutz"Condition.wait.<locals>.on_timeout   s<    {{}} F6vuEEE%%'''''r   c                 .                                   S r$   remove_timeout_io_looptimeout_handles    r   <lambda>z Condition.wait.<locals>.<lambda>   s    w/E/En/U/U r   r*   )r   r   appendr   IOLoopcurrentadd_timeoutadd_done_callbackr   r8   r>   rD   rE   r=   s   `  @@@r   waitzCondition.waitw   s     V$$$ 		W( ( ( ( ( ( (
 m++--G$00*EEN$$%U%U%U%U%UVVVr   r!   nc                     g }|rW| j         rP| j                                         }|                                s|dz  }|                    |           |r| j         P|D ]}t	          |d           dS )zWake ``n`` waiters.r!   TN)r   popleftr%   rG   r   )r   rN   waitersr=   s       r   notifyzCondition.notify   s     	'DM 	']**,,F;;== 'Qv&&&	  	'DM 	'  	= 	=F.vt<<<<	= 	=r   c                 T    |                      t          | j                             dS )zWake all waiters.N)rR   r5   r   r   s    r   
notify_allzCondition.notify_all   s$    C&&'''''r   r$   r!   r*   )r+   r,   r-   r.   strr7   r   r   floatdatetime	timedeltar   boolrM   intrR   rT   r/   r   r   r   r   5   s        9 9v#     EI eX-?&? @A	4   ,
= 
= 
=D 
= 
= 
= 
=( ( ( ( ( (r   r   c                       e Zd ZdZddZdefdZdefdZddZ	ddZ
	 dd	eeeej        f                  ded         fd
ZdS )r   a  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                 :    d| _         t                      | _        d S r;   )_valuesetr   r   s    r   r   zEvent.__init__   s    r   c                 n    d                     | j        j        |                                 rdnd          S )Nz<{} {}>r_   clear)formatr4   r+   is_setr   s    r   r7   zEvent.__repr__   s6    N#[[]]/EE
 
 	
r   c                     | j         S )z-Return ``True`` if the internal flag is true.r^   r   s    r   rc   zEvent.is_set   s
    {r   c                     | j         s:d| _         | j        D ]-}|                                s|                    d           ,dS dS )zSet the internal flag to ``True``. All waiters are awakened.

        Calling `.wait` once the flag is set will not block.
        TN)r^   r   r%   
set_result)r   futs     r   r_   z	Event.set   s]    
 { 	)DK} ) )xxzz )NN4(((	) 	)) )r   c                     d| _         dS )zkReset the internal flag to ``False``.

        Calls to `.wait` will block until `.set` is called.
        FNre   r   s    r   ra   zEvent.clear   s    
 r   r8   c                 (    t                       j        r                    d           S  j                                                            fd           |S t          j        |          }|                    fd           |S )zBlock until the internal flag is true.

        Returns an awaitable, which raises `tornado.util.TimeoutError` after a
        timeout.
        Nc                 8    j                             |           S r$   )r   remove)rh   r   s    r   rF   zEvent.wait.<locals>.<lambda>   s    $-*>*>s*C*C r   c                 X                                     s                                nd S r$   )r%   cancel)tfrh   s    r   rF   zEvent.wait.<locals>.<lambda>   s     sxxzzC3::<<<t r   )r   r^   rg   r   addrK   r   with_timeout)r   r8   timeout_futrh   s   `  @r   rM   z
Event.wait   s     hh; 	NN4   J#CCCCDDD?J*7C88K ))CCCC   r   r*   r$   )r+   r,   r-   r.   r   rV   r7   rZ   rc   r_   ra   r   r   rW   rX   rY   r   rM   r/   r   r   r   r      s        % %N   
# 
 
 
 
    
) 
) 
) 
)    EI eX-?&? @A	4     r   r   c                   d    e Zd ZdZdeddfdZddZddd	ee         d
ee	j
                 ddfdZdS )_ReleasingContextManagerzReleases a Lock or Semaphore at the end of a "with" statement.

    with (yield semaphore.acquire()):
        pass

    # Now semaphore.release() has been called.
    objr   Nc                     || _         d S r$   )_obj)r   ru   s     r   r   z!_ReleasingContextManager.__init__  s    			r   c                     d S r$   r/   r   s    r   	__enter__z"_ReleasingContextManager.__enter__  s    r   exc_typeOptional[Type[BaseException]]exc_valexc_tbc                 8    | j                                          d S r$   )rw   release)r   rz   r|   r}   s       r   __exit__z!_ReleasingContextManager.__exit__  s     		r   r*   )r+   r,   r-   r.   r
   r   ry   r   BaseExceptiontypesTracebackTyper   r/   r   r   rt   rt     s         C D       1 -( ,-	
 
     r   rt   c                       e Zd ZdZddeddf fdZdef fdZddZ	 dd	e	e
eej        f                  dee         fd
ZddZddde	e         de	ej                 ddfdZddZddde	e         de	ej                 ddfdZ xZS )r   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.

    r!   valuer   Nc                     t                                                       |dk     rt          d          || _        d S )Nr   z$semaphore initial value must be >= 0)superr   
ValueErrorr^   r   r   r4   s     r   r   zSemaphore.__init__  s<    199CDDDr   c                     t                                                      }| j        dk    rdn	d| j         }| j        r| dt	          | j                   }d|dd          d| d	S )
Nr   lockedzunlocked,value:z	,waiters:r2   r!   z [z]>)r   r7   r^   r   r5   )r   resextrar4   s      r   r7   zSemaphore.__repr__  s    gg   K1,,2QDK2Q2Q= 	<;;s4='9'9;;E)3qt9))))))r   c                    | xj         dz  c_         | j        rj| j                                        }|                                s4| xj         dz  c_         |                    t          |                      dS | j        hdS dS )*Increment the counter and wake one waiter.r!   N)r^   r   rP   r%   rg   rt   r<   s     r   r   zSemaphore.release  s    qm 	]**,,F;;== 
q  !!":4"@"@AAA m 	 	 	 	 	r   r8   c                     t                       j        dk    r3 xj        dz  c_                            t                                np j                                       |rTd fd}t          j                                        	                    ||          
                    fd           S )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!   r   Nc                                                       s&                    t          j                                                                 d S r$   )r%   set_exceptionr   TimeoutErrorr)   r<   s   r   r>   z%Semaphore.acquire.<locals>.on_timeout  sI    !;;== A,,S-=-?-?@@@))+++++r   c                 .                                   S r$   r@   rB   s    r   rF   z#Semaphore.acquire.<locals>.<lambda>  s    g44^DD r   r*   )r   r^   rg   rt   r   rG   r   rH   rI   rJ   rK   rL   s   `  @@@r   acquirezSemaphore.acquire  s     ;??KK1KK6t<<====M  ((( , , , , , , ,
 !-//11!(!4!4Wj!I!I((DDDDD   r   c                      t          d          )Nz0Use 'async with' instead of 'with' for SemaphoreRuntimeErrorr   s    r   ry   zSemaphore.__enter__  s    MNNNr   typr{   	tracebackc                 .    |                                   d S r$   ry   )r   r   r   r   s       r   r   zSemaphore.__exit__       	r   c                 >   K   |                                   d {V  d S r$   r   r   s    r   
__aenter__zSemaphore.__aenter__  ,      llnnr   tbc                 2   K   |                                   d S r$   r   r   r   r   r   s       r   	__aexit__zSemaphore.__aexit__         	r   rU   r*   r$   )r+   r,   r-   r.   r[   r   rV   r7   r   r   r   rW   rX   rY   r   rt   r   ry   r   r   r   r   r   r   __classcell__r4   s   @r   r   r     s       b bH c $      *# * * * * * *   $ EI eX-?&? @A	+	,   8O O O O, & E/0	
 
      , & U()	
 
       r   r   c                   :     e Zd ZdZddeddf fdZd	 fdZ xZS )
r   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   r   Nc                 Z    t                                          |           || _        d S )Nr   )r   r   _initial_valuer   s     r   r   zBoundedSemaphore.__init__  s,    u%%%#r   c                     | j         | j        k    rt          d          t                                                       dS )r   z!Semaphore released too many timesN)r^   r   r   r   r   )r   r4   s    r   r   zBoundedSemaphore.release  s<    ;$---@AAAr   rU   r*   )r+   r,   r-   r.   r[   r   r   r   r   s   @r   r   r     sx         $ $c $$ $ $ $ $ $ $         r   r   c                       e Zd ZdZddZdefdZ	 ddeee	e
j        f                  dee         fdZddZdd	Zd
ddee         deej                 ddfdZddZd
ddee         deej                 ddfdZdS )r   a  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                 0    t          d          | _        d S )Nr!   r   )r   _blockr   s    r   r   zLock.__init__
  s    &Q///r   c                 2    d| j         j         d| j         dS )Nr2   z _block=r3   )r4   r+   r   r   s    r   r7   zLock.__repr__  s"    B4>*BBDKBBBBr   r8   c                 6    | j                             |          S )zAttempt to lock. Returns an awaitable.

        Returns an awaitable, which raises `tornado.util.TimeoutError` after a
        timeout.
        )r   r   )r   r8   s     r   r   zLock.acquire  s     {""7+++r   c                 t    	 | j                                          dS # t          $ r t          d          w xY w)zUnlock.

        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   zLock.release  sK    	8K!!!!! 	8 	8 	86777	8s    7c                      t          d          )Nz+Use `async with` instead of `with` for Lockr   r   s    r   ry   zLock.__enter__&  s    HIIIr   r   r{   r   r   c                 .    |                                   d S r$   r   r   s       r   r   zLock.__exit__)  r   r   c                 >   K   |                                   d {V  d S r$   r   r   s    r   r   zLock.__aenter__1  r   r   c                 2   K   |                                   d S r$   r   r   s       r   r   zLock.__aexit__4  r   r   r*   r$   )r+   r,   r-   r.   r   rV   r7   r   r   rW   rX   rY   r   rt   r   r   ry   r   r   r   r   r   r   r/   r   r   r   r     si       " "H0 0 0 0C# C C C C EI, ,eX-?&? @A,	+	,, , , ,
8 
8 
8 
8J J J J, & U()	
 
      , & U()	
 
     r   r   )r   rX   r   tornador   r   tornado.concurrentr   r   typingr   r   r	   r
   r   TYPE_CHECKINGr   r   __all__r   r   r   rt   r   r   r   r/   r   r   <module>r      s                 I I I I I I I I 8 8 8 8 8 8 8 8 8 8 8 8 8 8 	 "!!!!!!!!
I
I
IX X X X X X X X,f( f( f( f( f(( f( f( f(Ra a a a a a a aH       0t t t t t( t t tn    y   (U U U U U U U U U Ur   