o VEVJ,@sddlZddlZddlZddlmZddlZz ddlZddlmZWn e y/dZdZYnwddZ ddZ Gdd d e Z ejd d Zd d ZdS)N)_utils)patcherc4fdd}s |s |St|dkr||dS|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. c(ddtfdd}|S)Nlock_lockcLt|}||g|Ri|WdS1swYdSN)getattr read_lockselfargskwargsrw_lock attr_namef0/usr/lib/python3/dist-packages/fasteners/lock.pywrapper2  $z/read_locked..decorator..wrappergetsixwrapsrrrrr decorator/ zread_locked..decoratorrlenrrrrrr read_locked&    r$cr)aDAcquires & 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. cr)Nrrcrr )r write_lockr rrrrQrz0write_locked..decorator..wrapperrrrrrrNrzwrite_locked..decoratorr rr!r#rrr write_lockedEr%r'c@szeZdZdZdZdZeddZej dfddZ e d d Z dd d Z e ddZddZejddZejddZdS)ReaderWriterLockaA reader/writer lock. This lock allows for simultaneous readers to exist but only one writer to exist for use-cases where it is useful to have such types of locks. Currently a reader can not escalate its read lock to a write lock and a writer can not acquire a read lock while it is waiting on the write lock. In the future these restrictions may be relaxed. This can be eventually removed if http://bugs.python.org/issue8800 ever gets accepted into the python standard threading library... wrcCs&tdurtdurtdrtjStjS)Nthread)eventleteventlet_patcheris_monkey_patched getcurrent threadingcurrent_threadrrrr_fetch_current_thread_functorzs z.ReaderWriterLock._fetch_current_thread_functorNcCs8d|_t|_i|_||_|dur|}||_dSr )_writer collectionsdeque_pending_writers_readers_condr2_current_thread)r condition_clscurrent_thread_functorrrr__init__s  zReaderWriterLock.__init__cCs t|jS)z@Returns if there are writers waiting to become the *one* writer.)boolr6r rrrhas_pending_writerss z$ReaderWriterLock.has_pending_writersTcCs(|}|j|kr dS|r||jvSdS)z?Returns if the caller is the active writer or a pending writer.TF)r9r3r6)r check_pendingmerrr is_writers   zReaderWriterLock.is_writercCs |jdur|jS|jr|jSdS)z9Returns whether the lock is locked by a writer or reader.N)r3WRITERr7READERr>rrrowners zReaderWriterLock.ownercCs|}||jvS)z,Returns if the caller is one of the readers.)r9r7)r rArrr is_readers zReaderWriterLock.is_readerccs|}||jvrtd||j5 |jdus|j|kr;z |j|d|j|<Wnty9d|j|<Ynwn|jqWdn1sKwYzB|VW|j1z|j|}|dkrk|d|j|<n|j|Wn ty{Ynw|j WddS1swYdS|j0z|j|}|dkr|d|j|<n|j|Wn tyYnw|j Wdw1swYw)zContext manager that grants a read lock. Will wait until no active or pending writers. Raises a ``RuntimeError`` if a pending writer tries to acquire a read lock. zFWriter %s can not acquire a read lock while waiting for the write lockTNr ) r9r6 RuntimeErrorr8r3r7KeyErrorwaitpop notify_all)r rA me_instancesrrrr sX        *    zReaderWriterLock.read_lockccs.|}|jdd}|r|std||r|VdS|j/|j| t|jdkrC|j durC|jd|krC|j |_ n|j q)Wdn1sSwYz"|VW|jd|_ |j WddS1stwYdS|jd|_ |j Wdw1swYw)zContext manager that grants a write lock. Will wait until no active readers. Blocks readers after acquiring. Raises a ``RuntimeError`` if an active reader attempts to acquire a lock. F)r@z4Reader %s to writer privilege escalation not allowedTrN) r9rBrFrGr8r6appendr"r7r3popleftrIrK)r rA i_am_writerrrrr&s:        * zReaderWriterLock.write_lock)T)__name__ __module__ __qualname____doc__rCrD staticmethodr2r0 Conditionr<propertyr?rBrErF contextlibcontextmanagerr r&rrrrr(ds&       +r(ccs:|d}z|VW|r|dSdS|r|ww)zDAttempts to acquire a lock, and auto releases if acquired (on exit).FN)acquirerelease)r was_lockedrrrtry_locks   r\cr)aA 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``. cs4dddtfdd}|S)Nrrloggercst|}t|ttfrFtjd*}t|D]\}}||s)t d|dq|g|Ri|WdS1s?wYdS|}||g|Ri|WdS1s`wYdS)N)r]zUnable to acquire lock %sr ) r isinstancetuplelistr LockStack enumerate acquire_lockr0 ThreadError)r rr attr_valuestackirrrr]rrr%s  $$z*locked..decorator..wrapperrrrrhrr!s  zlocked..decoratorr rr!r#rrrlockeds   ri)r4rWr0 fastenersrrr,rr- ImportErrorr$r'objectr(rXr\rirrrrs&