U
    VÚd§'  ã                   @   s8   d Z ddlmZmZmZ ddlmZ G dd„ deƒZdS )zî
ReadWriteLock

Taken from http://code.activestate.com/recipes/502283/

locks.py - Read-Write lock thread lock implementation

See the class documentation for more info.

Copyright (C) 2007, Heiko Wundram.
Released under the BSD-license.
é    )Ú	ConditionÚcurrentThreadÚLock)Útimec                   @   s4   e Zd ZdZdd„ Zddd„Zddd„Zd	d
„ ZdS )ÚReadWriteLocka[  Read-Write lock class. A read-write lock differs from a standard
    threading.RLock() by allowing multiple threads to simultaneously hold a
    read lock, while allowing only a single thread to hold a write lock at the
    same point of time.

    When a read lock is requested while a write lock is held, the reader
    is blocked; when a write lock is requested while another write lock is
    held or there are read locks, the writer is blocked.

    Writers are always preferred by this implementation: if there are blocked
    threads waiting for a write lock, current readers may request more read
    locks (which they eventually should free, as they starve the waiting
    writers otherwise), but a new thread requesting a read lock will not
    be granted one, and block. This might mean starvation for readers if
    two writer threads interweave their calls to acquire_write() without
    leaving a window only for readers.

    In case a current reader requests a write lock, this can and will be
    satisfied without giving up the read locks first, but, only one thread
    may perform this kind of lock upgrade, as a deadlock would otherwise
    occur. After the write lock has been granted, the thread will hold a
    full write lock, and not be downgraded after the upgrading call to
    acquire_write() has been match by a corresponding release().
    c                 C   s(   t tƒ ƒ| _d| _d| _g | _i | _dS )z Initialize this read-write lock.Nr   )r   r   Ú_ReadWriteLock__conditionÚ_ReadWriteLock__writerÚ"_ReadWriteLock__upgradewritercountÚ_ReadWriteLock__pendingwritersÚ_ReadWriteLock__readers)Úself© r   ú/opt/wsgidav/wsgidav/rw_lock.pyÚ__init__4   s
    zReadWriteLock.__init__Nc                 C   sð   |dk	rt ƒ | }tƒ }| j ¡  z¼| j|krD|  jd7  _W ¢ dS | jdkr | jsZ| jr€|| j	kr | j	|  d7  < W ¢fdS n | j	 
|d¡d | j	|< W ¢DdS |dk	rÐ|t ƒ  }|dkrÂtdƒ‚| j |¡ qD| j ¡  qDW 5 | j ¡  X dS )af  Acquire a read lock for the current thread, waiting at most
        timeout seconds or doing a non-blocking check in case timeout is <= 0.

        In case timeout is None, the call to acquire_read blocks until the
        lock request can be serviced.

        In case the timeout expires before the lock could be serviced, a
        RuntimeError is thrown.Né   r   zAcquiring read lock timed out)r   r   r   ÚacquireÚreleaser   Ú_ReadWriteLock__writercountr	   r
   r   ÚgetÚRuntimeErrorÚwait)r   ÚtimeoutÚendtimeÚmeÚ	remainingr   r   r   Úacquire_readC   s,    







zReadWriteLock.acquire_readc                 C   sn  |dk	rt ƒ | }tƒ d }}| j ¡  z2| j|krN|  jd7  _W ¢dS || jkrz| jrft	dƒ‚d}| j 
|¡| _n| j |¡ | jsô| jdkrô| jrÂ|rô|| _| jd | _d| _W ¢¢dS n2| jd |krô|| _d| _| jdd… | _W ¢ndS |dk	rN|t ƒ  }|dkr@|r,| j| j|< d| _n| j |¡ tdƒ‚| j |¡ q†| j ¡  q†W 5 | j ¡  X dS )aê  Acquire a write lock for the current thread, waiting at most
        timeout seconds or doing a non-blocking check in case timeout is <= 0.

        In case the write lock cannot be serviced due to the deadlock
        condition mentioned above, a ValueError is raised.

        In case timeout is None, the call to acquire_write blocks until the
        lock request can be serviced.

        In case the timeout expires before the lock could be serviced, a
        RuntimeError is thrown.NFr   z(Inevitable dead lock, denying write lockTr   zAcquiring write lock timed out)r   r   r   r   r   r   r   r   r	   Ú
ValueErrorÚpopr
   ÚappendÚremover   r   )r   r   r   r   Zupgradewriterr   r   r   r   Úacquire_writer   sJ    








zReadWriteLock.acquire_writec                 C   sž   t ƒ }| j ¡  z|| j|krB|  jd8  _| jsŠd| _| j ¡  nH|| jkr‚| j|  d8  < | j| sŠ| j|= | jsŠ| j ¡  ntdƒ‚W 5 | j ¡  X dS )zkRelease the currently held lock.

        In case the current thread holds no lock, a ValueError is thrown.r   NzTrying to release unheld lock)	r   r   r   r   r   r   Ú	notifyAllr   r   )r   r   r   r   r   r   Ç   s     



zReadWriteLock.release)N)N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r   r    r   r   r   r   r   r      s
   
/
Ur   N)r%   Ú	threadingr   r   r   r   Úobjectr   r   r   r   r   Ú<module>   s   