bpo-36688: Adding an implementation of RLock in _dummy_thread (GH-12943) · python/cpython@351b0e7
@@ -14,7 +14,7 @@
1414# Exports only things specified by thread documentation;
1515# skipping obsolete synonyms allocate(), start_new(), exit_thread().
1616__all__ = ['error', 'start_new_thread', 'exit', 'get_ident', 'allocate_lock',
17-'interrupt_main', 'LockType']
17+'interrupt_main', 'LockType', 'RLock']
18181919# A dummy value
2020TIMEOUT_MAX = 2**31
@@ -148,6 +148,36 @@ def __repr__(self):
148148hex(id(self))
149149 )
150150151+152+class RLock(LockType):
153+"""Dummy implementation of threading._RLock.
154+155+ Re-entrant lock can be aquired multiple times and needs to be released
156+ just as many times. This dummy implemention does not check wheter the
157+ current thread actually owns the lock, but does accounting on the call
158+ counts.
159+ """
160+def __init__(self):
161+super().__init__()
162+self._levels = 0
163+164+def acquire(self, waitflag=None, timeout=-1):
165+"""Aquire the lock, can be called multiple times in succession.
166+ """
167+locked = super().acquire(waitflag, timeout)
168+if locked:
169+self._levels += 1
170+return locked
171+172+def release(self):
173+"""Release needs to be called once for every call to acquire().
174+ """
175+if self._levels == 0:
176+raise error
177+if self._levels == 1:
178+super().release()
179+self._levels -= 1
180+151181# Used to signal that interrupt_main was called in a "thread"
152182_interrupt = False
153183# True when not executing in a "thread"