B
    he                 @   sH  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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 for historical reasons.
Applications can use either the `.IOLoop` interface or the underlying
`asyncio` event loop directly (unless compatibility with older
versions of Tornado is desired, in which case `.IOLoop` must be used).

Typical applications will use a single `IOLoop` object, accessed via
`IOLoop.current` class method. The `IOLoop.start` method (or
equivalently, `asyncio.AbstractEventLoop.run_forever`) should usually
be called at the end of the ``main()`` function. Atypical applications
may use more than one `IOLoop`, such as one `IOLoop` per thread, or
per `unittest` case.

    N)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   KC:\Users\sanjo\AppData\Local\Qlobot\Launcher\ext_packages\tornado\ioloop.pyfilenoC   s    z_Selectable.filenoNc             C   s   d S )Nr   )r   r   r   r   closeF   s    z_Selectable.close)__name__
__module____qualname__intr   r   r   r   r   r   r   B   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ddddZe
ee dddZe
ee dd d!Zdke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)d.d+Z!e#ee$f edd/d0d1Z%e#ee$f dd2d3d4Z&ddd5d6Z'ddd7d8Z(ddd9d:Z)dme e*ed;d<d=Z+e*dd>d?Z,e#e*e-j.f e d- eee/d@dAdBZ0e*e d- eee/dCdDdEZ1e*e d- 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 d2dedfZCe#ee$f dd2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 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 socket.error as e:
                    if e.args[0] not in (errno.EWOULDBLOCK, errno.EAGAIN):
                        raise
                    return
                connection.setblocking(0)
                io_loop = tornado.ioloop.IOLoop.current()
                io_loop.spawn_callback(handle_connection, connection, address)

        if __name__ == '__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)
            io_loop.start()

    .. testoutput::
       :hide:

    By default, a newly-constructed `IOLoop` becomes the thread's current
    `IOLoop`, unless there already is a current `IOLoop`. This behavior
    can be controlled with the ``make_current`` argument to the `IOLoop`
    constructor: if ``make_current=True``, the new `IOLoop` will always
    try to become current and it raises an error if there is already a
    current instance. If ``make_current=False``, the new `IOLoop` will
    not try to become current.

    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 in ``main()``.

    .. 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.

    r            z$Union[None, str, Type[Configurable]]N)implkwargsr   c                sZ   t d k	rBddlm} t|tr&t|}t|trBt||sBtdt	t
| j|f| d S )Nr   )BaseAsyncIOLoopz5only AsyncIOLoop is allowed when asyncio is available)asynciotornado.platform.asyncior*   
isinstancestrr
   type
issubclassRuntimeErrorsuperr$   	configure)clsr(   r)   r*   )	__class__r   r   r3      s    
zIOLoop.configure)r   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_current)r   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 )Nr   r   r   r   r   r6      s    zIOLoop.currentT)r7   r   c             C   s   d S )Nr   )r7   r   r   r   r6      s    c          	   C   st   yt  }W n" ttfk
r.   | s(dS  Y nX y
tj| S  tk
rn   | rfddlm} |dd}nd}Y nX |S )a  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.
        Nr   )AsyncIOMainLoopT)r8   )	r+   get_event_loopr1   AssertionErrorr$   _ioloop_for_asyncioKeyErrorr,   r<   )r7   loopr<   r6   r   r   r   r6      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.
        N)NotImplementedError)r   r   r   r   r8     s    zIOLoop.make_currentc              C   s0   t jdd} | dk	r|   tdkr,dt j_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.
        F)r7   N)r$   r6   _clear_current_hookr+   _currentr7   )oldr   r   r   r:   ,  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   rC   ;  s    zIOLoop._clear_current_hookc             C   s   t S )N)r$   )r4   r   r   r   configurable_baseB  s    zIOLoop.configurable_basec             C   s   ddl m} |S )Nr   )AsyncIOLoop)r,   rG   )r4   rG   r   r   r   configurable_defaultF  s    zIOLoop.configurable_default)r8   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 )NF)r7   zcurrent IOLoop already exists)r$   r6   r8   r1   )r   r8   r6   r   r   r   
initializeL  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.
        N)rB   )r   rJ   r   r   r   r   W  s    zIOLoop.close)fdhandlereventsr   c             C   s   d S )Nr   )r   rK   rL   rM   r   r   r   add_handlerr  s    zIOLoop.add_handlerc             C   s   d S )Nr   )r   rK   rL   rM   r   r   r   rN   x  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.
        N)rB   )r   rK   rL   rM   r   r   r   rN   ~  s    )rK   rM   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.
        N)rB   )r   rK   rM   r   r   r   update_handler  s    zIOLoop.update_handler)rK   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.
        N)rB   )r   rK   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.
        N)rB   )r   r   r   r   start  s    zIOLoop.startc             C   s0   t t jtdjtdjgs,t  dS )a  The IOLoop catches and logs exceptions, so it's
        important that log output be visible.  However, python's
        default behavior for non-root loggers (prior to python
        3.2) is to print an unhelpful "no handlers could be
        found" message rather than the actual log entry, so we
        must explicitly configure logging if we've made it this
        far without anything.

        This method should be called from start() in subclasses.
        tornadoztornado.applicationN)anylogging	getLoggerhandlersbasicConfig)r   r   r   r   _setup_logging  s
    
zIOLoop._setup_loggingc             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.
        N)rB   )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 `tornado.util.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.

        N)r   c                 s   y&  } | 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 )N)rY   )future)r   r   r   <lambda>      z.IOLoop.run_sync.<locals>.run.<locals>.<lambda>)Ztornado.genr\   	Exceptionr   r   sysexc_infor   
set_resultr>   
add_future)resultr\   fut)rZ   future_cellr   r   r   run  s     

zIOLoop.run_sync.<locals>.runc                  s(    d d k	st  d  s$  d S )Nr   )r>   cancelrY   r   )rg   r   r   r   timeout_callback  s    z)IOLoop.run_sync.<locals>.timeout_callbackr   z$Operation timed out after %s seconds)
add_callbackadd_timeouttimerQ   remove_timeoutr>   	cancelleddoner	   re   )r   rZ   r[   rh   rj   timeout_handler   )rZ   rg   r   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`.

        )rm   )r   r   r   r   rm     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.
        zUnsupported deadline %rN)	r-   numbersRealcall_atdatetime	timedeltarm   total_seconds	TypeError)r   rs   rt   ru   r)   r   r   r   rl   $  s     zIOLoop.add_timeout)delayrt   ru   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
        )rx   rm   )r   r}   rt   ru   r)   r   r   r   
call_laterM  s    zIOLoop.call_later)whenrt   ru   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
        )rl   )r   r   rt   ru   r)   r   r   r   rx   \  s    zIOLoop.call_at)r[   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.
        N)rB   )r   r[   r   r   r   rn   n  s    zIOLoop.remove_timeout)rt   ru   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`.
        N)rB   )r   rt   ru   r)   r   r   r   rk   w  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.
        N)rB   )r   rt   ru   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)rk   )r   rt   ru   r)   r   r   r   spawn_callback  s    zIOLoop.spawn_callbackz0Union[Future[_T], concurrent.futures.Future[_T]]z
Future[_T])r]   rt   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 )N)_run_callback	functoolspartial)f)rt   r]   r   r   r   r^     r_   z#IOLoop.add_future.<locals>.<lambda>c                s     S )N)rk   )r   )rt   r]   r   r   r   r^     r_   N)r-   r   add_done_callbackr   r>   r   )r   r]   rt   r   )rt   r]   r   r   rd     s    
	zIOLoop.add_future.)executorrZ   ru   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   )Zmax_workersc                s
   t |  S )N)r   )r   )t_futurer   r   r^     r_   z(IOLoop.run_in_executor.<locals>.<lambda>)
hasattrZtornado.processr   
concurrentfuturesThreadPoolExecutorr   submitr   rd   )r   r   rZ   ru   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)rt   r   c             C   s   yR| }|dk	rPddl m} y||}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   )genzException in callback %rT)rb   )rR   r   r\   BadYieldErrorrd   _discard_future_resultr+   CancelledErrorr`   r   error)r   rt   retr   r   r   r   r     s    zIOLoop._run_callback)r]   r   c             C   s   |   dS )z;Avoid unhandled-exception warnings from spawned coroutines.N)re   )r   r]   r   r   r   r     s    zIOLoop._discard_future_resultc             C   s   t |tr||fS | |fS )N)r-   r    r   )r   rK   r   r   r   split_fd  s    
zIOLoop.split_fdc             C   s<   y"t |trt| n|  W n tk
r6   Y nX d S )N)r-   r    osr   OSError)r   rK   r   r   r   close_fd  s    
zIOLoop.close_fd)T)T)N)F)N)Fr   r   r   __doc__NONEZREADZWRITEERRORdictr?   classmethodr   r3   staticmethodr7   r9   r;   typingoverloadr6   boolr   r8   r:   rC   r   r   rF   rH   rI   r   r    r   rN   r"   r   r   rO   rP   rQ   rX   rY   floatrr   rm   ry   rz   objectrl   r~   rx   rn   rk   r   r   rd   r   r   Executorr!   r   r   r   r   r   r   r   r   r   __classcell__r   r   )r5   r   r$   N   s   M%		J$	!


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 callbackrs   rt   	tdeadlineN)rs   rt   io_loopr   c             C   s8   t |tjstd| || _|| _|t|jf| _d S )NzUnsupported deadline %r)	r-   rv   rw   r|   rs   rt   nextZ_timeout_counterr   )r   rs   rt   r   r   r   r   __init__2  s    z_Timeout.__init__)otherr   c             C   s   | j |j k S )N)r   )r   r   r   r   r   __lt__B  s    z_Timeout.__lt__c             C   s   | j |j kS )N)r   )r   r   r   r   r   __le__E  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 df e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.
    Note that the timeout is given in milliseconds, while most other
    time-related functions in Tornado use seconds.

    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.
    r   N)rt   callback_timejitterr   c             C   s2   || _ |dkrtd|| _|| _d| _d | _d S )Nr   z4Periodic callback must have a positive callback_timeF)rt   
ValueErrorr   r   _running_timeout)r   rt   r   r   r   r   r   r   d  s    zPeriodicCallback.__init__)r   c             C   s(   t  | _d| _| j | _|   dS )zStarts the timer.TN)r$   r6   r   r   rm   _next_timeout_schedule_next)r   r   r   r   rQ   o  s    
zPeriodicCallback.startc             C   s(   d| _ | jdk	r$| j| j d| _dS )zStops the timer.FN)r   r   r   rn   )r   r   r   r   rY   y  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             C   sN   | j s
d S z4y|  S  tk
r:   tjd| jdd Y nX W d |   X d S )NzException in callback %rT)rb   )r   rt   r`   r   r   r   )r   r   r   r   _run  s    zPeriodicCallback._runc             C   s.   | j r*| | j  | j| j| j| _d S )N)r   _update_nextr   rm   rl   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   rQ   rY   r   r   r   r   r   r   r   r   r   r   I  s   	

r   ).r   r+   concurrent.futuresr   ry   r   rT   rv   r   ra   rm   r   r   tornado.concurrentr   r   r   r   r   tornado.logr   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>   (     c