1.2.5. The concurrency controller

The concurrency controller is implemented by the class LockManager which provides sensible default behaviour while allowing the programmer to override it if deemed necessary by the particular semantics of the class being programmed. As with StateManager and persistence, concurrency control implementations are accessed through interfaces. As well as providing access to remote services, the current implementations of concurrency control available to interfaces include:
  • local disk/database implementation, where locks are made persistent by being written to the local file system or database.
  • a purely local implementation, where locks are maintained within the memory of the virtual machine which created them; this implementation has better performance than when writing locks to the local disk, but objects cannot be shared between virtual machines. Importantly, it is a basic Java object with no requirements which can be affected by the SecurityManager
The primary programmer interface to the concurrency controller is via the setlock operation. By default, the runtime system enforces strict two-phase locking following a multiple reader, single writer policy on a per object basis. However, as shown in figure 1, by inheriting from the Lock class it is possible for programmers to provide their own lock implementations with different lock conflict rules to enable type specific concurrency control.
Lock acquisition is (of necessity) under programmer control, since just as StateManager cannot determine if an operation modifies an object, LockManager cannot determine if an operation requires a read or write lock. Lock release, however, is under control of the system and requires no further intervention by the programmer. This ensures that the two-phase property can be correctly maintained.
public abstract class LockManager extends StateManager
{
    public LockResult setlock (Lock toSet, int retry, int timeout);
};
The LockManager class is primarily responsible for managing requests to set a lock on an object or to release a lock as appropriate. However, since it is derived from StateManager, it can also control when some of the inherited facilities are invoked. For example, LockManager assumes that the setting of a write lock implies that the invoking operation must be about to modify the object. This may in turn cause recovery information to be saved if the object is recoverable. In a similar fashion, successful lock acquisition causes activate to be invoked.
The code below shows how we may try to obtain a write lock on an object:
public class Example extends LockManager
{
public boolean foobar ()
{
    AtomicAction A = new AtomicAction;
    boolean result = false;
        
    A.begin();
        
    if (setlock(new Lock(LockMode.WRITE), 0) == Lock.GRANTED)
    {
        /*
        * Do some work, and TXOJ will
        * guarantee ACID properties.
        */
        
        // automatically aborts if fails
        
        if (A.commit() == AtomicAction.COMMITTED)
        {
            result = true;
        }
    }
    else
        A.rollback();
            
    return result;
}
}