B
    ÐH/\a  ã               @   s¼   d Z ddlmZ ddlmZ ddlmZ ddlZddlmZ ddl	m
Z
 dgZeƒ Zed	ƒjeƒ d
< dd„ eƒ d< G dd„ deƒZG dd„ deƒZdd„ Zeƒ  ddlmZ eeƒ dƒ dS )z 
Low-level waiting primitives.

é    )Úabsolute_import)Údivision)Úprint_functionN)Úget_hub_noargs)ÚConcurrentObjectUseErrorÚWaiterÚgreenletÚ
getcurrentc               C   s   d S )N© r
   r
   r
   ú-lib/python3.7/site-packages/gevent/_waiter.pyÚ<lambda>   s    r   Úgreenlet_initc               @   sz   e Zd ZdZddddgZddd„Zd	d
„ Zdd„ Zdd„ Zdd„ Z	e
dd„ ƒZdd„ Zdd„ Zdd„ Zdd„ Zdd„ ZdS )r   a¼  
    A low level communication utility for greenlets.

    Waiter is a wrapper around greenlet's ``switch()`` and ``throw()`` calls that makes them somewhat safer:

    * switching will occur only if the waiting greenlet is executing :meth:`get` method currently;
    * any error raised in the greenlet is handled inside :meth:`switch` and :meth:`throw`
    * if :meth:`switch`/:meth:`throw` is called before the receiver calls :meth:`get`, then :class:`Waiter`
      will store the value/exception. The following :meth:`get` will return the value/raise the exception.

    The :meth:`switch` and :meth:`throw` methods must only be called from the :class:`Hub` greenlet.
    The :meth:`get` method must be called from a greenlet other than :class:`Hub`.

        >>> result = Waiter()
        >>> timer = get_hub().loop.timer(0.1)
        >>> timer.start(result.switch, 'hello from Waiter')
        >>> result.get() # blocks for 0.1 seconds
        'hello from Waiter'
        >>> timer.close()

    If switch is called before the greenlet gets a chance to call :meth:`get` then
    :class:`Waiter` stores the value.

        >>> result = Waiter()
        >>> timer = get_hub().loop.timer(0.1)
        >>> timer.start(result.switch, 'hi from Waiter')
        >>> sleep(0.2)
        >>> result.get() # returns immediately without blocking
        'hi from Waiter'
        >>> timer.close()

    .. warning::

        This a limited and dangerous way to communicate between
        greenlets. It can easily leave a greenlet unscheduled forever
        if used incorrectly. Consider using safer classes such as
        :class:`gevent.event.Event`, :class:`gevent.event.AsyncResult`,
        or :class:`gevent.queue.Queue`.
    Úhubr   ÚvalueÚ
_exceptionNc             C   s*   |d krt ƒ n|| _d | _d | _t| _d S )N)Úget_hubr   r   r   Ú_NONEr   )Úselfr   r
   r
   r   Ú__init__F   s    zWaiter.__init__c             C   s   d | _ d | _t| _d S )N)r   r   r   r   )r   r
   r
   r   ÚclearL   s    zWaiter.clearc             C   sX   | j tkrdt| ƒj| jf S | j d kr@dt| ƒj| j| jf S dt| ƒj| j| jf S )Nz<%s greenlet=%s>z<%s greenlet=%s value=%r>z<%s greenlet=%s exc_info=%r>)r   r   ÚtypeÚ__name__r   r   Úexc_info)r   r
   r
   r   Ú__str__Q   s
    

zWaiter.__str__c             C   s
   | j tk	S )z;Return true if and only if it holds a value or an exception)r   r   )r   r
   r
   r   ÚreadyX   s    zWaiter.readyc             C   s
   | j dkS )z8Return true if and only if it is ready and holds a valueN)r   )r   r
   r
   r   Ú
successful\   s    zWaiter.successfulc             C   s   | j tk	r| j S dS )zaHolds the exception info passed to :meth:`throw` if :meth:`throw` was called. Otherwise ``None``.N)r   r   )r   r
   r
   r   r   `   s    
zWaiter.exc_infoc             C   sj   | j }|dkr|| _d| _nJtƒ | jk	r0tdƒ‚|j}y||ƒ W n"   | jj|ft 	¡ žŽ  Y nX dS )z²
        Switch to the greenlet if one's available. Otherwise store the
        *value*.

        .. versionchanged:: 1.3b1
           The *value* is no longer optional.
        Nz7Can only use Waiter.switch method from the Hub greenlet)
r   r   r   r	   r   ÚAssertionErrorÚswitchÚhandle_errorÚsysr   )r   r   r   r   r
   r
   r   r   f   s    zWaiter.switchc             G   s
   |   |¡S )N)r   )r   Úargsr
   r
   r   Úswitch_args{   s    zWaiter.switch_argsc             G   sd   | j }|dkr|| _nJtƒ | jk	r*tdƒ‚|j}y||Ž  W n"   | jj|ft ¡ žŽ  Y nX dS )zWSwitch to the greenlet with the exception. If there's no greenlet, store the exception.Nz7Can only use Waiter.switch method from the Hub greenlet)	r   r   r	   r   r   Úthrowr   r   r   )r   Z
throw_argsr   r"   r
   r
   r   r"   ~   s    zWaiter.throwc             C   sd   | j tk	r*| j dkr| jS tƒ j| j Ž  n6| jdk	rDtd| jf ƒ‚tƒ | _z
| j ¡ S d| _X dS )zbIf a value/an exception is stored, return/raise it. Otherwise until switch() or throw() is called.Nz!This Waiter is already used by %r)	r   r   r   r	   r"   r   r   r   r   )r   r
   r
   r   ÚgetŒ   s    



z
Waiter.getc             C   s(   |j d kr|  |j¡ n|  |j ¡ d S )N)Z	exceptionr   r   r"   )r   Úsourcer
   r
   r   Ú__call__›   s    
zWaiter.__call__)N)r   Ú
__module__Ú__qualname__Ú__doc__Ú	__slots__r   r   r   r   r   Úpropertyr   r   r!   r"   r#   r%   r
   r
   r
   r   r      s   '
c               @   s0   e Zd ZdZdgZd
dd„Zdd„ Zdd	„ ZdS )ÚMultipleWaitera:  
    An internal extension of Waiter that can be used if multiple objects
    must be waited on, and there is a chance that in between waits greenlets
    might be switched out. All greenlets that switch to this waiter
    will have their value returned.

    This does not handle exceptions or throw methods.
    Ú_valuesNc             C   s   t  | |¡ tƒ | _d S )N)r   r   Úlistr,   )r   r   r
   r
   r   r   ±   s    zMultipleWaiter.__init__c             C   s   | j  |¡ t | d¡ d S )NT)r,   Úappendr   r   )r   r   r
   r
   r   r   º   s    zMultipleWaiter.switchc             C   s&   | j st | ¡ t | ¡ | j  d¡S )Nr   )r,   r   r#   r   Úpop)r   r
   r
   r   r#   ¾   s    

zMultipleWaiter.get)N)r   r&   r'   r(   r)   r   r   r#   r
   r
   r
   r   r+   ¦   s
   
	r+   c               C   s
   t ƒ  d S )N)r   r
   r
   r
   r   Ú_initÅ   s    r0   )Úimport_c_accelzgevent.__waiter)r(   Z
__future__r   r   r   r   Zgevent._hub_localr   r   Zgevent.exceptionsr   Ú__all__Úobjectr   Ú
__import__r	   Úlocalsr   r+   r0   Zgevent._utilr1   Úglobalsr
   r
   r
   r   Ú<module>   s"    