Class ObjectLockManager<O,​L>

  • Type Parameters:
    O - The type of the objects to be locked (locked object type).
    L - The type of the objects that lock (lock owning type).
    Direct Known Subclasses:
    OptimisticObjectLockManager, PessimisticObjectLockManager

    public abstract class ObjectLockManager<O,​L>
    extends Object
    A manager for locking objects with reentrant locks whereas the locks are itself object specific. That is, an object locks another object; the locking objects are managed using a LockCountManager which allows to flexibly change the equality of the locking objects.
    The locks are reentrant and read or write locks, that is a locking object (or also some other locking object considered equal) may acquire a lock multiple times (and have to release it multiple times with the same type (read or write)) but all non-equal locking objects will not receive the lock in case of a write lock. A read lock may be acquired by arbitrary other locking objects as long as there is no different locking object waiting to write.
    How a lock works depends on the LockCountManager provided to the constructor of this manager. This may treat various objects as equal concerning locks (for instance object hierarchies) or not.

    Lock upgrades and downgrades are impossible. When requesting a read lock while having a write the read lock will implicitly be granted as write lock. When releasing such a read lock, this will be implicitly a release of a write lock.

    This class only provides the basic means, the real locking, lock creation and synchronisation has to be provided by subclasses. These may also whether they behave optimistically or pessimistically.

    Author:
    Ulrich Kreher
    • Field Detail

      • lockCountManager

        protected final Class<? extends LockCountManager<? super L>> lockCountManager
        The lock count manager implementation which handles the lock counts per lock.
      • lockType

        protected final String lockType
        The type of lock as informal string for user information.
      • logger

        protected final Logger logger
        The logger for logging lock acquisitions and releasing - great for debugging purpose.
    • Constructor Detail

      • ObjectLockManager

        protected ObjectLockManager​(Class<? extends LockCountManager<? super L>> lockCountManager,
                                    String lockType,
                                    Logger logger)
        Creates a new ObjectLockManager with the designated lock count manager providing the "equality" for the designated reentrant locks and of the designated type.
        Parameters:
        lockCountManager - The lock count manager that encapsulates what locking objects are treated as equal when acquiring a lock. The provided class needs an accessible (public) constructor without parameters.
        lockType - The type of locks managed by the created object. This is for user information only.
        logger - The logger for log messages.
    • Method Detail

      • getObjectLock

        protected abstract ReentrantLock<L> getObjectLock​(O lockedObject)
        Gets the lock for the designated object. This allows subclasses to use their own data structure for lock management.
        Parameters:
        lockedObject - The locked object for which to retrieve the corresponding reentrant lock.
        Returns:
        The reentrant lock for the designated locked object or null in case the designated object is not locked.
      • getLockForObject

        public final void getLockForObject​(boolean writeLock,
                                           L lockingObject,
                                           O lockedObject,
                                           long timeout)
                                    throws InterruptedException,
                                           TimeoutException
        Locks the designated object by the designated locking object. Since the locks are expected to be short-term this method will wait until the lock can be successfully acquired. The locks are reentrant, that is, it needs to be unlocked for every call to this method and for the right lock type (read or write lock).
        When locking an object for reading while already having the write lock for the object, the lock will be granted as write lock. When releasing such a read lock, a write lock will be released implicitly instead.
        Parameters:
        writeLock - Whether to acquire a write lock.
        lockingObject - The object locking the designated object.
        lockedObject - The object to lock.
        timeout - The time to wait for the lock. A timeout <= 0 means to wait forever (or until the lock is granted).
        Throws:
        InterruptedException - If the thread is interrupted while waiting for the lock, an InterruptedException will be thrown.
        TimeoutException - If the designated timeout elapsed before the lock can be acquired, a TimeoutException will be thrown.
        RuntimeException - If the provided lock or the lock count manager can not be instantiated, a RuntimeException will be thrown.
      • getLockForObjectReadWriteDirect

        protected abstract void getLockForObjectReadWriteDirect​(boolean writeLock,
                                                                L lockingObject,
                                                                O lockedObject,
                                                                long timeout)
                                                         throws InterruptedException,
                                                                TimeoutException
        Cf. documentation of getLockForObject(boolean, Object, Object, long). Implementors can rely on the first boolean to be set appropriately depending on present locks.
        Parameters:
        writeLock - Whether to acquire a write lock. This will already be adapted to a write lock if required, that is, requesting a read lock while having the write lock already.
        lockingObject - The object locking the designated object.
        lockedObject - The object to lock.
        timeout - The time to wait for the lock. A timeout <= 0 means to wait forever (or until the lock is granted).
        Throws:
        InterruptedException - If the thread is interrupted while waiting for the lock, an InterruptedException will be thrown.
        TimeoutException - If the designated timeout elapsed before the lock can be acquired, a TimeoutException will be thrown.
        RuntimeException - If the provided lock or the lock count manager can not be instantiated, a RuntimeException will be thrown.
      • hasLock

        public boolean hasLock​(boolean writeLock,
                               L lockingObject,
                               O lockedObject)
        Checks whether the designated object is locked for reading or writing by the designated locking object.
        Parameters:
        writeLock - Whether the locking object is to be checked for having a write lock on the designated locked object.
        lockingObject - The object to check for having the lock on the designated object.
        lockedObject - The object to check for the lock lock.
        Returns:
        Whether the designated locking object has the designated lock on the designated locked object.
      • unlockObject

        public boolean unlockObject​(boolean writeLock,
                                    L lockingObject,
                                    O lockedObject)
                             throws LockException
        Unlocks the designated object by the designated locking object. The lock will not be released if it is held several times. If the LockException occurs while trying to unlock, the lock will still be held when returning.
        Parameters:
        writeLock - Whether to release the write lock.
        lockingObject - The object unlocking the designated object.
        lockedObject - The object to unlock.
        Returns:
        Whether a notification has been sent when unlocking. This is the same as ReentrantLock.Lock.unlock(Object) and usually only required by subclasses.
        Throws:
        LockException - If the locked object has not locked at all or not by the designated locking object, a LockException will be thrown.