openflexure-microscope-server/openflexure_microscope/lock.py
2019-05-24 16:32:20 +01:00

74 lines
2.2 KiB
Python

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.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()