
    gҏ                        d Z ddlZddlZddlZddlZddlZddlZddlZddl	Z	ddl
Z
ddlZddlZddlmZ ddlmZmZmZmZmZ ddlmZ ddlmZmZmZ ddlZddlmZmZmZmZm Z m!Z!m"Z"m#Z# ejH                  rddlm%Z%m&Z&m'Z' dd	l(m)Z) ne*Z) G d
 de)      Z+ e!d      Z, e!de+      Z- G d de      Z. G d de*      Z/ G d de*      Z0y)a  An I/O event loop for non-blocking sockets.

In Tornado 6.0, `.IOLoop` is a wrapper around the `asyncio` event loop, with a
slightly different interface. The `.IOLoop` interface is now provided primarily
for backwards compatibility; new code should generally use the `asyncio` event
loop interface directly. The `IOLoop.current` class method provides the
`IOLoop` instance corresponding to the running `asyncio` event loop.

    N)isawaitable)Future	is_futurechain_futurefuture_set_exc_infofuture_add_done_callback)app_log)ConfigurableTimeoutErrorimport_object)UnionAnyTypeOptionalCallableTypeVarTuple	Awaitable)DictListSet)Protocolc                        e Zd ZdefdZddZy)_Selectablereturnc                      y N selfs    C/var/www/openai/venv/lib/python3.12/site-packages/tornado/ioloop.pyfilenoz_Selectable.fileno=           Nc                      y r   r   r   s    r!   closez_Selectable.close@   r#   r$   r   N)__name__
__module____qualname__intr"   r&   r   r$   r!   r   r   <   s     r$   r   _T_S)boundc            
           e Zd ZdZdZdZdZdZ e       Z	 e
       Zeddded	d
f fd       ZedHd       ZdIdZedId       Zej(                  edHd              Zej(                  edJded	ed    fd              ZedJded	ed    fd       ZdIdZdIdZedId       ZedId       ZdIdZed	ee   fd       Zed	ee   fd       Z dJded	d
fdZ!dKded	d
fdZ"ej(                  de#de$e#e#gd
f   d e#d	d
fd!       Z%ej(                  de&de$e&e#gd
f   d e#d	d
fd"       Z%de'e#e(f   de$d#   d e#d	d
fd$Z%de'e#e(f   d e#d	d
fd%Z)de'e#e(f   d	d
fd&Z*dId'Z+dId(Z,dLd)e$d*ee-   d	efd+Z.d	e-fd,Z/d-e'e-e0jb                  f   d.e$d/eded	e2f
d0Z3d1e-d.e$d/eded	e2f
d2Z4d3e-d.e$d/eded	e2f
d4Z5d*e2d	d
fd5Z6d.e$d/eded	d
fd6Z7d.e$d/eded	d
fd7Z8d.e$d/eded	d
fd8Z9d9d:d.e$d;gd
f   d	d
fd<Z:d=ee;jx                  jz                     d)e$d>e>f   d/ed	d;fd?Z?d=e;jx                  jz                  d	d
fd@Z@d.e$g ef   d	d
fdAZAd9eBd	d
fdBZCde'e#e(f   d	eDe#e'e#e(f   f   fdCZEde'e#e(f   d	d
fdDZFdEeBd	d
fdFZGdEeBd	d
fdGZH xZIS )MIOLoopa  An I/O event loop.

    As of Tornado 6.0, `IOLoop` is a wrapper around the `asyncio` event loop.

    Example usage for a simple TCP server:

    .. testcode::

        import asyncio
        import errno
        import functools
        import socket

        import tornado
        from tornado.iostream import IOStream

        async def handle_connection(connection, address):
            stream = IOStream(connection)
            message = await stream.read_until_close()
            print("message from client:", message.decode().strip())

        def connection_ready(sock, fd, events):
            while True:
                try:
                    connection, address = sock.accept()
                except BlockingIOError:
                    return
                connection.setblocking(0)
                io_loop = tornado.ioloop.IOLoop.current()
                io_loop.spawn_callback(handle_connection, connection, address)

        async def main():
            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
            sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            sock.setblocking(0)
            sock.bind(("", 8888))
            sock.listen(128)

            io_loop = tornado.ioloop.IOLoop.current()
            callback = functools.partial(connection_ready, sock)
            io_loop.add_handler(sock.fileno(), callback, io_loop.READ)
            await asyncio.Event().wait()

        if __name__ == "__main__":
            asyncio.run(main())

    .. testoutput::
       :hide:

    Most applications should not attempt to construct an `IOLoop` directly,
    and instead initialize the `asyncio` event loop and use `IOLoop.current()`.
    In some cases, such as in test frameworks when initializing an `IOLoop`
    to be run in a secondary thread, it may be appropriate to construct
    an `IOLoop` with ``IOLoop(make_current=False)``.

    In general, an `IOLoop` cannot survive a fork or be shared across processes
    in any way. When multiple processes are being used, each process should
    create its own `IOLoop`, which also implies that any objects which depend on
    the `IOLoop` (such as `.AsyncHTTPClient`) must also be created in the child
    processes. As a guideline, anything that starts processes (including the
    `tornado.process` and `multiprocessing` modules) should do so as early as
    possible, ideally the first thing the application does after loading its
    configuration, and *before* any calls to `.IOLoop.start` or `asyncio.run`.

    .. versionchanged:: 4.2
       Added the ``make_current`` keyword argument to the `IOLoop`
       constructor.

    .. versionchanged:: 5.0

       Uses the `asyncio` event loop by default. The ``IOLoop.configure`` method
       cannot be used on Python 3 except to redundantly specify the `asyncio`
       event loop.

    .. versionchanged:: 6.3
       ``make_current=True`` is now the default when creating an IOLoop -
       previously the default was to make the event loop current if there wasn't
       already a current one.
    r            implz$Union[None, str, Type[Configurable]]kwargsr   Nc                     ddl m} t        |t              rt	        |      }t        |t
              rt        ||      st        d      t        t        | *  |fi | y )Nr   )BaseAsyncIOLoopz5only AsyncIOLoop is allowed when asyncio is available)tornado.platform.asyncior7   
isinstancestrr   type
issubclassRuntimeErrorsuperr0   	configure)clsr4   r5   r7   	__class__s       r!   r?   zIOLoop.configure   sO     	=dC  &DdD!*T?*KVWWfc$T4V4r$   c                  *    t         j                         S )aK  Deprecated alias for `IOLoop.current()`.

        .. versionchanged:: 5.0

           Previously, this method returned a global singleton
           `IOLoop`, in contrast with the per-thread `IOLoop` returned
           by `current()`. In nearly all cases the two were the same
           (when they differed, it was generally used from non-Tornado
           threads to communicate back to the main thread's `IOLoop`).
           This distinction is not present in `asyncio`, so in order
           to facilitate integration with that package `instance()`
           was changed to be an alias to `current()`. Applications
           using the cross-thread communications aspect of
           `instance()` should instead set their own global variable
           to point to the `IOLoop` they want to use.

        .. deprecated:: 5.0
        )r0   currentr   r$   r!   instancezIOLoop.instance   s    ( ~~r$   c                 $    | j                          y)a`  Deprecated alias for `make_current()`.

        .. versionchanged:: 5.0

           Previously, this method would set this `IOLoop` as the
           global singleton used by `IOLoop.instance()`. Now that
           `instance()` is an alias for `current()`, `install()`
           is an alias for `make_current()`.

        .. deprecated:: 5.0
        N)make_currentr   s    r!   installzIOLoop.install   s     	r$   c                  ,    t         j                          y)ak  Deprecated alias for `clear_current()`.

        .. versionchanged:: 5.0

           Previously, this method would clear the `IOLoop` used as
           the global singleton by `IOLoop.instance()`. Now that
           `instance()` is an alias for `current()`,
           `clear_instance()` is an alias for `clear_current()`.

        .. deprecated:: 5.0

        N)r0   clear_currentr   r$   r!   clear_instancezIOLoop.clear_instance   s     	r$   c                       y r   r   r   r$   r!   rC   zIOLoop.current        	r$   rD   c                      y r   r   rD   s    r!   rC   zIOLoop.current   rL   r$   c                    	 t        j                         }	 t
        j                  |   S # t        $ r0 | sY yt        j                         }t        j                  |       Y Lw xY w# t        $ r | rddlm	}  |       }Y |S d}Y |S w xY w)aC  Returns the current thread's `IOLoop`.

        If an `IOLoop` is currently running or has been marked as
        current by `make_current`, returns that instance.  If there is
        no current `IOLoop` and ``instance`` is true, creates one.

        .. versionchanged:: 4.1
           Added ``instance`` argument to control the fallback to
           `IOLoop.instance()`.
        .. versionchanged:: 5.0
           On Python 3, control of the current `IOLoop` is delegated
           to `asyncio`, with this and other methods as pass-through accessors.
           The ``instance`` argument now controls whether an `IOLoop`
           is created automatically when there is none, instead of
           whether we fall back to `IOLoop.instance()` (which is now
           an alias for this method). ``instance=False`` is deprecated,
           since even if we do not create an `IOLoop`, this method
           may initialize the asyncio loop.

        .. deprecated:: 6.2
           It is deprecated to call ``IOLoop.current()`` when no `asyncio`
           event loop is running.
        Nr   )AsyncIOMainLoop)
asyncioget_event_loopr=   new_event_loopset_event_loopr0   _ioloop_for_asyncioKeyErrorr8   rP   )rD   looprP   rC   s       r!   rC   zIOLoop.current   s    2	)))+D	--d33  	)))+D""4(	)  	D)+  	s+   * A& A#)A#"A#&BBBc                 \    t        j                  dt        d       | j                          y)a  Makes this the `IOLoop` for the current thread.

        An `IOLoop` automatically becomes current for its thread
        when it is started, but it is sometimes useful to call
        `make_current` explicitly before starting the `IOLoop`,
        so that code run at startup time can find the right
        instance.

        .. versionchanged:: 4.1
           An `IOLoop` created while there is no current `IOLoop`
           will automatically become current.

        .. versionchanged:: 5.0
           This method also sets the current `asyncio` event loop.

        .. deprecated:: 6.2
           Setting and clearing the current event loop through Tornado is
           deprecated. Use ``asyncio.set_event_loop`` instead if you need this.
        z6make_current is deprecated; start the event loop first   
stacklevelN)warningswarnDeprecationWarning_make_currentr   s    r!   rF   zIOLoop.make_current%  s'    ( 	D	

 	r$   c                     t               r   NotImplementedErrorr   s    r!   r_   zIOLoop._make_current@  s    !##r$   c                  d    t        j                  dt        d       t        j	                          y)zClears the `IOLoop` for the current thread.

        Intended primarily for use by test frameworks in between tests.

        .. versionchanged:: 5.0
           This method also clears the current `asyncio` event loop.
        .. deprecated:: 6.2
        zclear_current is deprecatedrY   rZ   N)r\   r]   r^   r0   _clear_currentr   r$   r!   rI   zIOLoop.clear_currentD  s'     	)	

 	r$   c                  V    t         j                  d      } | | j                          y y )NFrN   )r0   rC   _clear_current_hook)olds    r!   rd   zIOLoop._clear_currentU  s(    nnen,?##% r$   c                      y)zInstance method called when an IOLoop ceases to be current.

        May be overridden by subclasses as a counterpart to make_current.
        Nr   r   s    r!   rf   zIOLoop._clear_current_hook[  s    
 	r$   c                     t         S r   )r0   )r@   s    r!   configurable_basezIOLoop.configurable_baseb  s    r$   c                     ddl m} |S )Nr   )AsyncIOLoop)r8   rl   )r@   rl   s     r!   configurable_defaultzIOLoop.configurable_defaultf  s    8r$   rF   c                 *    |r| j                          y y r   )r_   )r    rF   s     r!   
initializezIOLoop.initializel  s      r$   all_fdsc                     t               )a  Closes the `IOLoop`, freeing any resources used.

        If ``all_fds`` is true, all file descriptors registered on the
        IOLoop will be closed (not just the ones created by the
        `IOLoop` itself).

        Many applications will only use a single `IOLoop` that runs for the
        entire lifetime of the process.  In that case closing the `IOLoop`
        is not necessary since everything will be cleaned up when the
        process exits.  `IOLoop.close` is provided mainly for scenarios
        such as unit tests, which create and destroy a large number of
        ``IOLoops``.

        An `IOLoop` must be completely stopped before it can be closed.  This
        means that `IOLoop.stop()` must be called *and* `IOLoop.start()` must
        be allowed to return before attempting to call `IOLoop.close()`.
        Therefore the call to `close` will usually appear just after
        the call to `start` rather than near the call to `stop`.

        .. versionchanged:: 3.1
           If the `IOLoop` implementation supports non-integer objects
           for "file descriptors", those objects will have their
           ``close`` method when ``all_fds`` is true.
        ra   )r    rp   s     r!   r&   zIOLoop.closep  s    2 "##r$   fdhandlereventsc                      y r   r   r    rr   rs   rt   s       r!   add_handlerzIOLoop.add_handler       	r$   c                      y r   r   rv   s       r!   rw   zIOLoop.add_handler  rx   r$   ).Nc                     t               )a+  Registers the given handler to receive the given events for ``fd``.

        The ``fd`` argument may either be an integer file descriptor or
        a file-like object with a ``fileno()`` and ``close()`` method.

        The ``events`` argument is a bitwise or of the constants
        ``IOLoop.READ``, ``IOLoop.WRITE``, and ``IOLoop.ERROR``.

        When an event occurs, ``handler(fd, events)`` will be run.

        .. versionchanged:: 4.0
           Added the ability to pass file-like objects in addition to
           raw file descriptors.
        ra   rv   s       r!   rw   zIOLoop.add_handler  s    " "##r$   c                     t               )zChanges the events we listen for ``fd``.

        .. versionchanged:: 4.0
           Added the ability to pass file-like objects in addition to
           raw file descriptors.
        ra   )r    rr   rt   s      r!   update_handlerzIOLoop.update_handler       "##r$   c                     t               )zStop listening for events on ``fd``.

        .. versionchanged:: 4.0
           Added the ability to pass file-like objects in addition to
           raw file descriptors.
        ra   r    rr   s     r!   remove_handlerzIOLoop.remove_handler  r}   r$   c                     t               )zStarts the I/O loop.

        The loop will run until one of the callbacks calls `stop()`, which
        will make the loop stop after the current event iteration completes.
        ra   r   s    r!   startzIOLoop.start  s     "##r$   c                     t               )a  Stop the I/O loop.

        If the event loop is not currently running, the next call to `start()`
        will return immediately.

        Note that even after `stop` has been called, the `IOLoop` is not
        completely stopped until `IOLoop.start` has also returned.
        Some work that was scheduled before the call to `stop` may still
        be run before the `IOLoop` shuts down.
        ra   r   s    r!   stopzIOLoop.stop  s     "##r$   functimeoutc                 z    dgd fd} j                  |       |*d fd} j                   j                         |z   |      } j                          | j	                         d   J d   j                         sd   j                         st        d|z        d   j                         S )a  Starts the `IOLoop`, runs the given function, and stops the loop.

        The function must return either an awaitable object or
        ``None``. If the function returns an awaitable object, the
        `IOLoop` will run until the awaitable is resolved (and
        `run_sync()` will return the awaitable's result). If it raises
        an exception, the `IOLoop` will stop and the exception will be
        re-raised to the caller.

        The keyword-only argument ``timeout`` may be used to set
        a maximum duration for the function.  If the timeout expires,
        a `asyncio.TimeoutError` is raised.

        This method is useful to allow asynchronous calls in a
        ``main()`` function::

            async def main():
                # do stuff...

            if __name__ == '__main__':
                IOLoop.current().run_sync(main)

        .. versionchanged:: 4.3
           Returning a non-``None``, non-awaitable value is now an error.

        .. versionchanged:: 5.0
           If a timeout occurs, the ``func`` coroutine will be cancelled.

        .. versionchanged:: 6.2
           ``tornado.util.TimeoutError`` is now an alias to ``asyncio.TimeoutError``.
        Nc                  P   	         } | ddl m}  ||       } t        |       r| d<   n!t               }|d<   |j	                  |        	 d   J j                  d   fd       y # t
        $ r0 t               }|d<   t        |t        j                                Y Xw xY w)Nr   )convert_yieldedc                 $    j                         S r   )r   )futurer    s    r!   <lambda>z.IOLoop.run_sync.<locals>.run.<locals>.<lambda>  s    499;r$   )
tornado.genr   r   r   
set_result	Exceptionr   sysexc_info
add_future)resultr   futr   future_cellr    s      r!   runzIOLoop.run_sync.<locals>.run  s    +%;,V4F V$%+KN (C%(KNNN6*q>---OOKN,FG  9h!$A#C89s   A, ,6B%$B%c                  \     d   J  d   j                         sj                          y y )Nr   )cancelr   )r   r    s   r!   timeout_callbackz)IOLoop.run_sync.<locals>.timeout_callback  s3    
 #1~111"1~,,.IIK /r$   r   z$Operation timed out after %s secondsr'   )	add_callbackadd_timeouttimer   remove_timeout	cancelleddoner   r   )r    r   r   r   r   timeout_handler   s   ``    @r!   run_synczIOLoop.run_sync  s    @ f	H* 	#  "--diikG.CEUVN

/1~)))q>##%[^-@-@-BEOPP1~$$&&r$   c                 *    t        j                          S )a  Returns the current time according to the `IOLoop`'s clock.

        The return value is a floating-point number relative to an
        unspecified time in the past.

        Historically, the IOLoop could be customized to use e.g.
        `time.monotonic` instead of `time.time`, but this is not
        currently supported and so this method is equivalent to
        `time.time`.

        )r   r   s    r!   r   zIOLoop.time  s     yy{r$   deadlinecallbackargsc                     t        |t        j                        r | j                  ||g|i |S t        |t        j
                        r6 | j                  | j                         |j                         z   |g|i |S t        d|z        )a  Runs the ``callback`` at the time ``deadline`` from the I/O loop.

        Returns an opaque handle that may be passed to
        `remove_timeout` to cancel.

        ``deadline`` may be a number denoting a time (on the same
        scale as `IOLoop.time`, normally `time.time`), or a
        `datetime.timedelta` object for a deadline relative to the
        current time.  Since Tornado 4.0, `call_later` is a more
        convenient alternative for the relative case since it does not
        require a timedelta object.

        Note that it is not safe to call `add_timeout` from other threads.
        Instead, you must use `add_callback` to transfer control to the
        `IOLoop`'s thread, and then call `add_timeout` from there.

        Subclasses of IOLoop must implement either `add_timeout` or
        `call_at`; the default implementations of each will call
        the other.  `call_at` is usually easier to implement, but
        subclasses that wish to maintain compatibility with Tornado
        versions prior to 4.0 must use `add_timeout` instead.

        .. versionchanged:: 4.0
           Now passes through ``*args`` and ``**kwargs`` to the callback.
        Unsupported deadline %r)	r9   numbersRealcall_atdatetime	timedeltar   total_seconds	TypeError)r    r   r   r   r5   s        r!   r   zIOLoop.add_timeout+  s    @ h-4<<(DTDVDD("4"454<<		h4466CGKQ  5@AAr$   delayc                 R     | j                   | j                         |z   |g|i |S )a  Runs the ``callback`` after ``delay`` seconds have passed.

        Returns an opaque handle that may be passed to `remove_timeout`
        to cancel.  Note that unlike the `asyncio` method of the same
        name, the returned object does not have a ``cancel()`` method.

        See `add_timeout` for comments on thread-safety and subclassing.

        .. versionadded:: 4.0
        )r   r   )r    r   r   r   r5   s        r!   
call_laterzIOLoop.call_laterT  s,     t||DIIK%/KDKFKKr$   whenc                 0     | j                   ||g|i |S )a  Runs the ``callback`` at the absolute time designated by ``when``.

        ``when`` must be a number using the same reference point as
        `IOLoop.time`.

        Returns an opaque handle that may be passed to `remove_timeout`
        to cancel.  Note that unlike the `asyncio` method of the same
        name, the returned object does not have a ``cancel()`` method.

        See `add_timeout` for comments on thread-safety and subclassing.

        .. versionadded:: 4.0
        )r   )r    r   r   r   r5   s        r!   r   zIOLoop.call_atc  s#       th@@@@r$   c                     t               )zCancels a pending timeout.

        The argument is a handle as returned by `add_timeout`.  It is
        safe to call `remove_timeout` even if the callback has already
        been run.
        ra   )r    r   s     r!   r   zIOLoop.remove_timeoutu  r}   r$   c                     t               )a  Calls the given callback on the next I/O loop iteration.

        It is safe to call this method from any thread at any time,
        except from a signal handler.  Note that this is the **only**
        method in `IOLoop` that makes this thread-safety guarantee; all
        other interaction with the `IOLoop` must be done from that
        `IOLoop`'s thread.  `add_callback()` may be used to transfer
        control from other threads to the `IOLoop`'s thread.
        ra   r    r   r   r5   s       r!   r   zIOLoop.add_callback~  s     "##r$   c                     t               )a  Calls the given callback on the next I/O loop iteration.

        Intended to be afe for use from a Python signal handler; should not be
        used otherwise.

        .. deprecated:: 6.4
           Use ``asyncio.AbstractEventLoop.add_signal_handler`` instead.
           This method is suspected to have been broken since Tornado 5.0 and
           will be removed in version 7.0.
        ra   r   s       r!   add_callback_from_signalzIOLoop.add_callback_from_signal  s     "##r$   c                 0     | j                   |g|i | y)zCalls the given callback on the next IOLoop iteration.

        As of Tornado 6.0, this method is equivalent to `add_callback`.

        .. versionadded:: 4.0
        Nr   r   s       r!   spawn_callbackzIOLoop.spawn_callback  s     	(4T4V4r$   r   z0Union[Future[_T], concurrent.futures.Future[_T]]z
Future[_T]c                      t        |t              r|j                   fd       yt        |      sJ t	        | fd       y)aA  Schedules a callback on the ``IOLoop`` when the given
        `.Future` is finished.

        The callback is invoked with one argument, the
        `.Future`.

        This method only accepts `.Future` objects and not other
        awaitables (unlike most of Tornado where the two are
        interchangeable).
        c                 N    j                  t        j                  |             S r   )_run_callback	functoolspartialfr   r    s    r!   r   z#IOLoop.add_future.<locals>.<lambda>  s    $,,Y->->x-KLr$   c                 (    j                  |       S r   r   r   s    r!   r   z#IOLoop.add_future.<locals>.<lambda>  s    t7H7HST7Ur$   N)r9   r   add_done_callbackr   r   )r    r   r   s   ` `r!   r   zIOLoop.add_future  s?     ff% $$L V$$$ %V-UVr$   executor.c                    |Kt        | d      s3ddlm} t        j                  j                   |       dz        | _        | j                  } |j                  |g| }t               | j                  |fd       S )zRuns a function in a ``concurrent.futures.Executor``. If
        ``executor`` is ``None``, the IO loop's default executor will be used.

        Use `functools.partial` to pass keyword arguments to ``func``.

        .. versionadded:: 5.0
        	_executorr   )	cpu_count   )max_workersc                     t        |       S r   )r   )r   t_futures    r!   r   z(IOLoop.run_in_executor.<locals>.<lambda>  s    LH,Er$   )
hasattrtornado.processr   
concurrentfuturesThreadPoolExecutorr   submitr   r   )r    r   r   r   r   c_futurer   s         @r!   run_in_executorzIOLoop.run_in_executor  s|     4-5!+!3!3!F!F!*q "G " ~~H"8??4/$/ 8"EFr$   c                     || _         y)zfSets the default executor to use with :meth:`run_in_executor`.

        .. versionadded:: 5.0
        N)r   )r    r   s     r!   set_default_executorzIOLoop.set_default_executor  s    
 "r$   c                 "   	  |       }|5ddl m} 	 |j                  |      }| j                  || j                         yy# |j
                  $ r Y yw xY w# t        j                  $ r Y yt        $ r t        j                  d|d       Y yw xY w)zRuns a callback with error handling.

        .. versionchanged:: 6.0

           CancelledErrors are no longer logged.
        Nr   )genException in callback %rTr   )tornador   r   r   _discard_future_resultBadYieldErrorrQ   CancelledErrorr   r	   error)r    r   retr   s       r!   r   zIOLoop._run_callback  s    	O*C'F--c2C OOC)D)DE  ((  	 %% 	 	OMM4hN	Os9   A A A AA AA B+ BBc                 $    |j                          y)z;Avoid unhandled-exception warnings from spawned coroutines.N)r   )r    r   s     r!   r   zIOLoop._discard_future_result  s    r$   c                 N    t        |t              r||fS |j                         |fS r   )r9   r+   r"   r   s     r!   split_fdzIOLoop.split_fd  s'    $ b#r6Myy{Br$   c                     	 t        |t              rt        j                  |       y |j                          y # t        $ r Y y w xY wr   )r9   r+   osr&   OSErrorr   s     r!   close_fdzIOLoop.close_fd  s7    	"c"
 		s   %9 9 	AAr   c                 :    | j                   j                  |       y r   )_pending_tasksaddr    r   s     r!   _register_taskzIOLoop._register_task2  s    "r$   c                 :    | j                   j                  |       y r   )r   discardr   s     r!   _unregister_taskzIOLoop._unregister_task5  s    ##A&r$   )r   r0   r'   )T)Fr   )Jr(   r)   r*   __doc__NONEREADWRITEERRORdictrU   setr   classmethodr   r?   staticmethodrD   rG   rJ   typingoverloadrC   boolr   rF   r_   rI   rd   rf   r   r
   rj   rm   ro   r&   r+   r   rw   r-   r   r   r|   r   r   r   floatr   r   r   r   objectr   r   r   r   r   r   r   r   r   r   Executorr,   r   r   r   r   r   r   r   r   r   r   __classcell__)rA   s   @r!   r0   r0   H   sE   Nb DDEE & UN	59	5EH	5		5 	5    *   __   __$ (8*<    *$ *(8*< * *X6$      & &
 $|"4   T,%7  
!t !t !$T $d $6 __ (#sT)9 :DG	 
 __'S	48BE	 
$[()$4<Y4G$QT$	$&$sK'7!8 $# $$ $$sK'7!8 $T $$$J'X J' J'3 J'Xe 'Bx1112'B 'B 	'B
 'B 
'BRLL&.L7:LFIL	LAA%-A69AEHA	A$$f $ $
$X 
$c 
$S 
$T 
$$ $),$8;$	$5x 5 5s 5t 5WBW L>4/0W 
	WB:--667 sBw 	
 
8"Z-?-?-H-H "T "Ohr3w&7 OD O<V  [()	sE#{*++	,,5k!12 t (# #4 #'& 'T 'r$   r0   c                   Z    e Zd ZdZg dZdedeg df   deddfdZd	d de	fd
Z
d	d de	fdZy)_Timeoutz2An IOLoop timeout, a UNIX timestamp and a callback)r   r   	tdeadliner   r   Nio_loopr   c                     t        |t        j                        st        d|z        || _        || _        |t        |j                        f| _        y )Nr   )	r9   r   r   r   r   r   next_timeout_counterr  )r    r   r   r  s       r!   __init__z_Timeout.__init__?  sK     (GLL15@AA  ))*
r$   otherc                 4    | j                   |j                   k  S r   r  r    r  s     r!   __lt__z_Timeout.__lt__O  s    ~~//r$   c                 4    | j                   |j                   k  S r   r
  r  s     r!   __le__z_Timeout.__le__R  s    ~~00r$   )r(   r)   r*   r   	__slots__r   r   r0   r  r   r  r  r   r$   r!   r  r  9  s`    < 6I



)1"d();

FL

	

 0J 04 01J 14 1r$   r  c            	           e Zd ZdZ	 ddeg ee   f   deej                  e
f   de
ddfdZddZdd	Zdefd
ZddZddZde
ddfdZy)PeriodicCallbacka  Schedules the given callback to be called periodically.

    The callback is called every ``callback_time`` milliseconds when
    ``callback_time`` is a float. Note that the timeout is given in
    milliseconds, while most other time-related functions in Tornado use
    seconds. ``callback_time`` may alternatively be given as a
    `datetime.timedelta` object.

    If ``jitter`` is specified, each callback time will be randomly selected
    within a window of ``jitter * callback_time`` milliseconds.
    Jitter can be used to reduce alignment of events with similar periods.
    A jitter of 0.1 means allowing a 10% variation in callback time.
    The window is centered on ``callback_time`` so the total number of calls
    within a given interval should not be significantly affected by adding
    jitter.

    If the callback runs for longer than ``callback_time`` milliseconds,
    subsequent invocations will be skipped to get back on schedule.

    `start` must be called after the `PeriodicCallback` is created.

    .. versionchanged:: 5.0
       The ``io_loop`` argument (deprecated since version 4.1) has been removed.

    .. versionchanged:: 5.1
       The ``jitter`` argument is added.

    .. versionchanged:: 6.2
       If the ``callback`` argument is a coroutine, and a callback runs for
       longer than ``callback_time``, subsequent invocations will be skipped.
       Previously this was only true for regular functions, not coroutines,
       which were "fire-and-forget" for `PeriodicCallback`.

       The ``callback_time`` argument now accepts `datetime.timedelta` objects,
       in addition to the previous numeric milliseconds.
    r   callback_timejitterr   Nc                     || _         t        |t        j                        r|t        j                  d      z  | _        n|dk  rt        d      || _        || _        d| _        d | _        y )Nr1   )millisecondsr   z4Periodic callback must have a positive callback_timeF)	r   r9   r   r   r  
ValueErrorr  _running_timeout)r    r   r  r  s       r!   r  zPeriodicCallback.__init__|  se     !mX%7%78!.1C1CQR1S!SD! !WXX!.Dr$   c                     t         j                         | _        d| _        | j                  j	                         | _        | j                          y)zStarts the timer.TN)r0   rC   r  r  r   _next_timeout_schedule_nextr   s    r!   r   zPeriodicCallback.start  s:    
 ~~'!\\..0r$   c                     d| _         | j                  -| j                  j                  | j                         d| _        yy)zStops the timer.FN)r  r  r  r   r   s    r!   r   zPeriodicCallback.stop  s5    ==$LL''6 DM %r$   c                     | j                   S )zfReturns ``True`` if this `.PeriodicCallback` has been started.

        .. versionadded:: 4.1
        )r  r   s    r!   
is_runningzPeriodicCallback.is_running  s    
 }}r$   c                 &  K   | j                   sy 	 | j                         }|t        |      r
| d {    | j                          y 7 # t        $ r% t	        j
                  d| j                  d       Y @w xY w# | j                          w xY ww)Nr   Tr   )r  r   r   r   r	   r   r  )r    vals     r!   _runzPeriodicCallback._run  sz     }}	"--/C;s#3		 !	  	TMM4dmmdS	T !sC   B"A A	A B	A +A96A< 8A99A< <BBc                     | j                   r_| j                  | j                  j                                | j                  j	                  | j
                  | j                        | _        y y r   )r  _update_nextr  r   r   r  r!  r  r   s    r!   r  zPeriodicCallback._schedule_next  sK    ==dll//12 LL44T5G5GSDM r$   current_timec                 T   | j                   dz  }| j                  r*|d| j                  t        j                         dz
  z  z   z  }| j                  |k  r?| xj                  t	        j
                  || j                  z
  |z        dz   |z  z  c_        y | xj                  |z  c_        y )Ng     @@r1   g      ?)r  r  randomr  mathfloor)r    r$  callback_time_secs      r!   r#  zPeriodicCallback._update_next  s     ..7;;dkkV]]_s5J&K!LL-
 

L4+=+==ARRSVWW!#" "$ "33r$   )r   r'   )r(   r)   r*   r   r   r   r   r   r   r   r   r  r   r   r   r  r!  r  r#  r   r$   r!   r  r  V  s    #R 	2x	223 X//67 	
 
"!D 
"T
4 44 4r$   r  )1r   rQ   concurrent.futuresr   r   r   r   r   r   r   r'  r&  r\   inspectr   tornado.concurrentr   r   r   r   r   tornado.logr	   tornado.utilr
   r   r   r   r   r   r   r   r   r   r   r   TYPE_CHECKINGr   r   r   typing_extensionsr   r   r   r,   r-   r0   r  r  r   r$   r!   <module>r1     s          	 
         B B  R R R	&&*H(  T]T%n'\ n'b1v 1:|4v |4r$   