from threading import RLock from openflexure_microscope.exceptions import LockError class StrictLock(object): """ Class that behaves like a Python RLock, but with stricter timeout conditions and custom exceptions. Args: timeout (int): Time, in seconds, lock acquisition will wait before raising an exception Attributes: _lock (:py:class:`threading.RLock`): Parent RLock object timeout (int): Time, in seconds, lock acquisition will wait before raising an exception """ def __init__(self, timeout=1): self._lock = RLock() self.timeout = timeout def locked(self): return self._lock.locked() def acquire(self, blocking=True): return self._lock.acquire(blocking, timeout=self.timeout) def __enter__(self): result = self._lock.acquire(blocking=True, timeout=self.timeout) if result: return result else: raise LockError("ACQUIRE_ERROR", self) def __exit__(self, *args): self._lock.release() def release(self): self._lock.release() class CompositeLock(object): """ Class that behaves like a :py:class:`openflexure_microscope.common.lock.StrictLock`, but allows multiple locks to be acquired and released. Args: locks (list): List of parent RLock objects timeout (int): Time, in seconds, lock acquisition will wait before raising an exception Attributes: locks (list): List of parent RLock objects timeout (int): Time, in seconds, lock acquisition will wait before raising an exception """ def __init__(self, locks, timeout=1): self.locks = locks self.timeout = timeout def acquire(self, blocking=True): return (lock.acquire(blocking=blocking) for lock in self.locks) def __enter__(self): result = (lock.acquire(blocking=True) for lock in self.locks) if all(result): return result else: raise LockError("ACQUIRE_ERROR", self) def __exit__(self, *args): for lock in self.locks: lock.release() def release(self): for lock in self.locks: lock.release()