a
    &ñ»j@6  ã                   @   s|   d dl Z d dlZd dlZd dlZd dlmZ d dlmZ G dd„ deƒZ	dd„ Z
dd	„ Zd
d„ Zejejedœdd„ƒZdS )é    N)ÚOptional)Ú_utilsc                   @   sÒ   e Zd ZdZdZdZejejfdd„Z	e
edœdd„ƒZd&eed
œdd„Zedœdd„Ze
ee dœdd„ƒZdd„ Zdd„ Zdd„ Zd'dd„Zejdd„ ƒZdd„ Zd(dd„Zdd „ Zd!d"„ Zejd#d$„ ƒZd%S ))ÚReaderWriterLockz$An inter-thread readers writer lock.ÚwÚrc                 C   s.   d| _ d| _t ¡ | _i | _|ƒ | _|| _dS )aH  
        Args:
            condition_cls:
                Optional custom `Condition` primitive used for synchronization.
            current_thread_functor:
                Optional function that returns the identity of the thread in case
                threads are not properly identified by threading.current_thread
        Nr   )Ú_writerÚ_writer_entriesÚcollectionsÚdequeÚ_pending_writersÚ_readersÚ_condÚ_current_thread)ÚselfZcondition_clsZcurrent_thread_functor© r   ú4E:\soccer\ml_env\Lib\site-packages\fasteners/lock.pyÚ__init__#   s    
zReaderWriterLock.__init__)Úreturnc                 C   s
   t | jƒS )zhCheck if there pending writers

        Returns:
            Whether there are pending writers.
        )Úboolr   ©r   r   r   r   Úhas_pending_writers5   s    z$ReaderWriterLock.has_pending_writersT)Úcheck_pendingr   c                 C   s,   |   ¡ }| j|krdS |r$|| jv S dS dS )a  Check if caller is a writer (optionally pending writer).

        Args:
            check_pending:
                Whether to check for pending writer status.

        Returns:
            Whether the caller is the active (or optionally pending) writer.
        TFN)r   r   r   )r   r   Úmer   r   r   Ú	is_writer>   s    


zReaderWriterLock.is_writerc                 C   s   |   ¡ }|| jv S )zkCheck if caller is a reader.

        Returns:
            Whether the caller is an active reader.
        )r   r   ©r   r   r   r   r   Ú	is_readerP   s    zReaderWriterLock.is_readerc                 C   s    | j dur| jS | jr| jS dS )z–Caller ownership (if any) of the lock

        Returns:
            `'w'` if caller is a writer, `'r'` if caller is a reader, None otherwise.
        N)r   ÚWRITERr   ÚREADERr   r   r   r   ÚownerY   s
    
zReaderWriterLock.ownerc                 C   s   |   ¡ }|  |¡ dS )z±Acquire a read lock.

        Will wait until no active or pending writers.

        Raises:
            RuntimeError: if a pending writer tries to acquire a read lock.
        N)r   Ú_acquire_read_lockr   r   r   r   Úacquire_read_lockg   s    z"ReaderWriterLock.acquire_read_lockc                 C   s   |   ¡ }|  |¡ dS )zxRelease a read lock.

        Raises:
            RuntimeError: if the current thread does not own a read lock.
        N)r   Ú_release_read_lockr   r   r   r   Úrelease_read_lockr   s    z"ReaderWriterLock.release_read_lockc                 C   sž   || j v rtd| ƒ‚| j�n | jd u s2| j|krp|| jv rT| j| d | j|< q|n| j|ksd| jspd| j|< q|| j ¡  qW d   ƒ n1 s�0    Y  d S )NzFWriter %s can not acquire a read lock while waiting for the write locké   )r   ÚRuntimeErrorr   r   r   r   Úwaitr   r   r   r   r   {   s    
þ

z#ReaderWriterLock._acquire_read_lockc              	   C   sŽ   | j �t z2| j| }|dkr,|d | j|< n| j |¡ W n& ty`   |r\td|› d�ƒ‚Y n0 | j  ¡  W d   ƒ n1 s€0    Y  d S )Nr#   úThread z does not own a read lock)r   r   ÚpopÚKeyErrorr$   Ú
notify_all)r   r   Úraise_on_not_ownedZme_instancesr   r   r   r!   �   s    
z#ReaderWriterLock._release_read_lockc              
   c   s@   |   ¡ }|  |¡ z| V  W | j|dd� n| j|dd� 0 dS )zÅContext manager that grants a read lock.

        Will wait until no active or pending writers.

        Raises:
            RuntimeError: if a pending writer tries to acquire a read lock.
        F)r*   N)r   r   r!   r   r   r   r   Ú	read_lock¡   s
    	
zReaderWriterLock.read_lockc                 C   s�   |   ¡ rtd| ƒ‚| j�b | j |¡ t| jƒdkrb| jd u rb| jd |krb| j ¡ | _d| _	qn| j 
¡  q(W d   ƒ n1 s‚0    Y  d S )Nz4Reader %s to writer privilege escalation not allowedr   r#   )r   r$   r   r   ÚappendÚlenr   r   Úpopleftr   r%   r   r   r   r   Ú_acquire_write_lock±   s    ÿz$ReaderWriterLock._acquire_write_lockc                 C   s@   | j �& d | _d| _| j  ¡  W d   ƒ n1 s20    Y  d S )Nr   )r   r   r   r)   )r   r   r*   r   r   r   Ú_release_write_lockÁ   s    z$ReaderWriterLock._release_write_lockc                 C   s0   |   ¡ }| j|kr"|  jd7  _n
|  |¡ dS )a	  Acquire a write lock.

        Will wait until no active readers. Blocks readers after acquiring.

        Guaranteed for locks to be processed in fair order (FIFO).

        Raises:
            RuntimeError: if an active reader attempts to acquire a lock.
        r#   N)r   r   r   r/   r   r   r   r   Úacquire_write_lockÇ   s    

z#ReaderWriterLock.acquire_write_lockc                 C   sJ   |   ¡ }| j|kr6|  jd8  _| jdkrF|  |¡ ntd|› d�ƒ‚dS )zzRelease a write lock.

        Raises:
            RuntimeError: if the current thread does not own a write lock.
        r#   r   r&   z does not own a write lockN)r   r   r   r0   r$   r   r   r   r   Úrelease_write_lock×   s    

z#ReaderWriterLock.release_write_lockc              	   c   s~   |   ¡ }| jdd�rN|  jd7  _z| V  W |  jd8  _qz|  jd8  _0 n,|  |¡ z| V  W |  |¡ n|  |¡ 0 dS )a  Context manager that grants a write lock.

        Will wait until no active readers. Blocks readers after acquiring.

        Guaranteed for locks to be processed in fair order (FIFO).

        Raises:
            RuntimeError: if an active reader attempts to acquire a lock.
        F)r   r#   N)r   r   r   r/   r0   r   r   r   r   Ú
write_lockå   s    "
zReaderWriterLock.write_lockN)T)T)T)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r   Ú	threadingÚ	ConditionÚcurrent_threadr   Úpropertyr   r   r   r   r   Ústrr   r    r"   r   r!   Ú
contextlibÚcontextmanagerr+   r/   r0   r1   r2   r3   r   r   r   r   r      s0   þ
		


r   c                     s8   ‡ fdd„}ˆ s| s|S t | ƒdkr0|| d ƒS |S dS )aÐ  A locking **method** decorator.

    It will look for a provided attribute (typically a lock or a list
    of locks) on the first argument of the function decorated (typically this
    is the 'self' object) and before executing the decorated function it
    activates the given lock or list of locks as a context manager,
    automatically releasing that lock on exit.

    NOTE(harlowja): if no attribute name is provided then by default the
    attribute named '_lock' is looked for (this attribute is expected to be
    the lock/list of locks object/s) in the instance object this decorator
    is attached to.

    NOTE(harlowja): a custom logger (which will be used if lock release
    failures happen) can be provided by passing a logger instance for keyword
    argument ``logger``.

    NOTE(paulius): This function is DEPRECATED and will be kept until the end
    of time. It is potentially used by oslo, but too specific to be recommended
    for other projects
    c                    s4   ˆ  dd¡‰ ˆ  d¡‰t ˆ¡‡ ‡‡fdd„ƒ}|S )NÚlockÚ_lockÚloggerc                    sÌ   t | ˆ ƒ}t|ttfƒrŠtjˆd��T}t|ƒD ]$\}}| |¡s.t 	d|d  ¡‚q.ˆ| g|¢R i |¤ŽW  d   ƒ S 1 s~0    Y  n>|}|�& ˆ| g|¢R i |¤ŽW  d   ƒ S 1 s¾0    Y  d S )N)rA   zUnable to acquire lock %sr#   )
ÚgetattrÚ
isinstanceÚtupleÚlistr   Z	LockStackÚ	enumerateÚacquire_lockr8   ÚThreadError)r   ÚargsÚkwargsZ
attr_valueÚstackÚir?   ©Ú	attr_nameÚfrA   r   r   Úwrapper  s    

ÿ6z*locked.<locals>.decorator.<locals>.wrapper©ÚgetÚ	functoolsÚwraps©rO   rP   ©rJ   rM   r   Ú	decorator  s
    
zlocked.<locals>.decoratorr#   r   N©r-   ©rI   rJ   rW   r   rV   r   Úlockedÿ   s    rZ   c                     s8   ‡ fdd„}ˆ s| s|S t | ƒdkr0|| d ƒS |S dS )aò  Acquires & releases a read lock around call into decorated method.

    NOTE(harlowja): if no attribute name is provided then by default the
    attribute named '_lock' is looked for (this attribute is expected to be
    a :py:class:`.ReaderWriterLock`) in the instance object this decorator
    is attached to.

    NOTE(paulius): This function is DEPRECATED and will be kept until the end
    of time. It is potentially used by oslo, but too specific to be recommended
    for other projects
    c                    s(   ˆ  dd¡‰ t ˆ¡‡ ‡fdd„ƒ}|S )Nr?   r@   c                    sL   t | ˆ ƒ}| ¡ �& ˆ| g|¢R i |¤ŽW  d   ƒ S 1 s>0    Y  d S ©N)rB   r+   ©r   rI   rJ   Zrw_lock©rN   rO   r   r   rP   F  s    

z/read_locked.<locals>.decorator.<locals>.wrapperrQ   rU   rV   r]   r   rW   C  s    zread_locked.<locals>.decoratorr#   r   NrX   rY   r   rV   r   Úread_locked6  s    r^   c                     s8   ‡ fdd„}ˆ s| s|S t | ƒdkr0|| d ƒS |S dS )aú  Acquires & releases a write lock around call into decorated method.

    NOTE(harlowja): if no attribute name is provided then by default the
    attribute named '_lock' is looked for (this attribute is expected to be
    a :py:class:`.ReaderWriterLock` object) in the instance object this
    decorator is attached to.

    NOTE(paulius): This function is DEPRECATED and will be kept until the end
    of time. It is potentially used by oslo, but too specific to be recommended
    for other projects
    c                    s(   ˆ  dd¡‰ t ˆ¡‡ ‡fdd„ƒ}|S )Nr?   r@   c                    sL   t | ˆ ƒ}| ¡ �& ˆ| g|¢R i |¤ŽW  d   ƒ S 1 s>0    Y  d S r[   )rB   r3   r\   r]   r   r   rP   i  s    

z0write_locked.<locals>.decorator.<locals>.wrapperrQ   rU   rV   r]   r   rW   f  s    zwrite_locked.<locals>.decoratorr#   r   NrX   rY   r   rV   r   Úwrite_lockedY  s    r_   )r?   r   c                 c   s4   |   d¡}z|V  W |r0|  ¡  n|r.|  ¡  0 dS )aö  Context manager that attempts to acquire a lock without a timeout, and
    releases it on exit (if acquired).

    Args:
        lock:
            A lock to try to acquire.

    Returns:
        Whether the lock was acquired.

    # NOTE(harlowja): the keyword argument for 'blocking' does not work
    # in py2.x and only is fixed in py3.x (this adjustment is documented
    # and/or debated in http://bugs.python.org/issue10789); so we'll just
    # stick to the format that works in both (oddly the keyword argument
    # works in py2.x but only with reentrant locks).

    NOTE(paulius): This function is DEPRECATED and will be kept until the end
    of time. It is potentially used by oslo, but too specific to be recommended
    for other projects
    FN)ÚacquireÚrelease)r?   Z
was_lockedr   r   r   Útry_lock|  s    

ÿrb   )r	   r=   rS   r8   Útypingr   Z	fastenersr   Úobjectr   rZ   r^   r_   r>   ÚLockr   rb   r   r   r   r   Ú<module>   s    c7##