U
    d                     @   sT  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$rddl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)Z/d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)Protocolc                   @   s(   e Zd ZedddZddddZdS )_Selectablereturnc                 C   s   d S N selfr   r   2/tmp/pip-unpacked-wheel-fekwu36z/tornado/ioloop.pyfileno=   s    z_Selectable.filenoNc                 C   s   d S r   r   r   r   r   r   close@   s    z_Selectable.close)__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
dedd fd	d
Zed dddZddddZeddddZejed dddZejedieed  dddZedjeed  dddZddddZeddddZeddddZddddZe
ee dd d!Ze
ee dd"d#Zdkee dd$d%d&Zdledd(d)d*Zeje e!e e gdf e dd+d,d-Z"eje#e!e#e gdf e dd+d.d-Z"e$e e%f e!d/ e dd+d0d-Z"e$e e%f e dd1d2d3Z&e$e e%f dd4d5d6Z'ddd7d8Z(ddd9d:Z)dme!ee* ed;d<d=Z+e*dd>d?Z,e$e*e-j.f e!eee/d@dAdBZ0e*e!eee/dCdDdEZ1e*e!eee/dFdGdHZ2e/ddIdJdKZ3e!eeddLdMdNZ4e!eeddLdOdPZ5e!eeddLdQdRZ6dSe!dTgdf ddUdVdWZ7ee8j9j: e!dXe;f ee<e; dYdZd[Z=e8j9j:dd\d]d^Z>e!g ef dd_d`daZ?e@ddbdcddZAe$e e%f eBe e$e e%f f d4dedfZCe$e e%f dd4dgdhZD  ZES )n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.ioloop
        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)``. Constructing an `IOLoop`
    without the ``make_current=False`` argument is deprecated since Tornado 6.2.

    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.

    .. deprecated:: 6.2
       It is deprecated to create an event loop that is "current" but not
       running. This means it is deprecated to pass
       ``make_current=True`` to the ``IOLoop`` constructor, or to create
       an ``IOLoop`` while no asyncio event loop is running unless
       ``make_current=False`` is used.
    r            z$Union[None, str, Type[Configurable]]N)implkwargsr   c                    sR   ddl m} t|trt|}t|tr:t||s:tdtt	| j
|f| d S )Nr   )BaseAsyncIOLoopz5only AsyncIOLoop is allowed when asyncio is available)tornado.platform.asyncior.   
isinstancestrr   type
issubclassRuntimeErrorsuperr(   	configure)clsr,   r-   r.   	__class__r   r   r6      s    
zIOLoop.configurer   c                   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   s   d S r   r   r   r   r   r   r:      s    zIOLoop.currentT)r;   r   c                 C   s   d S r   r   r;   r   r   r   r:      s    c              	   C   sx   zt  }W n$ ttfk
r0   | s*Y dS  Y nX ztj| W S  tk
rr   | rjddlm} |dd}nd}Y nX |S )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   )AsyncIOMainLoopTr<   )	asyncioZget_event_loopr4   AssertionErrorr(   _ioloop_for_asyncioKeyErrorr/   rB   )r;   ZlooprB   r:   r   r   r   r:      s    
c                 C   s
   t  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
           The concept of an event loop that is "current" without
           currently running is deprecated in asyncio since Python
           3.10. All related functionality in Tornado is also
           deprecated. Instead, start the event loop with `asyncio.run`
           before interacting with it.
        NNotImplementedErrorr   r   r   r   r=     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 deprecated   )
stacklevelN)warningswarnDeprecationWarningr(   _clear_currentr   r   r   r   r?   3  s    
zIOLoop.clear_currentc                  C   s    t jdd} | d k	r|   d S )NFrA   )r(   r:   _clear_current_hook)oldr   r   r   rN   D  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   rO   J  s    zIOLoop._clear_current_hookc                 C   s   t S r   )r(   )r7   r   r   r   configurable_baseQ  s    zIOLoop.configurable_basec                 C   s   ddl m} |S )Nr   )AsyncIOLoop)r/   rR   )r7   rR   r   r   r   configurable_defaultU  s    zIOLoop.configurable_default)r=   r   c                 C   sV   |d kr"t jddd krR|   n0|rRt jdd}|d k	rJ|| k	rJtd|   d S )NFrA   zcurrent IOLoop already exists)r(   r:   r=   r4   )r   r=   r:   r   r   r   
initialize[  s    
zIOLoop.initializeF)all_fdsr   c                 C   s
   t  dS )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.
        NrG   )r   rU   r   r   r   r    f  s    zIOLoop.close)fdhandlereventsr   c                 C   s   d S r   r   r   rV   rW   rX   r   r   r   add_handler  s    zIOLoop.add_handlerc                 C   s   d S r   r   rY   r   r   r   rZ     s    ).Nc                 C   s
   t  dS )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.
        NrG   rY   r   r   r   rZ     s    )rV   rX   r   c                 C   s
   t  dS )zChanges the events we listen for ``fd``.

        .. versionchanged:: 4.0
           Added the ability to pass file-like objects in addition to
           raw file descriptors.
        NrG   )r   rV   rX   r   r   r   update_handler  s    zIOLoop.update_handler)rV   r   c                 C   s
   t  dS )zStop listening for events on ``fd``.

        .. versionchanged:: 4.0
           Added the ability to pass file-like objects in addition to
           raw file descriptors.
        NrG   r   rV   r   r   r   remove_handler  s    zIOLoop.remove_handlerc                 C   s
   t  dS )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.
        NrG   r   r   r   r   start  s    zIOLoop.startc                 C   s
   t  dS )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.
        NrG   r   r   r   r   stop  s    zIOLoop.stop)functimeoutr   c                    s   dgdd fdd} | |dk	rVddfdd} | |}  |dk	rp| d dk	std  sd  st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 k	r$ddl m} || } W n0 tk
rV   t }|d< t|t  Y n,X t| rj| d< nt }|d< ||  d d k	st	
d fdd d S )Nr   )convert_yieldedc                    s      S r   )r_   )futurer   r   r   <lambda>      z.IOLoop.run_sync.<locals>.run.<locals>.<lambda>)Ztornado.genrb   	Exceptionr   r   sysexc_infor   Z
set_resultrD   
add_future)resultrb   Zfutr`   future_cellr   r   r   run  s     

zIOLoop.run_sync.<locals>.runc                      s(    d d k	st  d  s$  d S )Nr   )rD   cancelr_   r   )rl   r   r   r   timeout_callback  s    z)IOLoop.run_sync.<locals>.timeout_callbackr   z$Operation timed out after %s seconds)
add_callbackadd_timeouttimer^   remove_timeoutrD   Z	cancelleddoner
   rj   )r   r`   ra   rm   ro   Ztimeout_handler   rk   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`.

        )rr   r   r   r   r   rr     s    zIOLoop.time)deadlinecallbackargsr-   r   c                 O   s\   t |tjr | j||f||S t |tjrL| j|  |  |f||S td| dS )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 %rN)	r0   numbersRealcall_atdatetime	timedeltarr   total_seconds	TypeError)r   rv   rw   rx   r-   r   r   r   rq   !  s      zIOLoop.add_timeout)delayrw   rx   r-   r   c                 O   s   | j |  | |f||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|   rr   )r   r   rw   rx   r-   r   r   r   
call_laterJ  s    zIOLoop.call_later)whenrw   rx   r-   r   c                 O   s   | j ||f||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
        )rq   )r   r   rw   rx   r-   r   r   r   r|   Y  s    zIOLoop.call_at)ra   r   c                 C   s
   t  dS )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.
        NrG   )r   ra   r   r   r   rs   k  s    zIOLoop.remove_timeout)rw   rx   r-   r   c                 O   s
   t  dS )a3  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.

        To add a callback from a signal handler, see
        `add_callback_from_signal`.
        NrG   r   rw   rx   r-   r   r   r   rp   t  s    zIOLoop.add_callbackc                 O   s
   t  dS )zCalls the given callback on the next I/O loop iteration.

        Safe for use from a Python signal handler; should not be used
        otherwise.
        NrG   r   r   r   r   add_callback_from_signal  s    zIOLoop.add_callback_from_signalc                 O   s   | j |f|| 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rp   r   r   r   r   spawn_callback  s    zIOLoop.spawn_callbackz0Union[Future[_T], concurrent.futures.Future[_T]]z
Future[_T])rc   rw   r   c                    sH   t tr" fdd n"ts.t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rw   rc   r   r   r   rd     re   z#IOLoop.add_future.<locals>.<lambda>c                    s     S r   r   r   r   r   r   rd     re   N)r0   r   Zadd_done_callbackr   rD   r   )r   rc   rw   r   r   r   ri     s    
	 zIOLoop.add_future.)executorr`   rx   r   c                    sh   |dkr:t | ds4ddlm} tjj| d d| _| j}|j|f| }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   rd     re   z(IOLoop.run_in_executor.<locals>.<lambda>)
hasattrZtornado.processr   
concurrentfuturesZThreadPoolExecutorr   Zsubmitr   ri   )r   r   r`   rx   r   Zc_futurer   r   r   run_in_executor  s    
zIOLoop.run_in_executor)r   r   c                 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_executor)rw   r   c                 C   s   zR| }|dk	rPddl m} z||}W n |jk
r@   Y nX | || j W n8 tjk
rh   Y n$ tk
r   t	j
d|dd Y nX dS )zRuns a callback with error handling.

        .. versionchanged:: 6.0

           CancelledErrors are no longer logged.
        Nr   )genException in callback %rTrh   )Ztornador   rb   ZBadYieldErrorri   _discard_future_resultrC   ZCancelledErrorrf   r   error)r   rw   retr   r   r   r   r     s    zIOLoop._run_callback)rc   r   c                 C   s   |   dS )z;Avoid unhandled-exception warnings from spawned coroutines.N)rj   )r   rc   r   r   r   r     s    zIOLoop._discard_future_resultc                 C   s   t |tr||fS | |fS r   )r0   r$   r   r\   r   r   r   split_fd  s    
zIOLoop.split_fdc                 C   s<   z"t |trt| n|  W n tk
r6   Y nX d S r   )r0   r$   osr    OSErrorr\   r   r   r   close_fd  s    
zIOLoop.close_fd)T)T)N)F)N)Fr!   r"   r#   __doc__NONEREADWRITEERRORdictrE   classmethodr   r6   staticmethodr;   r>   r@   typingoverloadr:   boolr   r=   r?   rN   rO   r   r	   rQ   rS   rT   r    r$   r   rZ   r&   r   r   r[   r]   r^   r_   floatru   rr   r}   r~   objectrq   r   r|   rs   rp   r   r   ri   r   r   ZExecutorr%   r   r   r   r   r   r   r   r   r   __classcell__r   r   r8   r   r(   H   s   T )    
  		L*      	  
%


r(   c                   @   sV   e Zd ZdZdddgZeeg df eddddZd e	d	d
dZ
d e	d	ddZdS )_Timeoutz2An IOLoop timeout, a UNIX timestamp and a callbackrv   rw   	tdeadlineN)rv   rw   io_loopr   c                 C   s8   t |tjstd| || _|| _|t|jf| _d S )Nry   )	r0   rz   r{   r   rv   rw   nextZ_timeout_counterr   )r   rv   rw   r   r   r   r   __init__/  s    z_Timeout.__init__)otherr   c                 C   s   | j |j k S r   r   r   r   r   r   r   __lt__?  s    z_Timeout.__lt__c                 C   s   | j |j kS r   r   r   r   r   r   __le__B  s    z_Timeout.__le__)r!   r"   r#   r   	__slots__r   r   r(   r   r   r   r   r   r   r   r   r   )  s   
 
 r   c                   @   s   e Zd ZdZdeg ee f eej	e
f e
ddddZdddd	Zddd
dZedddZddddZddddZe
dd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   N)rw   callback_timejitterr   c                 C   sR   || _ t|tjr&|tjdd | _n|dkr6td|| _|| _d| _d | _d S )Nr)   )Zmillisecondsr   z4Periodic callback must have a positive callback_timeF)	rw   r0   r}   r~   r   
ValueErrorr   _running_timeout)r   rw   r   r   r   r   r   r   l  s    zPeriodicCallback.__init__r   c                 C   s(   t  | _d| _| j | _|   dS )zStarts the timer.TN)r(   r:   r   r   rr   _next_timeout_schedule_nextr   r   r   r   r^   }  s    
zPeriodicCallback.startc                 C   s(   d| _ | jdk	r$| j| j d| _dS )zStops the timer.FN)r   r   r   rs   r   r   r   r   r_     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                    sl   | j s
d S zRz&|  }|d k	r0t|r0|I d H  W n& tk
rX   tjd| jdd Y nX W 5 |   X d S )Nr   Tr   )r   r   rw   r   rf   r   r   )r   valr   r   r   _run  s    zPeriodicCallback._runc                 C   s.   | j r*| | j  | j| j| j| _d S r   )r   _update_nextr   rr   rq   r   r   r   r   r   r   r   r     s    zPeriodicCallback._schedule_next)current_timer   c                 C   sn   | j d }| jr*|d| jt d   9 }| j|kr\|  jt|| j | d | 7  _n|  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^   r_   r   r   r   r   r   r   r   r   r   r   F  s   ) 
r   )0r   rC   concurrent.futuresr   r}   r   rz   r   rg   rr   r   r   rK   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   Ztyping_extensionsr   r   r   r%   r&   r(   r   r   r   r   r   r   <module>   s@   
(     f