3
Z_ð]^  ã               @   sR   d dl mZ d dlmZ d dlmZ dgZG dd„ dƒZeƒ ZG dd„ de	ƒZ
dS )	é    )Úprint_function)Úhubs)Ú	greenletsÚEventc               @   s   e Zd Zdd„ ZdS )ÚNOT_USEDc             C   s   dS )Nr   © )Úselfr   r   ú2/tmp/pip-build-yz_zf6az/eventlet/eventlet/event.pyÚ__repr__
   s    zNOT_USED.__repr__N)Ú__name__Ú
__module__Ú__qualname__r
   r   r   r   r	   r   	   s   r   c               @   sŠ   e Zd ZdZdZdZdd„ Zdd„ Zdd„ Zd	d
„ Z	dd„ Z
dd„ Zddd„Zddd„Zddd„Zd dd„Zd!dd„Zdd„ Zdd„ ZdS )"r   aè  An abstraction where an arbitrary number of coroutines
    can wait for one event from another.

    Events are similar to a Queue that can only hold one item, but differ
    in two important ways:

    1. calling :meth:`send` never unschedules the current greenthread
    2. :meth:`send` can only be called once; create a new event to send again.

    They are good for communicating results between coroutines, and
    are the basis for how
    :meth:`GreenThread.wait() <eventlet.greenthread.GreenThread.wait>`
    is implemented.

    >>> from eventlet import event
    >>> import eventlet
    >>> evt = event.Event()
    >>> def baz(b):
    ...     evt.send(b + 1)
    ...
    >>> _ = eventlet.spawn_n(baz, 3)
    >>> evt.wait()
    4
    Nc             C   s   t ƒ | _| jƒ  d S )N)ÚsetÚ_waitersÚreset)r   r   r   r	   Ú__init__,   s    zEvent.__init__c             C   s,   | j jtt| ƒƒ| j| jt| jƒf}d| S )Nz)<%s at %s result=%r _exc=%r _waiters[%d]>)Ú	__class__r   ÚhexÚidÚ_resultÚ_excÚlenr   )r   Úparamsr   r   r	   Ú__str__0   s    zEvent.__str__c             C   s"   | j tk	stdƒ‚t| _ d | _d S )Nz#Trying to re-reset() a fresh event.)r   r   ÚAssertionErrorr   )r   r   r   r	   r   5   s    zEvent.resetc             C   s
   | j tk	S )a]   Return true if the :meth:`wait` call will return immediately.
        Used to avoid waiting for things that might take a while to time out.
        For example, you can put a bunch of events into a list, and then visit
        them all repeatedly, calling :meth:`ready` until one returns ``True``,
        and then you can :meth:`wait` on that one.)r   r   )r   r   r   r	   Úready=   s    zEvent.readyc             C   s
   | j d k	S )N)r   )r   r   r   r	   Úhas_exceptionE   s    zEvent.has_exceptionc             C   s   | j tk	o| jd kS )N)r   r   r   )r   r   r   r	   Ú
has_resultH   s    zEvent.has_resultc             C   s   | j ƒ r| jƒ S |S )N)r   Úwait)r   Únotreadyr   r   r	   ÚpollK   s    z
Event.pollc             C   s   | j ƒ r| jƒ S |S )N)r   r   )r   r   r   r   r	   Úpoll_exceptionU   s    zEvent.poll_exceptionc             C   s   | j ƒ r| jƒ S |S )N)r   r   )r   r   r   r   r	   Úpoll_resultZ   s    zEvent.poll_resultc             C   sŽ   t jƒ }| jtkrrtjƒ }| jj|ƒ d}|dk	rF|j|| j	dd|ƒ}z|j
ƒ }|dk	r`|jƒ  |S | jj|ƒ X | jdk	rˆ|j| jŽ  | jS )aÎ  Wait until another coroutine calls :meth:`send`.
        Returns the value the other coroutine passed to :meth:`send`.

        >>> import eventlet
        >>> evt = eventlet.Event()
        >>> def wait_on():
        ...    retval = evt.wait()
        ...    print("waited for {0}".format(retval))
        >>> _ = eventlet.spawn(wait_on)
        >>> evt.send('result')
        >>> eventlet.sleep(0)
        waited for result

        Returns immediately if the event has already occurred.

        >>> evt.wait()
        'result'

        When the timeout argument is present and not None, it should be a floating point number
        specifying a timeout for the operation in seconds (or fractions thereof).
        N)ÚgreenletZ
getcurrentr   r   r   Úget_hubr   ÚaddZschedule_call_localÚ_do_sendÚswitchÚcancelÚdiscardr   Úthrow)r   ÚtimeoutÚcurrentÚhubZtimerÚresultr   r   r	   r   _   s     

z
Event.waitc             C   sl   | j tkstdƒ‚|| _ |dk	r2t|tƒ r2|f}|| _tjƒ }x&| jD ]}|j	d| j
| j | j|ƒ qHW dS )a]  Makes arrangements for the waiters to be woken with the
        result and then returns immediately to the parent.

        >>> from eventlet import event
        >>> import eventlet
        >>> evt = event.Event()
        >>> def waiter():
        ...     print('about to wait')
        ...     result = evt.wait()
        ...     print('waited for {0}'.format(result))
        >>> _ = eventlet.spawn(waiter)
        >>> eventlet.sleep(0)
        about to wait
        >>> evt.send('a')
        >>> eventlet.sleep(0)
        waited for a

        It is an error to call :meth:`send` multiple times on the same event.

        >>> evt.send('whoops')
        Traceback (most recent call last):
        ...
        AssertionError: Trying to re-send() an already-triggered event.

        Use :meth:`reset` between :meth:`send` s to reuse an event object.
        z/Trying to re-send() an already-triggered event.Nr   )r   r   r   Ú
isinstanceÚtupler   r   r$   r   Zschedule_call_globalr&   )r   r.   Úexcr-   Úwaiterr   r   r	   Úsend‡   s    z
Event.sendc             C   s,   || j kr(|d kr|j|ƒ n
|j|Ž  d S )N)r   r'   r*   )r   r.   r1   r2   r   r   r	   r&   ¬   s    
zEvent._do_sendc             G   s   | j d|ƒS )aÞ  Same as :meth:`send`, but sends an exception to waiters.

        The arguments to send_exception are the same as the arguments
        to ``raise``.  If a single exception object is passed in, it
        will be re-raised when :meth:`wait` is called, generating a
        new stacktrace.

           >>> from eventlet import event
           >>> evt = event.Event()
           >>> evt.send_exception(RuntimeError())
           >>> evt.wait()
           Traceback (most recent call last):
             File "<stdin>", line 1, in <module>
             File "eventlet/event.py", line 120, in wait
               current.throw(*self._exc)
           RuntimeError

        If it's important to preserve the entire original stack trace,
        you must pass in the entire :func:`sys.exc_info` tuple.

           >>> import sys
           >>> evt = event.Event()
           >>> try:
           ...     raise RuntimeError()
           ... except RuntimeError:
           ...     evt.send_exception(*sys.exc_info())
           ...
           >>> evt.wait()
           Traceback (most recent call last):
             File "<stdin>", line 1, in <module>
             File "eventlet/event.py", line 120, in wait
               current.throw(*self._exc)
             File "<stdin>", line 2, in <module>
           RuntimeError

        Note that doing so stores a traceback object directly on the
        Event object, which may cause reference cycles. See the
        :func:`sys.exc_info` documentation.
        N)r3   )r   Úargsr   r   r	   Úsend_exception³   s    )zEvent.send_exception)N)N)N)N)NN)r   r   r   Ú__doc__r   r   r   r   r   r   r   r   r    r!   r"   r   r3   r&   r5   r   r   r   r	   r      s    




(
%N)Ú
__future__r   Zeventletr   Zeventlet.supportr   r#   Ú__all__r   Úobjectr   r   r   r   r	   Ú<module>   s   