HEX
Server: Apache/2.4.52 (Ubuntu)
System: Linux spn-python 5.15.0-89-generic #99-Ubuntu SMP Mon Oct 30 20:42:41 UTC 2023 x86_64
User: arjun (1000)
PHP: 8.1.2-1ubuntu2.20
Disabled: NONE
Upload Files
File: //home/arjun/projects/env/lib/python3.10/site-packages/tornado/__pycache__/ioloop.cpython-310.pyc
o

weҏ�@sXdZddlZddlZddlZddlZddlZddlZddlZddl	Z	ddl
Z
ddlZddlZddl
mZddlmZmZmZmZmZddlmZddlmZmZmZddlZddlmZmZmZmZm Z m!Z!m"Z"m#Z#ej$r~ddlm%Z%m&Z&m'Z'dd	l(m)Z)ne*Z)Gd
d�de)�Z+e!d�Z,e!d
e+d�Z-Gdd�de�Z.Gdd�de*�Z/Gdd�de*�Z0dS)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$eZdZdefdd�Zddd�ZdS)�_Selectable�returncC�dS�N���selfrr�G/home/arjun/projects/env/lib/python3.10/site-packages/tornado/ioloop.py�fileno=�z_Selectable.filenoNcCrrrrrrr�close@r!z_Selectable.close�rN)�__name__�
__module__�__qualname__�intr r"rrrrr<sr�_T�_S)�boundc
seZdZdZdZdZdZdZe�Z	e
�Zeddde
d	d
f�fdd��Zedod
d��Zdpdd�Zedpdd��Zejedodd���Zejedqded	edfdd���Zedqded	edfdd��Zdpdd�Zdpdd�Zedpdd��Zedpdd ��Zdpd!d"�Zed	eefd#d$��Zed	eefd%d&��Z dqd'ed	d
fd(d)�Z!drd+ed	d
fd,d-�Z"ejd.e#d/e$e#e#gd
fd0e#d	d
fd1d2��Z%ejd.e&d/e$e&e#gd
fd0e#d	d
fd3d2��Z%d.e'e#e(fd/e$d4d0e#d	d
fd5d2�Z%d.e'e#e(fd0e#d	d
fd6d7�Z)d.e'e#e(fd	d
fd8d9�Z*dpd:d;�Z+dpd<d=�Z,dsd>e$d?ee-d	e
fd@dA�Z.d	e-fdBdC�Z/dDe'e-e0j1fdEe$dFe
de
d	e2f
dGdH�Z3dIe-dEe$dFe
de
d	e2f
dJdK�Z4dLe-dEe$dFe
de
d	e2f
dMdN�Z5d?e2d	d
fdOdP�Z6dEe$dFe
de
d	d
fdQdR�Z7dEe$dFe
de
d	d
fdSdT�Z8dEe$dFe
de
d	d
fdUdV�Z9dWdXdEe$dYgd
fd	d
fdZd[�Z:d\ee;j<j=d>e$d]e>fdFe
d	dYfd^d_�Z?d\e;j<j=d	d
fd`da�Z@dEe$ge
fd	d
fdbdc�ZAdWeBd	d
fddde�ZCd.e'e#e(fd	eDe#e'e#e(fffdfdg�ZEd.e'e#e(fd	d
fdhdi�ZFdjeBd	d
fdkdl�ZGdjeBd	d
fdmdn�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]]�kwargsrNcsVddlm}t|t�rt|�}t|t�rt||�std��tt	|�j
|fi|��dS)Nr)�BaseAsyncIOLoopz5only AsyncIOLoop is allowed when asyncio is available)�tornado.platform.asyncior1�
isinstance�strr�type�
issubclass�RuntimeError�superr+�	configure)�clsr/r0r1��	__class__rrr9�s
zIOLoop.configurecCst��S)aKDeprecated 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+�currentrrrr�instance�szIOLoop.instancecCs|��dS)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_currentrrrr�install�szIOLoop.installcCst��dS)akDeprecated 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_currentrrrr�clear_instance�szIOLoop.clear_instancecCrrrrrrrr=��zIOLoop.currentTr>cCrrr�r>rrrr=�rCcCs~zt��}Wnty|sYdSt��}t�|�Ynwztj|WSty>|r9ddlm	}|�}Y|Sd}Y|Sw)aCReturns 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_loopr7�new_event_loop�set_event_loopr+�_ioloop_for_asyncio�KeyErrorr2rE)r>�looprEr=rrrr=�s$���cCstjdtdd�|��dS)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_currentrrrrr?%s�zIOLoop.make_currentcC�t��r��NotImplementedErrorrrrrrS@szIOLoop._make_currentcCstjdtdd�t��dS)z�Clears 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
        zclear_current is deprecatedrMrNN)rPrQrRr+�_clear_currentrrrrrADs
�zIOLoop.clear_currentcCs$tjdd�}|dur|��dSdS)NFrD)r+r=�_clear_current_hook)�oldrrrrWUs�zIOLoop._clear_currentcCsdS)z�Instance method called when an IOLoop ceases to be current.

        May be overridden by subclasses as a counterpart to make_current.
        NrrrrrrX[szIOLoop._clear_current_hookcCstSr)r+)r:rrr�configurable_basebszIOLoop.configurable_basecCsddlm}|S)Nr)�AsyncIOLoop)r2r[)r:r[rrr�configurable_defaultfszIOLoop.configurable_defaultr?cCs|r|��dSdSr)rS)rr?rrr�
initializels�zIOLoop.initializeF�all_fdscCrT)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.
        rU)rr^rrrr"pszIOLoop.close�fd�handler�eventscCrrr�rr_r`rarrr�add_handler��zIOLoop.add_handlercCrrrrbrrrrc�rd).NcCrT)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.
        rUrbrrrrc�scCrT)z�Changes the events we listen for ``fd``.

        .. versionchanged:: 4.0
           Added the ability to pass file-like objects in addition to
           raw file descriptors.
        rU)rr_rarrr�update_handler��zIOLoop.update_handlercCrT)z�Stop listening for events on ``fd``.

        .. versionchanged:: 4.0
           Added the ability to pass file-like objects in addition to
           raw file descriptors.
        rU�rr_rrr�remove_handler�rfzIOLoop.remove_handlercCrT)z�Starts 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.
        rUrrrr�start�szIOLoop.startcCrT)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.
        rUrrrr�stop�szIOLoop.stop�func�timeoutcs�dg�d	���fdd�}��|�|dur'd	��fdd�}�����||�}���|dur4��|��ddus<J��d��sH�d��sNtd|���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``.
        Nrcs�z��}|durddlm}||�}Wnty*t�}|�d<t|t���Ynwt|�r4|�d<nt�}|�d<|�|��ddusHJ���	�d�fdd��dS)Nr)�convert_yieldedcs���Sr)rj)�futurerrr�<lambda>sz.IOLoop.run_sync.<locals>.run.<locals>.<lambda>)
�tornado.genrm�	Exceptionrr�sys�exc_infor�
set_result�
add_future)�resultrm�fut�rk�future_cellrrr�run�s$��

zIOLoop.run_sync.<locals>.runcs,�ddusJ��d��s���dSdS)Nr)�cancelrjr)ryrrr�timeout_callbacks�z)IOLoop.run_sync.<locals>.timeout_callbackrz$Operation timed out after %s secondsr#)	�add_callback�add_timeout�timeri�remove_timeout�	cancelled�doner
rv)rrkrlrzr|�timeout_handlerrxr�run_sync�s 
	
zIOLoop.run_synccCst��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`.

        )rrrrrrszIOLoop.time�deadline�callback�argscOsdt|tj�r|j||g|�Ri|��St|tj�r,|j|��|��|g|�Ri|��Std|��)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�	timedeltar�
total_seconds�	TypeError)rr�r�r�r0rrrr~+s ���zIOLoop.add_timeout�delaycOs"|j|��||g|�Ri|��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)rr�r�r�r0rrr�
call_laterTs"
zIOLoop.call_later�whencOs|j||g|�Ri|��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~)rr�r�r�r0rrrr�cszIOLoop.call_atcCrT)z�Cancels 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.
        rU)rrlrrrr�urfzIOLoop.remove_timeoutcOrT)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.
        rU�rr�r�r0rrrr}~s
zIOLoop.add_callbackcOrT)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.
        rUr�rrr�add_callback_from_signal�s
zIOLoop.add_callback_from_signalcOs|j|g|�Ri|��dS)z�Calls 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�rrr�spawn_callback�szIOLoop.spawn_callbackrnz0Union[Future[_T], concurrent.futures.Future[_T]]z
Future[_T]csFt|t�r|���fdd��dSt|�sJ�t|��fdd��dS)aASchedules 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).
        cs��t��|��Sr)�
_run_callback�	functools�partial��f�r�rrrro�sz#IOLoop.add_future.<locals>.<lambda>cs���|�Srr�r�r�rrro�sN)r3r�add_done_callbackrr)rrnr�rr�rru�s
	�zIOLoop.add_future�executor.csj|durt|d�sddlm}tjj|�dd�|_|j}|j|g|�R�}t��|�	|�fdd���S)	z�Runs 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_workerscs
t|��Sr)rr���t_futurerrro�s
z(IOLoop.run_in_executor.<locals>.<lambda>)
�hasattr�tornado.processr��
concurrent�futures�ThreadPoolExecutorr��submitrru)rr�rkr�r��c_futurerr�r�run_in_executor�s
�zIOLoop.run_in_executorcCs
||_dS)zfSets the default executor to use with :meth:`run_in_executor`.

        .. versionadded:: 5.0
        N)r�)rr�rrr�set_default_executor�s
zIOLoop.set_default_executorcCs�z.|�}|dur,ddlm}z|�|�}Wn|jy!YWdSw|�||j�WdSWdStjy9YdStyJt	j
d|dd�YdSw)z�Runs a callback with error handling.

        .. versionchanged:: 6.0

           CancelledErrors are no longer logged.
        Nr)�gen�Exception in callback %rT�rs)�tornador�rm�
BadYieldErrorru�_discard_future_resultrF�CancelledErrorrqr�error)rr��retr�rrrr��s ���zIOLoop._run_callbackcCs|��dS)z;Avoid unhandled-exception warnings from spawned coroutines.N)rv)rrnrrrr�szIOLoop._discard_future_resultcCst|t�r	||fS|��|fSr)r3r'r rgrrr�split_fds
zIOLoop.split_fdcCs>zt|t�rt�|�WdS|��WdStyYdSwr)r3r'�osr"�OSErrorrgrrr�close_fds
�zIOLoop.close_fdr�cC�|j�|�dSr)�_pending_tasks�add�rr�rrr�_register_task2�zIOLoop._register_taskcCr�r)r��discardr�rrr�_unregister_task5r�zIOLoop._unregister_task)rr+r#)T)Fr)Jr$r%r&�__doc__�NONE�READ�WRITE�ERROR�dictrJ�setr��classmethodr
r9�staticmethodr>r@rB�typing�overloadr=�boolrr?rSrArWrXrr	rZr\r]r"r'rrcr)rrrerhrirj�floatr�rr�r��objectr~r�r�r�r}r�r�rur�r��Executorr(r�r�r�rr�rr�r�r�r��
__classcell__rrr;rr+Hs*Q���

,

��������
���
�	
	

L����
�)����
�����
�	���
�	��
�!
�
��
�
�
�r+c@s^eZdZdZgd�Zdedegdfdeddfdd	�Zd
dde	fdd�Z
d
dde	fd
d�ZdS)�_Timeoutz2An IOLoop timeout, a UNIX timestamp and a callback)r�r��	tdeadliner�r�N�io_looprcCs8t|tj�std|��||_||_|t|j�f|_dS)Nr�)	r3r�r�r�r�r��next�_timeout_counterr�)rr�r�r�rrr�__init__?s
�z_Timeout.__init__�othercCs|j|jkSr�r��rr�rrr�__lt__O�z_Timeout.__lt__cCs|j|jkSrr�r�rrr�__le__Rr�z_Timeout.__le__)r$r%r&r��	__slots__r�rr+r�r�r�r�rrrrr�9s�
��
�r�c	@s�eZdZdZ	ddegeefdeej	e
fde
ddfdd	�Zdd
d�Zddd
�Z
defdd�Zddd�Zddd�Zde
ddfdd�ZdS)�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.
    rr��
callback_time�jitterrNcCsR||_t|tj�r|tjdd�|_n|dkrtd��||_||_d|_d|_dS)Nr,)�millisecondsrz4Periodic callback must have a positive callback_timeF)	r�r3r�r�r��
ValueErrorr��_running�_timeout)rr�r�r�rrrr�|s
zPeriodicCallback.__init__cCs(t��|_d|_|j��|_|��dS)zStarts the timer.TN)r+r=r�r�r�
_next_timeout�_schedule_nextrrrrri�s
zPeriodicCallback.startcCs,d|_|jdur|j�|j�d|_dSdS)zStops the timer.FN)r�r�r�r�rrrrrj�s


�zPeriodicCallback.stopcCs|jS)zfReturns ``True`` if this `.PeriodicCallback` has been started.

        .. versionadded:: 4.1
        )r�rrrr�
is_running�szPeriodicCallback.is_runningc�s��|jsdSz4z|��}|durt|�r|IdHWnty,tjd|jdd�YnwW|��dSW|��dS|��w)Nr�Tr�)r�r�rrqrr�r�)r�valrrr�_run�s�
����zPeriodicCallback._runcCs2|jr|�|j���|j�|j|j�|_dSdSr)r��_update_nextr�rr~r�r�r�rrrrr��s�zPeriodicCallback._schedule_next�current_timecCsp|jd}|jr|d|jt��d9}|j|kr/|jt�||j|�d|7_dS|j|7_dS)Ng@�@r,g�?)r�r��randomr��math�floor)rr��callback_time_secrrrr��s

�zPeriodicCallback._update_next)rr#)r$r%r&r�rrrrr�r�r�r�rirjr�r�r�r�r�rrrrr�Vs$)����
�




r�)1r�rF�concurrent.futuresr�r�r�r�r�rrrr�r�rP�inspectr�tornado.concurrentrrrrr�tornado.logr�tornado.utilr	r
rr�rr
rrrrrr�
TYPE_CHECKINGrrr�typing_extensionsrr�rr(r)r+r�r�rrrr�<module>sB
(v