o
    ‡eÎQ  ã                   @   sê   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	d
„ Zeƒ eƒ d< [d dlmZ d dlmZ d dlmZ G dd„ deƒZeƒ Zeƒ ZG dd„ deƒZG d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                  C   s   t dƒ} | jjS )Nzgevent._abstract_linkable)Ú
__import__Z_abstract_linkableÚAbstractLinkable)Úx© r   úAD:\Projects\ConvertPro\env\Lib\site-packages\gevent/_semaphore.pyÚ_get_linkable   s   r   r   )Úget_hub_if_exists)Úget_hub)Ú	spawn_rawc                   @   s    e Zd ZdZdd„ Zdd„ ZdS )Ú_LockReleaseLink©Úlockc                 C   s
   || _ d S ©Nr   )Úselfr   r   r   r   Ú__init__'   s   
z_LockReleaseLink.__init__c                 C   s   | j  ¡  d S r   )r   Úrelease)r   Ú_r   r   r   Ú__call__*   s   z_LockReleaseLink.__call__N)Ú__name__Ú
__module__Ú__qualname__Ú	__slots__r   r   r   r   r   r   r   "   s    r   c                       s¾   e Zd ZdZdZd,‡ fd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eZdd„ Zdd„ Zdd„ Zdd„ Zd d!„ Zd"d#„ Zd$d%„ Zd&d'„ Zd(d)„ Zd*d+„ Z‡  ZS )/r   aî  
    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.
    )ÚcounterÚ_multithreadedé   Nc                    s8   || _ | j dk rtdƒ‚tt| ƒ |¡ d| _t| _d S )Nr   z$semaphore initial value must be >= 0F)r"   Ú
ValueErrorÚsuperr   r   Z_notify_allÚ_UNSETr#   )r   ÚvalueÚhub©Ú	__class__r   r   r   \   s   

zSemaphore.__init__c                 C   s   d| j jt| ƒ| j|  ¡ f S )Nz"<%s at 0x%x counter=%s _links[%s]>)r+   r   Úidr"   Z	linkcount©r   r   r   r   Ú__str__d   s   üzSemaphore.__str__c                 C   s
   | 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"   r-   r   r   r   Úlockedl   s   
zSemaphore.lockedc                 C   s   |  j d7  _ |  ¡  | 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_notifyr-   r   r   r   r   v   s   zSemaphore.releasec                 C   s
   | 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/   r-   r   r   r   Úready‹   s   
zSemaphore.readyc                 C   ó   |   ¡  d S r   )r1   r-   r   r   r   Ú_start_notify”   ó   zSemaphore._start_notifyc                 C   s   |r|S dS )NTr   )r   ZwaitedZwait_successr   r   r   Ú_wait_return_value—   s   zSemaphore._wait_return_valuec                 C   s    | 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   Útimeoutr   r   r   ÚwaitŸ   s   

zSemaphore.waitTc              
   C   sÆ  | j tu r|  ¡ | _ n
| j |  ¡ krt| _ d}z|  d¡ W n) tyG } z|j}d}| js=|r=|  |||¡W  Y d}~S W Y d}~nd}~ww | jdkrV|  jd8  _dS |sZdS | j turh| j	du rht
ƒ | _	| j	du r||s||  dd|  ¡ df||¡S z|  |¡}W n> tyÁ } z2|j}d}| jr–d}n!t|ƒdkr¢|d jr¢‚ |  | j	tƒ |  ¡ df||¡W  Y d}~S W Y d}~nd}~ww |sÌ|dusÊJ ‚dS | jdksÚJ | j|||fƒ‚|  jd8  _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$   TZNoHubsé   r
   )r#   r'   Z_get_thread_identÚ_MULTIZ_capture_hubr	   Úargsr"   Ú%_Semaphore__acquire_from_other_threadr)   r   Z_getcurrentr7   r
   ÚlenZmain_hubr   )r   Úblockingr8   Zinvalid_thread_useÚeÚsuccessÚexr<   r   r   r   Úacquire´   sd   

€ù
	ýýú€üzSemaphore.acquirec                 C   r3   r   )rC   r-   r   r   r   Ú	__enter__  r5   zSemaphore.__enter__c                 C   r3   r   )r   )r   ÚtÚvÚtbr   r   r   Ú__exit__  r5   zSemaphore.__exit__c                 C   s   | j  |¡ d S r   )Z_linksÚextend)r   Z
unswitchedr   r   r   Ú _handle_unswitched_notifications  s   z*Semaphore._handle_unswitched_notificationsc                 C   s*   | j s
|  |¡ d S | j jd  |¡ d S )Nr   )Z	_notifierZrawlinkr<   Úappend)r   Úlinkr   r   r   Z
__add_link5  s   zSemaphore.__add_linkc                 C   s\   |sJ ‚|d }|d }|d }|d u r|d u r|   |¡S |d u r'|  ||¡S |  |||¡S )Nr   r$   é   )Ú _Semaphore__acquire_without_hubsÚ#_Semaphore__acquire_using_other_hubÚ"_Semaphore__acquire_using_two_hubs)r   Zex_argsr?   r8   Ú
owning_hubÚhub_for_this_threadÚcurrent_greenletr   r   r   Z__acquire_from_other_thread;  s   
þz%Semaphore.__acquire_from_other_threadc           	      C   s‚  |j  ¡ }|j}| |j| ¡ z£t |¡†}zX	 | jdkrE|  jd8  _| jdks.J | fƒ‚W W d   ƒ W |  |¡ | 	¡  | 
¡  dS |  |¡ |  |¡ |  d¡}|rn|W W  d   ƒ W |  |¡ | 	¡  | 
¡  S q tyš } z ||ur{‚ W Y d }~W d   ƒ W |  |¡ | 	¡  | 
¡  dS d }~ww 1 sžw   Y  W |  |¡ | 	¡  | 
¡  d S |  |¡ | 	¡  | 
¡  w )Nr$   r   TF)ÚloopZasync_Zsend_ignoring_argÚstartÚswitchr   Z_start_new_or_dummyr"   Ú_quiet_unlink_allÚstopÚcloseÚ_Semaphore__add_linkZ_switch_to_hubrC   )	r   rR   rS   r8   ÚwatcherÚsendÚtimerÚresultÚtexr   r   r   Z__acquire_using_two_hubs`  sT   

ø

î

ì

è
è
€ùë

þ
z"Semaphore.__acquire_using_two_hubsc                 C   s0   z|   ||¡}| |¡ W | ¡  |S | ¡  w r   )rC   rK   r   )r   Úresultsr?   r8   Úthread_lockr^   r   r   r   Z__acquire_from_other_thread_cbŠ  s   
ÿz(Semaphore.__acquire_from_other_thread_cbc                 C   sN   |t ƒ usJ ‚|  ¡ }| ¡  g }|j t| j|d||¡ |  |d ¡ |d S )Nr$   r   )r   Ú_allocate_lockrC   rT   Zrun_callback_threadsafer   Ú(_Semaphore__acquire_from_other_thread_cbÚ_Semaphore__spin_on_native_lock)r   rQ   r8   ra   r`   r   r   r   Z__acquire_using_other_hub’  s   úz#Semaphore.__acquire_using_other_hubc           	      C   s    |   ¡ }| ¡  d}d}|rtƒ | }t|ƒ}	 |  |¡ |r"tƒ }|  ||¡}|  |¡ |r6|  d¡r6dS |rOtƒ }||krAdS || }||8 }|dkrOdS q)Nr   r$   TF)rb   rC   r   r   rZ   rd   rW   )	r   r8   ra   Zabsolute_expirationÚbeginrL   Z
got_nativeÚnowÚdurationr   r   r   Z__acquire_without_hubs¦  s2   



ïz Semaphore.__acquire_without_hubsc                 C   sl   d}|r	t ƒ | }|  ¡  z#| d¡s*|r!t ƒ |kr!W |  ¡  dS tdƒ | d¡rW |  ¡  dS |  ¡  w )Nr   Fgü©ñÒMbP?T)r   Z_drop_lock_for_switch_outrC   Z_acquire_lock_for_switch_inÚ_native_sleep)r   ra   r8   Z
expirationr   r   r   Z__spin_on_native_lockÃ  s   

ý
üzSemaphore.__spin_on_native_lock)r$   Nr   )TN)r   r   r    Ú__doc__r!   r   r.   r0   r   r2   r4   r6   r9   rC   Z_py3k_acquirerD   rH   rJ   rZ   r=   rP   rc   rO   rN   rd   Ú__classcell__r   r   r*   r   r   0   s.    !

	

`%*c                       s8   e Zd ZdZdZeZdd„ Zdd„ Z‡ fdd„Z	‡  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                 O   s$   t j| g|¢R i |¤Ž | j| _d S r   )r   r   r"   rk   )r   r<   Úkwargsr   r   r   r   ì  s   zBoundedSemaphore.__init__c                 C   s4   | 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"   rk   Ú_OVER_RELEASE_ERRORr   r   r)   )r   r"   r   r   r   r   ð  s   


zBoundedSemaphore.releasec                    s   t t| ƒ ¡  | j| _d S r   )r&   r   Ú_at_fork_reinitrk   r"   r-   r*   r   r   rn   ÿ  s   z BoundedSemaphore._at_fork_reinit)r   r   r    ri   r!   r%   rm   r   r   rn   rj   r   r   r*   r   r   Ø  s    )Úimport_c_accelzgevent.__semaphoreN) Ú
__future__r   r   r   Ú__all__Útimer   rh   Zgevent._compatr   Zgevent.exceptionsr	   r
   Zgevent.timeoutr   r   ÚlocalsZgevent._hub_localr   r   Z
gevent.hubr   Úobjectr   r'   r;   r   r   r   Zgevent._utilro   Úglobalsr   r   r   r   Ú<module>   s2   	þ   +8