σ
ΠH/\c           @` 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   e   d <d e f d     YZ d e f d     YZ d   Z e   d d l m Z e e   d  d S(   s    
Low-level waiting primitives.

i    (   t   absolute_import(   t   division(   t   print_functionN(   t   get_hub_noargs(   t   ConcurrentObjectUseErrort   Waitert   greenlett
   getcurrentc           C` s   d  S(   N(   t   None(    (    (    s-   lib/python2.7/site-packages/gevent/_waiter.pyt   <lambda>   s    t   greenlet_initc           B` s   e  Z d  Z d d d d g Z d d  Z d   Z d   Z d   Z d	   Z	 e
 d
    Z d   Z d   Z d   Z d   Z d   Z RS(   sΌ  
    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`.
    t   hubR   t   valuet
   _exceptionc         C` s=   | d  k r t   n | |  _ d  |  _ d  |  _ t |  _ d  S(   N(   R   t   get_hubR   R   R   t   _NONER   (   t   selfR   (    (    s-   lib/python2.7/site-packages/gevent/_waiter.pyt   __init__F   s    		c         C` s   d  |  _ d  |  _ t |  _ d  S(   N(   R   R   R   R   R   (   R   (    (    s-   lib/python2.7/site-packages/gevent/_waiter.pyt   clearL   s    		c         C` sx   |  j  t k r) d t |   j |  j f S|  j  d  k rX d t |   j |  j |  j f Sd t |   j |  j |  j f S(   Ns   <%s greenlet=%s>s   <%s greenlet=%s value=%r>s   <%s greenlet=%s exc_info=%r>(   R   R   t   typet   __name__R   R   R   t   exc_info(   R   (    (    s-   lib/python2.7/site-packages/gevent/_waiter.pyt   __str__Q   s
     c         C` s   |  j  t k	 S(   s;   Return true if and only if it holds a value or an exception(   R   R   (   R   (    (    s-   lib/python2.7/site-packages/gevent/_waiter.pyt   readyX   s    c         C` s   |  j  d k S(   s8   Return true if and only if it is ready and holds a valueN(   R   R   (   R   (    (    s-   lib/python2.7/site-packages/gevent/_waiter.pyt
   successful\   s    c         C` s   |  j  t k	 r |  j  Sd S(   sa   Holds the exception info passed to :meth:`throw` if :meth:`throw` was called. Otherwise ``None``.N(   R   R   (   R   (    (    s-   lib/python2.7/site-packages/gevent/_waiter.pyR   `   s    c         C` s   |  j  } | d k r* | |  _ d |  _ n[ t   |  j k	 rK t d   n  | j } y | |  Wn  |  j j | t	 j
    n Xd S(   s²   
        Switch to the greenlet if one's available. Otherwise store the
        *value*.

        .. versionchanged:: 1.3b1
           The *value* is no longer optional.
        s7   Can only use Waiter.switch method from the Hub greenletN(   R   R   R   R   R   R   t   AssertionErrort   switcht   handle_errort   sysR   (   R   R   R   R   (    (    s-   lib/python2.7/site-packages/gevent/_waiter.pyR   f   s    			c         G` s   |  j  |  S(   N(   R   (   R   t   args(    (    s-   lib/python2.7/site-packages/gevent/_waiter.pyt   switch_args{   s    c         G` s   |  j  } | d k r! | |  _ n[ t   |  j k	 rB t d   n  | j } y | |   Wn  |  j j | t j	    n Xd S(   sW   Switch to the greenlet with the exception. If there's no greenlet, store the exception.s7   Can only use Waiter.switch method from the Hub greenletN(
   R   R   R   R   R   R   t   throwR   R   R   (   R   t
   throw_argsR   R   (    (    s-   lib/python2.7/site-packages/gevent/_waiter.pyR   ~   s    		c         C` s   |  j  t k	 r; |  j  d k r% |  j St   j |  j    nR |  j d k	 rc t d |  j f   n  t   |  _ z |  j j	   SWd d |  _ Xd S(   sb   If a value/an exception is stored, return/raise it. Otherwise until switch() or throw() is called.s!   This Waiter is already used by %rN(
   R   R   R   R   R   R   R   R   R   R   (   R   (    (    s-   lib/python2.7/site-packages/gevent/_waiter.pyt   get   s    c         C` s6   | j  d  k r" |  j | j  n |  j | j   d  S(   N(   t	   exceptionR   R   R   R   (   R   t   source(    (    s-   lib/python2.7/site-packages/gevent/_waiter.pyt   __call__   s    N(   R   t
   __module__t   __doc__t	   __slots__R   R   R   R   R   R   t   propertyR   R   R   R   R!   R$   (    (    (    s-   lib/python2.7/site-packages/gevent/_waiter.pyR      s   '								t   MultipleWaiterc           B` s5   e  Z d  Z d g Z d d  Z d   Z d   Z RS(   s:  
    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.
    t   _valuesc         C` s    t  j |  |  t   |  _ d  S(   N(   R   R   t   listR*   (   R   R   (    (    s-   lib/python2.7/site-packages/gevent/_waiter.pyR   ±   s    c         C` s$   |  j  j |  t j |  t  d  S(   N(   R*   t   appendR   R   t   True(   R   R   (    (    s-   lib/python2.7/site-packages/gevent/_waiter.pyR   Ί   s    c         C` s6   |  j  s& t j |   t j |   n  |  j  j d  S(   Ni    (   R*   R   R!   R   t   pop(   R   (    (    s-   lib/python2.7/site-packages/gevent/_waiter.pyR!   Ύ   s    	N(   R   R%   R&   R'   R   R   R   R!   (    (    (    s-   lib/python2.7/site-packages/gevent/_waiter.pyR)   ¦   s
   			c           C` s   t    d  S(   N(   R
   (    (    (    s-   lib/python2.7/site-packages/gevent/_waiter.pyt   _initΕ   s    (   t   import_c_accels   gevent.__waiter(   R&   t
   __future__R    R   R   R   t   gevent._hub_localR   R   t   gevent.exceptionsR   t   __all__t   objectR   t
   __import__R   t   localsR   R)   R/   t   gevent._utilR0   t   globals(    (    (    s-   lib/python2.7/site-packages/gevent/_waiter.pyt   <module>   s    			