LatticeLocker.h

Classes

LatticeLocker -- Class to hold a (user) lock on a lattice. (full description)

class LatticeLocker

Interface

Public Members
explicit LatticeLocker (LatticeBase& lattice, LatticeBase::LockType, uInt nattempts = 0)
~LatticeLocker()
Bool hasLock (FileLocker::LockType) const
Private Members
LatticeLocker (const LatticeLocker&)
LatticeLocker& operator= (const LatticeLocker&)

Description

Review Status

Programs:
Tests:

Prerequisite

Synopsis

Class LatticeLocker can be used to acquire a (user) lock on a lattice. The lock can be a read or write lock. The destructor releases the lock when needed.

LatticeLocker simply uses the lock and unlock function of class Lattice. The advantage of LatticeLocker over these functions is that the destructor of LatticeLocker is called automatically by the system, so unlocking the lattice does not need to be done explicitly and cannot be forgotten. Especially in case of exception handling this can be quite an adavantage.

This class is meant to be used with the UserLocking option. It can, however, also be used with the other locking options. In case of PermanentLocking(Wait) it won't do anything at all. In case of AutoLocking it will acquire and release the lock when needed. However, it is possible that the system releases an auto lock before the LatticeLocker destructor is called.

The constructor of LatticeLocker will look if the lattice is already appropriately locked. If so, it will set a flag to prevent the destructor from unlocking the lattice. In this way nested locks can be used. I.e. one can safely use LatticeLocker in a function without having to be afraid that its destructor would undo a lock set in a higher function.
Similarly LatticeLocker will remember if a lattice was already read-locked, when a write-lock is acquired. In such a case the destructor will try to ensure that the lattice remains read-locked.

Example

    // Open a lattice to be updated.
    PagedArray<Float> myLattice (Table ("theLattice",
                                 LatticeLock::UserLocking,
                                 Lattice::Update);
    // Start of some critical section requiring a lock.
    {
        LatticeLocker lock1 (myLattice, FileLocker::Write);
        ... write the data
    }
    // The LatticeLocker destructor invoked by } unlocks the table.
    

Motivation

LatticeLocker makes it easier to unlock a lattice. It also makes it easier to use locking in a nested way.

Member Description

explicit LatticeLocker (LatticeBase& lattice, LatticeBase::LockType, uInt nattempts = 0)

The constructor acquires a read or write lock on a lattice. If the lattice was already locked, the destructor will not unlock the lattice. This means that the class can be used in a nested way.
The number of attempts (default = forever) can be specified when acquiring the lock does not succeed immediately. When nattempts>1, the system waits 1 second between each attempt, so nattempts is more or less equal to a wait period in seconds. An exception is thrown when the lock cannot be acquired.

~LatticeLocker()

If the constructor acquired the lock, the destructor releases the lock and flushes the data if changed.

Bool hasLock (FileLocker::LockType) const

Has this process the read or write lock, thus can the table be read or written safely?

LatticeLocker (const LatticeLocker&)
LatticeLocker& operator= (const LatticeLocker&)

The copy constructor and assignment are not possible. Note that only one lock can be held on a lattice, so copying a TableLocker object imposes great difficulties which object should release the lock. It can be solved by turning LatticeLocker into a handle class with a reference counted body class. However, that will only be done when the need arises.