o
    )Zhҏ                     @   sX  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j$r~ddlm%Z%m&Z&m'Z' dd	l(m)Z) ne*Z)G d
d de)Z+e!dZ,e!de+dZ-G dd deZ.G dd de*Z/G dd de*Z0dS )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                   @   s$   e Zd ZdefddZdddZdS )_Selectablereturnc                 C      d S N selfr   r   E/var/www/html/lang_env/lib/python3.10/site-packages/tornado/ioloop.pyfileno=      z_Selectable.filenoNc                 C   r   r   r   r   r   r   r   close@   r!   z_Selectable.closer   N)__name__
__module____qualname__intr    r"   r   r   r   r   r   <   s    r   _T_S)boundc                
       s   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dZedoddZdpddZedpddZejedoddZejedqded	ed  fddZedqded	ed  fddZdpddZdpddZedpddZedpdd Zdpd!d"Zed	ee fd#d$Zed	ee fd%d&Z dqd'ed	d
fd(d)Z!drd+ed	d
fd,d-Z"ejd.e#d/e$e#e#gd
f d0e#d	d
fd1d2Z%ejd.e&d/e$e&e#gd
f d0e#d	d
fd3d2Z%d.e'e#e(f d/e$d4 d0e#d	d
fd5d2Z%d.e'e#e(f d0e#d	d
fd6d7Z)d.e'e#e(f d	d
fd8d9Z*dpd:d;Z+dpd<d=Z,dsd>e$d?ee- d	efd@dAZ.d	e-fdBdCZ/dDe'e-e0j1f dEe$dFeded	e2f
dGdHZ3dIe-dEe$dFeded	e2f
dJdKZ4dLe-dEe$dFeded	e2f
dMdNZ5d?e2d	d
fdOdPZ6dEe$dFeded	d
fdQdRZ7dEe$dFeded	d
fdSdTZ8dEe$dFeded	d
fdUdVZ9dWdXdEe$dYgd
f d	d
fdZd[Z:d\ee;j<j= d>e$d]e>f dFed	dYfd^d_Z?d\e;j<j=d	d
fd`daZ@dEe$g ef d	d
fdbdcZAdWeBd	d
fdddeZCd.e'e#e(f d	eDe#e'e#e(f f fdfdgZEd.e'e#e(f d	d
fdhdiZFdjeBd	d
fdkdlZGdjeBd	d
fdmdnZH  ZIS )t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                    sV   ddl m} t|trt|}t|trt||stdtt	| j
|fi | d S )Nr   )BaseAsyncIOLoopz5only AsyncIOLoop is allowed when asyncio is available)tornado.platform.asyncior1   
isinstancestrr   type
issubclassRuntimeErrorsuperr+   	configure)clsr/   r0   r1   	__class__r   r   r9      s   
zIOLoop.configurec                   C   s   t  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
        )r+   currentr   r   r   r   instance   s   zIOLoop.instancec                 C   s   |    dS )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   r   r   r   install   s   zIOLoop.installc                   C   s   t   dS )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)r+   clear_currentr   r   r   r   clear_instance   s   zIOLoop.clear_instancec                   C   r   r   r   r   r   r   r   r=         zIOLoop.currentTr>   c                 C   r   r   r   r>   r   r   r   r=      rC   c                 C   s~   zt  }W n ty   | sY dS t  }t | Y nw ztj| W S  ty>   | r9ddlm	} | }Y |S d}Y |S 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)
asyncioZget_event_loopr7   Znew_event_loopZset_event_loopr+   _ioloop_for_asyncioKeyErrorr2   rE   )r>   looprE   r=   r   r   r   r=      s$   c                 C   s   t jdtdd |   dS )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   r   r   r   r?   %  s   zIOLoop.make_currentc                 C      t  r   NotImplementedErrorr   r   r   r   rP   @  s   zIOLoop._make_currentc                   C   s   t jdtdd t  dS )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 deprecatedrJ   rK   N)rM   rN   rO   r+   _clear_currentr   r   r   r   rA   D  s   
zIOLoop.clear_currentc                  C   s$   t jdd} | d ur|   d S d S )NFrD   )r+   r=   _clear_current_hook)oldr   r   r   rT   U  s   zIOLoop._clear_currentc                 C   s   dS )zInstance method called when an IOLoop ceases to be current.

        May be overridden by subclasses as a counterpart to make_current.
        Nr   r   r   r   r   rU   [  s   zIOLoop._clear_current_hookc                 C   s   t S r   )r+   )r:   r   r   r   configurable_baseb  s   zIOLoop.configurable_basec                 C   s   ddl m} |S )Nr   )AsyncIOLoop)r2   rX   )r:   rX   r   r   r   configurable_defaultf  s   zIOLoop.configurable_defaultr?   c                 C   s   |r|    d S d S r   )rP   )r   r?   r   r   r   
initializel  s   zIOLoop.initializeFall_fdsc                 C   rQ   )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.
        rR   )r   r[   r   r   r   r"   p  s   zIOLoop.closefdhandlereventsc                 C   r   r   r   r   r\   r]   r^   r   r   r   add_handler     zIOLoop.add_handlerc                 C   r   r   r   r_   r   r   r   r`     ra   ).Nc                 C   rQ   )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.
        rR   r_   r   r   r   r`     s   c                 C   rQ   )zChanges the events we listen for ``fd``.

        .. versionchanged:: 4.0
           Added the ability to pass file-like objects in addition to
           raw file descriptors.
        rR   )r   r\   r^   r   r   r   update_handler     zIOLoop.update_handlerc                 C   rQ   )zStop listening for events on ``fd``.

        .. versionchanged:: 4.0
           Added the ability to pass file-like objects in addition to
           raw file descriptors.
        rR   r   r\   r   r   r   remove_handler  rc   zIOLoop.remove_handlerc                 C   rQ   )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.
        rR   r   r   r   r   start  s   zIOLoop.startc                 C   rQ   )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.
        rR   r   r   r   r   stop  s   zIOLoop.stopfunctimeoutc                    s   dgd	 fdd} | |dur'd	fdd} | |}  |dur4| d dus<J d  sHd  sNtd| d  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``.
        Nr   c                     s   z  } | d urddl m} || } W n ty*   t }|d< t|t  Y nw t| r4| d< nt }|d< ||  d d usHJ 	d fdd d S )Nr   )convert_yieldedc                    s      S r   )rg   )futurer   r   r   <lambda>  s    z.IOLoop.run_sync.<locals>.run.<locals>.<lambda>)
Ztornado.genrj   	Exceptionr   r   sysexc_infor   Z
set_result
add_future)resultrj   Zfutrh   future_cellr   r   r   run  s$   

zIOLoop.run_sync.<locals>.runc                      s,    d d usJ  d   s  d S d S )Nr   )cancelrg   r   )rs   r   r   r   timeout_callback  s   z)IOLoop.run_sync.<locals>.timeout_callbackr   z$Operation timed out after %s secondsr#   )	add_callbackadd_timeouttimerf   remove_timeoutZ	cancelleddoner
   rq   )r   rh   ri   rt   rv   Ztimeout_handler   rr   r   run_sync  s    
	
zIOLoop.run_syncc                 C   s   t   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`.

        )ry   r   r   r   r   ry     s   zIOLoop.timedeadlinecallbackargsc                 O   sd   t |tjr| j||g|R i |S t |tjr,| j|  |  |g|R i |S td| )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)	r3   numbersRealcall_atdatetime	timedeltary   total_seconds	TypeError)r   r}   r~   r   r0   r   r   r   rx   +  s    zIOLoop.add_timeoutdelayc                 O   s"   | j |  | |g|R 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   ry   )r   r   r~   r   r0   r   r   r   
call_laterT  s   "zIOLoop.call_laterwhenc                 O   s   | j ||g|R 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
        )rx   )r   r   r~   r   r0   r   r   r   r   c  s   zIOLoop.call_atc                 C   rQ   )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.
        rR   )r   ri   r   r   r   rz   u  rc   zIOLoop.remove_timeoutc                 O   rQ   )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.
        rR   r   r~   r   r0   r   r   r   rw   ~  s   
zIOLoop.add_callbackc                 O   rQ   )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.
        rR   r   r   r   r   add_callback_from_signal  s   zIOLoop.add_callback_from_signalc                 O   s   | j |g|R i | dS )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rw   r   r   r   r   spawn_callback  s   zIOLoop.spawn_callbackrk   z0Union[Future[_T], concurrent.futures.Future[_T]]z
Future[_T]c                    sF   t |tr| fdd dS t|sJ t| fdd dS )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                    s    t | S r   )_run_callback	functoolspartialfr~   r   r   r   rl     s    z#IOLoop.add_future.<locals>.<lambda>c                    s     | S r   r   r   r   r   r   rl     s    N)r3   r   Zadd_done_callbackr   r   )r   rk   r~   r   r   r   rp     s   
	zIOLoop.add_futureexecutor.c                    sj   |du rt | dsddlm} tjj| d d| _| j}|j|g|R  }t  | 	| fd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
        N	_executorr   )	cpu_count   )max_workersc                    s
   t |  S r   )r   r   Zt_futurer   r   rl     s   
 z(IOLoop.run_in_executor.<locals>.<lambda>)
hasattrZtornado.processr   
concurrentfuturesZThreadPoolExecutorr   Zsubmitr   rp   )r   r   rh   r   r   Zc_futurer   r   r   run_in_executor  s   
zIOLoop.run_in_executorc                 C   s
   || _ dS )zfSets the default executor to use with :meth:`run_in_executor`.

        .. versionadded:: 5.0
        N)r   )r   r   r   r   r   set_default_executor  s   
zIOLoop.set_default_executorc                 C   s   z.| }|dur,ddl m} z||}W n |jy!   Y W dS w | || j W dS W dS  tjy9   Y dS  tyJ   t	j
d|dd Y dS w )zRuns a callback with error handling.

        .. versionchanged:: 6.0

           CancelledErrors are no longer logged.
        Nr   )genException in callback %rTro   )tornador   rj   ZBadYieldErrorrp   _discard_future_resultrF   ZCancelledErrorrm   r   error)r   r~   retr   r   r   r   r     s    zIOLoop._run_callbackc                 C   s   |   dS )z;Avoid unhandled-exception warnings from spawned coroutines.N)rq   )r   rk   r   r   r   r     s   zIOLoop._discard_future_resultc                 C   s   t |tr	||fS | |fS r   )r3   r'   r    rd   r   r   r   split_fd  s   
zIOLoop.split_fdc                 C   s>   zt |trt| W d S |  W d S  ty   Y d S w r   )r3   r'   osr"   OSErrorrd   r   r   r   close_fd  s   
zIOLoop.close_fdr   c                 C      | j | d S r   )_pending_tasksaddr   r   r   r   r   _register_task2     zIOLoop._register_taskc                 C   r   r   )r   discardr   r   r   r   _unregister_task5  r   zIOLoop._unregister_task)r   r+   r#   )T)Fr   )Jr$   r%   r&   __doc__NONEREADWRITEERRORdictrG   setr   classmethodr   r9   staticmethodr>   r@   rB   typingoverloadr=   boolr   r?   rP   rA   rT   rU   r   r	   rW   rY   rZ   r"   r'   r   r`   r)   r   r   rb   re   rf   rg   floatr|   ry   r   r   objectrx   r   r   rz   rw   r   r   rp   r   r   ZExecutorr(   r   r   r   r   r   r   r   r   r   r   __classcell__r   r   r;   r   r+   H   s*   Q

,



	
	
L
)

	
	
!




r+   c                   @   s^   e Zd ZdZg dZdedeg df deddfdd	Zd
d de	fddZ
d
d de	fddZdS )_Timeoutz2An IOLoop timeout, a UNIX timestamp and a callback)r}   r~   	tdeadliner}   r~   Nio_loopr   c                 C   s8   t |tjstd| || _|| _|t|jf| _d S )Nr   )	r3   r   r   r   r}   r~   nextZ_timeout_counterr   )r   r}   r~   r   r   r   r   __init__?  s   
z_Timeout.__init__otherc                 C   s   | j |j k S r   r   r   r   r   r   r   __lt__O     z_Timeout.__lt__c                 C   s   | j |j kS r   r   r   r   r   r   __le__R  r   z_Timeout.__le__)r$   r%   r&   r   	__slots__r   r   r+   r   r   r   r   r   r   r   r   r   9  s    

r   c                	   @   s   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d	Zdd
dZdddZdefddZdddZdddZde
ddfddZdS )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   r~   callback_timejitterr   Nc                 C   sR   || _ t|tjr|tjdd | _n|dkrtd|| _|| _d| _d | _d S )Nr,   )Zmillisecondsr   z4Periodic callback must have a positive callback_timeF)	r~   r3   r   r   r   
ValueErrorr   _running_timeout)r   r~   r   r   r   r   r   r   |  s   
zPeriodicCallback.__init__c                 C   s(   t  | _d| _| j | _|   dS )zStarts the timer.TN)r+   r=   r   r   ry   _next_timeout_schedule_nextr   r   r   r   rf     s   
zPeriodicCallback.startc                 C   s,   d| _ | jdur| j| j d| _dS dS )zStops the timer.FN)r   r   r   rz   r   r   r   r   rg     s
   

zPeriodicCallback.stopc                 C   s   | j S )zfReturns ``True`` if this `.PeriodicCallback` has been started.

        .. versionadded:: 4.1
        )r   r   r   r   r   
is_running  s   zPeriodicCallback.is_runningc                    s   | j sd S z4z|  }|d urt|r|I d H  W n ty,   tjd| jdd Y nw W |   d S W |   d S |   w )Nr   Tr   )r   r~   r   rm   r   r   r   )r   valr   r   r   _run  s   
zPeriodicCallback._runc                 C   s2   | j r| | j  | j| j| j| _d S d S r   )r   _update_nextr   ry   rx   r   r   r   r   r   r   r   r     s   zPeriodicCallback._schedule_nextcurrent_timec                 C   sp   | j d }| jr|d| jt d   9 }| j|kr/|  jt|| j | d | 7  _d S |  j|7  _d S )Ng     @@r,   g      ?)r   r   randomr   mathfloor)r   r   Zcallback_time_secr   r   r   r     s   

zPeriodicCallback._update_next)r   r#   )r$   r%   r&   r   r   r   r   r   r   r   r   r   rf   rg   r   r   r   r   r   r   r   r   r   r   V  s$    )





r   )1r   rF   concurrent.futuresr   r   r   r   r   rn   ry   r   r   rM   inspectr   Ztornado.concurrentr   r   r   r   r   Ztornado.logr   Ztornado.utilr	   r
   r   r   r   r   r   r   r   r   r   r   TYPE_CHECKINGr   r   r   typing_extensionsr   r   r   r(   r)   r+   r   r   r   r   r   r   <module>   sB   
(     v