Cameron Simpson wrote at 2020-3-15 10:17 +1100: >On 12Mar2020 20:08, Dieter Maurer <die...@handshake.de> wrote: > ... >>The documentation for the basic lock explicitely allows >>lock release by a foreign thread. >>As I understand the documentation, this lock type is by design >>very basic - a mechanism to implement higher level abstractions. >>I use other synchronisation mechanisms when the basic lock does >>not fit my requirements. > >Aye. I have certainly gone: >- take lock associated with some task specific resource >- set up task >- kick off worker Thread (or queue worker function for later) >- worker releases the lock > >However, having an error check mode disallowing attempts by the same >Thread to take a Lock it itself took seems valuable. If the lock object >has that piece of information (IIRC it does).
Below is a Python 3 implementation for such a lock. The quirks required to get a nested "with" safe might be seen as an indication that it should not be implemented in the base lock class. from _thread import allocate_lock, get_ident class NestedTLockError(RuntimeError): """Special error used to make nested ``with`` statements safe.""" def __init__(self, message, lock): self._lock = lock super().__init__(message, lock) class TLock: """A lock preventing the same thread to get the lock twice.""" def __init__(self): self._lock = allocate_lock() self._tid = None def acquire(self, wait=True, timeout=-1): tid = get_ident() if self._tid == tid: # this remains stable raise NestedTLockError("already acquired", self) acquired = self._lock.acquire(0) or self._lock.acquire(wait, timeout) if acquired: # Lock successfully acquired - no other thread will interfere self._tid = tid return acquired def __enter__(self): return self.acquire() def release(self): # the application is responsible that nothing interferes # with our release self._tid = None self._lock.release() def __exit__(self, t, v, tb): if not self.locked(): return # the ``__enter__`` failed if t is NestedTLockError and v._lock is self: # the ``__enter__`` failed due to nested lock acquisition # we must not release the lock (it would be too early) # but must allow the outer ``__exit__`` to release the lock v._lock = None return self.release() def locked(self): return self._lock.locked() -- https://mail.python.org/mailman/listinfo/python-list