
    iQ                     d   d dl mZmZmZ ddgZd dlmZ d dlm	Z	 d dl
mZ d dl
mZ d dlmZ d	 Z e             e            d
<   [d dlmZ d dlmZ d dlmZ  G d de          Z e            Z e            Z G d de          Z G d de          Zd dlmZ  e e            d           dS )    )print_functionabsolute_importdivision	SemaphoreBoundedSemaphore)sleep)	monotonic)InvalidThreadUseError)LoopExit)Timeoutc                  8    t          d          } | j        j        S )Nzgevent._abstract_linkable)
__import___abstract_linkableAbstractLinkable)xs    </usr/local/lib/python3.11/dist-packages/gevent/_semaphore.py_get_linkabler      s    .//A00    r   )get_hub_if_exists)get_hub)	spawn_rawc                       e Zd ZdZd Zd ZdS )_LockReleaseLinklockc                     || _         d S Nr   )selfr   s     r   __init__z_LockReleaseLink.__init__'   s    			r   c                 8    | j                                          d S r   )r   release)r   _s     r   __call__z_LockReleaseLink.__call__*   s    	r   N)__name__
__module____qualname__	__slots__r   r#    r   r   r   r   "   s9        I      r   r   c                        e Zd ZdZdZd fd	Zd Zd Zd Zd	 Z	d
 Z
d ZddZddZeZd Zd Zd Zd Zd Zd Zd Zd Zd Zd Z xZS )r   ap  
    Semaphore(value=1) -> Semaphore

    .. seealso:: :class:`BoundedSemaphore` for a safer version that prevents
       some classes of bugs. If unsure, most users should opt for `BoundedSemaphore`.

    A semaphore manages a counter representing the number of `release`
    calls minus the number of `acquire` calls, plus an initial value.
    The `acquire` method blocks if necessary until it can return
    without making the counter negative. A semaphore does not track ownership
    by greenlets; any greenlet can call `release`, whether or not it has previously
    called `acquire`.

    If not given, ``value`` defaults to 1.

    The semaphore is a context manager and can be used in ``with`` statements.

    This Semaphore's ``__exit__`` method does not call the trace function
    on CPython, but does under PyPy.

    .. versionchanged:: 1.4.0
        Document that the order in which waiters are awakened is not specified. It was not
        specified previously, but due to CPython implementation quirks usually went in FIFO order.
    .. versionchanged:: 1.5a3
       Waiting greenlets are now awakened in the order in which they waited.
    .. versionchanged:: 1.5a3
       The low-level ``rawlink`` method (most users won't use this) now automatically
       unlinks waiters before calling them.
    .. versionchanged:: 20.12.0
       Improved support for multi-threaded usage. When multi-threaded usage is detected,
       instances will no longer create the thread's hub if it's not present.

    .. versionchanged:: 24.2.1
       Uses Python 3 native lock timeouts for cross-thread operations instead
       of spinning.
    )counter_multithreaded   Nc                     || _         | j         dk     rt          d          t          t          |                               |           d| _        t          | _        d S )Nr   z$semaphore initial value must be >= 0F)r*   
ValueErrorsuperr   r   _notify_all_UNSETr+   )r   valuehub	__class__s      r   r   zSemaphore.__init__`   sZ    <!CDDDi'',,, $r   c                 p    d| j         j        t          |           | j        |                                 fz  S )Nz"<%s at 0x%x counter=%s _links[%s]>)r4   r$   idr*   	linkcountr   s    r   __str__zSemaphore.__str__h   s7    3N#tHHLNN	7
 
 	
r   c                     | j         dk    S )z
        Return a boolean indicating whether the semaphore can be
        acquired (`False` if the semaphore *can* be acquired). Most
        useful with binary semaphores (those with an initial value of 1).

        :rtype: bool
        r   r*   r8   s    r   lockedzSemaphore.lockedp   s     |q  r   c                 X    | xj         dz  c_         |                                  | j         S )a  
        Release the semaphore, notifying any waiters if needed. There
        is no return value.

        .. note::

            This can be used to over-release the semaphore.
            (Release more times than it has been acquired or was initially
            created with.)

            This is usually a sign of a bug, but under some circumstances it can be
            used deliberately, for example, to model the arrival of additional
            resources.

        :rtype: None
        r,   )r*   _check_and_notifyr8   s    r   r!   zSemaphore.releasez   s.    " 	   |r   c                     | j         dk    S )z
        Return a boolean indicating whether the semaphore can be
        acquired (`True` if the semaphore can be acquired).

        :rtype: bool
        r   r;   r8   s    r   readyzSemaphore.ready   s     |ar   c                 .    |                                   d S r   )r>   r8   s    r   _start_notifyzSemaphore._start_notify   s         r   c                     |r|S dS NTr(   )r   waitedwait_successs      r   _wait_return_valuezSemaphore._wait_return_value   s     	  tr   c                 ^    | j         dk    r| j         S |                     |           | j         S )aD  
        Wait until it is possible to acquire this semaphore, or until the optional
        *timeout* elapses.

        .. note:: If this semaphore was initialized with a *value* of 0,
           this method will block forever if no timeout is given.

        :keyword float timeout: If given, specifies the maximum amount of seconds
           this method will block.
        :return: A number indicating how many times the semaphore can be acquired
            before blocking. *This could be 0,* if other waiters acquired
            the semaphore.
        :rtype: int
        r   )r*   _wait)r   timeouts     r   waitzSemaphore.wait   s3     <!<

7|r   Tc                    | j         t          u r|                                 | _         n)| j         |                                 k    rt          | _         d}	 |                     d           nE# t
          $ r8}|j        }d}| j        s|r|                     |||          cY d}~S Y d}~nd}~ww xY w| j        dk    r| xj        dz  c_        dS |sdS | j         t          ur| j	        t                      | _	        | j	        /|s-|                     dd|                                 df||          S 	 |                     |          }n# t          $ r}|j        }d}| j        rd}ndt          |          dk    r|d         j        r |                     | j	        t!                      |                                 df||          cY d}~S Y d}~nd}~ww xY w|s|J dS | j        dk    sJ | j        |||f            | xj        dz  c_        dS )	a"  
        acquire(blocking=True, timeout=None) -> bool

        Acquire the semaphore.

        .. note:: If this semaphore was initialized with a *value* of 0,
           this method will block forever (unless a timeout is given or blocking is
           set to false).

        :keyword bool blocking: If True (the default), this function will block
           until the semaphore is acquired.
        :keyword float timeout: If given, and *blocking* is true,
           specifies the maximum amount of seconds
           this method will block.
        :return: A `bool` indicating whether the semaphore was acquired.
           If ``blocking`` is True and ``timeout`` is None (the default), then
           (so long as this semaphore was initialized with a size greater than 0)
           this will always return True. If a timeout was given, and it expired before
           the semaphore was acquired, False will be returned. (Note that this can still
           raise a ``Timeout`` exception, if some other caller had already started a timer.)
        NFr   r,   TNoHubs   r   )r+   r1   _get_thread_ident_MULTI_capture_hubr
   argsr*   %_Semaphore__acquire_from_other_threadr3   r   _getcurrentrI   r   lenmain_hubr   )r   blockingrJ   invalid_thread_useesuccessexrR   s           r   acquirezSemaphore.acquire   s   0 &(("&"8"8":":D D$:$:$<$<<<"(D "		_e$$$$$ 	_ 	_ 	_ "#A< _H _778JHV]^^^^^^^^	_ <!LLALL4 	5f,,1AyyDH8$6 33tT--//:  	jj))GG 	 	 	7DB| 
 t99>>d1g&6>77X022D4D4D4F4F
S        		  	&&&5 |a$,'7!Lts=   A+ +
B-5(B(B-(B-0E 
GA1GGGc                 .    |                                   d S r   )r\   r8   s    r   	__enter__zSemaphore.__enter__      r   c                 .    |                                   d S r   )r!   )r   tvtbs       r   __exit__zSemaphore.__exit__  r_   r   c                 :    | j                             |           d S r   )_linksextend)r   
unswitcheds     r    _handle_unswitched_notificationsz*Semaphore._handle_unswitched_notifications   s     . 	:&&&&&r   c                     | j         s|                     |           d S | j         j        d                             |           d S )Nr   )	_notifierrawlinkrR   append)r   links     r   
__add_linkzSemaphore.__add_link9  sH    ~ 	0LLN"))$/////r   c                     |sJ |d         }|d         }|d         }|||                      |          S ||                     ||          S |                     |||          S )Nr   r,      ) _Semaphore__acquire_without_hubs#_Semaphore__acquire_using_other_hub"_Semaphore__acquire_using_two_hubs)r   ex_argsrW   rJ   
owning_hubhub_for_this_threadcurrent_greenlets          r   __acquire_from_other_threadz%Semaphore.__acquire_from_other_thread?  s     QZ
%aj"1:"5"=..w777& 11*gFFF ,,-@-=-46 6 	6r   c                    |j                                         }|j        }|                    |j        |            	 t          j        |          5 }	 	 | j        dk    rq| xj        dz  c_        | j        dk    sJ | f            	 d d d            |                     |           |	                                 |
                                 dS |                     |           |                     |           |                     d          }|rK|cd d d            |                     |           |	                                 |
                                 S 
# t
          $ rX}||ur Y d }~d d d            |                     |           |	                                 |
                                 dS d }~ww xY w# 1 swxY w Y   	 |                     |           |	                                 |
                                 d S # |                     |           |	                                 |
                                 w xY w)Nr,   r   TF)loopasync_send_ignoring_argstartswitchr   _start_new_or_dummyr*   _quiet_unlink_allstopclose_Semaphore__add_link_switch_to_hubr\   )	r   rw   rx   rJ   watchersendtimerresulttexs	            r   __acquire_using_two_hubsz"Semaphore.__acquire_using_two_hubsd  s    &*1133(&-t444	,W55 !!*<!++ LLA-LL#'<1#4#4#4tg#4#4#4#'! ! ! ! ! !4 ""4(((LLNNNMMOOOOO% --- ++,?@@@
 "&a! *#))! ! ! ! ! ! !4 ""4(((LLNNNMMOOOO1*"  ! ! !%'' 5551! ! ! ! ! !4 ""4(((LLNNNMMOOOOO!+! ! ! ! ! ! ! ! !4 ""4(((LLNNNMMOOOOO ""4(((LLNNNMMOOOOsl   H G2EH AEH E
G (F;-G1H ;G  GGH 
GH ?Ic                     	 |                      ||          }|                    |           |                                 n# |                                 w xY w|S r   )r\   rm   r!   )r   resultsrW   rJ   thread_lockr   s         r   __acquire_from_other_thread_cbz(Semaphore.__acquire_from_other_thread_cb  s^    	"\\(G44FNN6"""!!!!K!!!!s   +A Ac                    |t                      usJ |                                 }|                                 g }|j                            t
          | j        |d||           |                     |d            |d         S )Nr,   r   )r   _allocate_lockr\   r{   run_callback_threadsafer   (_Semaphore__acquire_from_other_thread_cb_Semaphore__spin_on_native_lock)r   rv   rJ   r   r   s        r   __acquire_using_other_hubz#Semaphore.__acquire_using_other_hub  s    !2!4!44444))++///	 	 	 	"";555qzr   c                    |                                  }|                                 d}d}|rt                      |z   }t          |          }	 |                     |           |rt                      }|                     ||          }|                     |           |r|                     d          rdS |r(t                      }||k    rdS ||z
  }||z  }|dk    rdS )Nr   r,   TF)r   r\   r	   r   r   r   r   )	r   rJ   r   absolute_expirationbeginrn   
got_nativenowdurations	            r   __acquire_without_hubsz Semaphore.__acquire_without_hubs  s   ))++ 	8"+++"7  ,,	!OOD!!!" $!33KIIJ""4(((  <<??  4" !kk--- 5;8#a<< 5#	!r   c                    |                                   	 |r*|                    d|          |                                  S |                                |                                  S # |                                  w xY wrD   )_drop_lock_for_switch_outr\   _acquire_lock_for_switch_in)r   r   rJ   s      r   __spin_on_native_lockzSemaphore.__spin_on_native_lock  s    &&(((
	/
  :"**499 ,,.... &&((,,....D,,....s   A* A* *B )r,   Nr   )TN)r$   r%   r&   __doc__r'   r   r9   r<   r!   r@   rB   rG   rK   r\   _py3k_acquirer^   rd   ri   r   rS   rt   r   rs   rr   r   __classcell__r4   s   @r   r   r   0   su       # #JI% % % % % %
 
 
! ! !  *     ! ! !     *^ ^ ^ ^@ M    ' ' '20 0 0#6 #6 #6J( ( (T    (! ! !:/ / / / / / /r   c                   6     e Zd ZdZdZeZd Zd Z fdZ	 xZ
S )r   a  
    BoundedSemaphore(value=1) -> BoundedSemaphore

    A bounded semaphore checks to make sure its current value doesn't
    exceed its initial value. If it does, :class:`ValueError` is
    raised. In most situations semaphores are used to guard resources
    with limited capacity. If the semaphore is released too many times
    it's a sign of a bug.

    If not given, *value* defaults to 1.
    )_initial_valuec                 H    t          j        | g|R i | | j        | _        d S r   )r   r   r*   r   )r   rR   kwargss      r   r   zBoundedSemaphore.__init__  s3    41$111&111"lr   c                     | j         | j        k    r|                     d          t                              |           }|| j        k    rd| _        |S )z
        Like :meth:`Semaphore.release`, but raises :class:`ValueError`
        if the semaphore is being over-released.
        z!Semaphore released too many timesN)r*   r   _OVER_RELEASE_ERRORr   r!   r3   )r   r*   s     r   r!   zBoundedSemaphore.release  sX    
 <4...**+NOOO##D)) d)))DHr   c                 n    t          t          |                                            | j        | _        d S r   )r/   r   _at_fork_reinitr   r*   )r   r4   s    r   r   z BoundedSemaphore._at_fork_reinit  s.    %%55777*r   )r$   r%   r&   r   r'   r.   r   r   r!   r   r   r   s   @r   r   r     so        
 
I
 %+ + +  + + + + + + + + +r   )import_c_accelzgevent.__semaphoreN) 
__future__r   r   r   __all__timer   _native_sleepgevent._compatr	   gevent.exceptionsr
   r   gevent.timeoutr   r   localsgevent._hub_localr   r   
gevent.hubr   objectr   r1   rP   r   r   r   gevent._utilr   globalsr(   r   r   <module>r      s   A @ @ @ @ @ @ @ @ @ 
 ( ' ' ' ' ' $ $ $ $ $ $ 3 3 3 3 3 3 & & & & & & " " " " " "1 1 1  -}	  / / / / / / % % % % % %            	 	 	 	 	v 	 	 	 
	c/ c/ c/ c/ c/  c/ c/ c/L)+ )+ )+ )+ )+y )+ )+ )+p ( ' ' ' ' ' wwyy. / / / / /r   