org.apache.commons.transaction.locking
Class GenericLock

java.lang.Object
  extended by org.apache.commons.transaction.locking.GenericLock
All Implemented Interfaces:
MultiLevelLock, MultiLevelLock2
Direct Known Subclasses:
ReadWriteLock, ReadWriteUpgradeLock

public class GenericLock
extends java.lang.Object
implements MultiLevelLock2

A generic implementaion of a simple multi level lock.

The idea is to have an ascending number of lock levels ranging from 0 to maxLockLevel as specified in GenericLock(Object, int, LoggerFacade): the higher the lock level the stronger and more restrictive the lock. To determine which lock may coexist with other locks you have to imagine matching pairs of lock levels. For each pair both parts allow for all lock levels less than or equal to the matching other part. Pairs are composed by the lowest and highest level not yet part of a pair and successively applying this method until no lock level is left. For an even amount of levels each level is part of exactly one pair. For an odd amount the middle level is paired with itself. The highst lock level may coexist with the lowest one (0) which by definition means NO LOCK. This implies that you will have to specify at least one other lock level and thus set maxLockLevel to at least 1.

Although this may sound complicated, in practice this is quite simple. Let us imagine you have three lock levels:

Accordingly, you will have to set maxLockLevel to 2. Now, there are two pairs of levels This means when the current highest lock level is NO LOCK everything less or equal to EXCLUSIVE is allowed - which means every other lock level. On the other side EXCLUSIVE allows exacly for NO LOCK- which means nothing else. In conclusion, SHARED allows for SHARED or NO LOCK, but not for EXCLUSIVE. To make this very clear have a look at this table, where o means compatible or can coexist and x means incompatible or can not coexist:

NO LOCK SHARED EXCLUSIVE
NO LOCK o o o
SHARED o o x
EXCLUSIVE o x x

Additionally, there are preferences for specific locks you can pass to acquire(Object, int, boolean, int, boolean, long). This means whenever more thanone party waits for a lock you can specify which one is to be preferred. This gives you every freedom you might need to specifcy e.g.

Version:
$Revision$

Nested Class Summary
protected static class GenericLock.LockOwner
           
 
Field Summary
protected  LoggerFacade logger
           
protected  java.util.Map owners
           
protected  java.lang.Object resourceId
           
protected  int waiters
           
protected  java.util.List waitingOwners
           
 
Fields inherited from interface org.apache.commons.transaction.locking.MultiLevelLock2
COMPATIBILITY_NONE, COMPATIBILITY_REENTRANT, COMPATIBILITY_REENTRANT_AND_SUPPORT, COMPATIBILITY_SUPPORT
 
Constructor Summary
GenericLock(java.lang.Object resourceId, int maxLockLevel, LoggerFacade logger)
          Creates a new lock.
 
Method Summary
 boolean acquire(java.lang.Object ownerId, int targetLockLevel, boolean wait, boolean reentrant, long timeoutMSecs)
          Tries to acquire a certain lock level on this lock.
 boolean acquire(java.lang.Object ownerId, int targetLockLevel, boolean wait, int compatibility, boolean preferred, long timeoutMSecs)
          Tries to acquire a certain lock level on this lock.
 boolean acquire(java.lang.Object ownerId, int targetLockLevel, boolean wait, int compatibility, long timeoutMSecs)
           
 boolean acquire(java.lang.Object ownerId, int targetLockLevel, boolean preferred, long timeoutMSecs)
          Tries to blockingly acquire a lock which can be preferred.
 boolean equals(java.lang.Object o)
           
protected  java.util.Set getConflictingOwners(GenericLock.LockOwner myOwner, java.util.Collection ownersToTest)
           
protected  java.util.Set getConflictingOwners(java.lang.Object ownerId, int targetLockLevel, int compatibility)
           
protected  java.util.Collection getConflictingWaiters(java.lang.Object ownerId)
           
 int getLevelMaxLock()
          Gets the highst lock level possible.
 int getLevelMinLock()
          Gets the lowest lock level possible.
 int getLockLevel(java.lang.Object ownerId)
          Retuns the highest lock level the specified owner holds on this lock or 0 if it holds no locks at all.
protected  GenericLock.LockOwner getMaxLevelOwner()
           
protected  GenericLock.LockOwner getMaxLevelOwner(GenericLock.LockOwner reentrantOwner, boolean preferred)
           
protected  GenericLock.LockOwner getMaxLevelOwner(GenericLock.LockOwner reentrantOwner, int supportLockLevel, boolean preferred)
           
protected  GenericLock.LockOwner getMaxLevelOwner(int supportLockLevel, boolean preferred)
           
 java.lang.Object getOwner()
           
 java.lang.Object getResourceId()
          Gets the resource assotiated to this lock.
 boolean has(java.lang.Object ownerId, int lockLevel)
          Tests if a certain lock level is owned by an owner.
 int hashCode()
           
protected  boolean isCompatible(int targetLockLevel, int currentLockLevel)
           
protected  void registerWaiter(GenericLock.LockOwner waitingOwner)
           
 boolean release(java.lang.Object ownerId)
          Releases any lock levels the specified owner may hold on this lock.
protected  void setLockLevel(java.lang.Object ownerId, GenericLock.LockOwner lock, int targetLockLevel, int compatibility, boolean intention)
           
 boolean test(java.lang.Object ownerId, int targetLockLevel, int compatibility)
          Tests if a certain lock level could be acquired.
 java.lang.String toString()
           
protected  boolean tryLock(java.lang.Object ownerId, int targetLockLevel, int compatibility, boolean preferred)
           
protected  boolean tryLock(java.lang.Object ownerId, int targetLockLevel, int compatibility, boolean preferred, boolean tryOnly)
           
protected  void unregisterWaiter(GenericLock.LockOwner waitingOwner)
           
 
Methods inherited from class java.lang.Object
clone, finalize, getClass, notify, notifyAll, wait, wait, wait
 

Field Detail

resourceId

protected java.lang.Object resourceId

owners

protected java.util.Map owners

waitingOwners

protected java.util.List waitingOwners

logger

protected LoggerFacade logger

waiters

protected int waiters
Constructor Detail

GenericLock

public GenericLock(java.lang.Object resourceId,
                   int maxLockLevel,
                   LoggerFacade logger)
Creates a new lock.

Parameters:
resourceId - identifier for the resource associated to this lock
maxLockLevel - highest allowed lock level as described in class intro
logger - generic logger used for all kind of debug logging
Method Detail

equals

public boolean equals(java.lang.Object o)
Overrides:
equals in class java.lang.Object

hashCode

public int hashCode()
Overrides:
hashCode in class java.lang.Object

test

public boolean test(java.lang.Object ownerId,
                    int targetLockLevel,
                    int compatibility)
Description copied from interface: MultiLevelLock2
Tests if a certain lock level could be acquired. This method tests only and does not actually acquire the lock.

Specified by:
test in interface MultiLevelLock2
Parameters:
ownerId - a unique id identifying the entity that wants to test a certain lock level on this lock
targetLockLevel - the lock level to acquire
compatibility - MultiLevelLock2.COMPATIBILITY_NONEif no additional compatibility is desired (same as reentrant set to false) , MultiLevelLock2.COMPATIBILITY_REENTRANTif lock level by the same owner shall not affect compatibility (same as reentrant set to true), or MultiLevelLock2.COMPATIBILITY_SUPPORTif lock levels that are the same as the desired shall not affect compatibility, or finally MultiLevelLock2.COMPATIBILITY_REENTRANT_AND_SUPPORTwhich is a combination of reentrant and support
Returns:
true if the lock could be acquired at the time this method was called
See Also:
MultiLevelLock2.test(Object, int, int)

has

public boolean has(java.lang.Object ownerId,
                   int lockLevel)
Description copied from interface: MultiLevelLock2
Tests if a certain lock level is owned by an owner.

Specified by:
has in interface MultiLevelLock2
Parameters:
ownerId - a unique id identifying the entity that wants to check a certain lock level on this lock
lockLevel - the lock level to test
Returns:
true if the lock could be acquired at the time this method was called
See Also:
MultiLevelLock2.has(Object, int)

acquire

public boolean acquire(java.lang.Object ownerId,
                       int targetLockLevel,
                       boolean wait,
                       boolean reentrant,
                       long timeoutMSecs)
                throws java.lang.InterruptedException
Description copied from interface: MultiLevelLock
Tries to acquire a certain lock level on this lock.

Specified by:
acquire in interface MultiLevelLock
Parameters:
ownerId - a unique id identifying the entity that wants to acquire a certain lock level on this lock
targetLockLevel - the lock level to acquire
wait - true if this method shall block when the desired lock level can not be acquired
reentrant - true if lock levels of the same entity acquired earlier should not restrict compatibility with the lock level desired now
timeoutMSecs - if blocking is enabled by the wait parameter this specifies the maximum wait time in milliseconds
Returns:
true if the lock actually was acquired
Throws:
java.lang.InterruptedException - when the thread waiting on this method is interrupted
See Also:
MultiLevelLock.acquire(java.lang.Object, int, boolean, boolean, long)

acquire

public boolean acquire(java.lang.Object ownerId,
                       int targetLockLevel,
                       boolean wait,
                       int compatibility,
                       long timeoutMSecs)
                throws java.lang.InterruptedException
Throws:
java.lang.InterruptedException
See Also:
acquire(Object, int, boolean, int, boolean, long)

acquire

public boolean acquire(java.lang.Object ownerId,
                       int targetLockLevel,
                       boolean preferred,
                       long timeoutMSecs)
                throws java.lang.InterruptedException
Tries to blockingly acquire a lock which can be preferred.

Throws:
java.lang.InterruptedException
Since:
1.1
See Also:
acquire(Object, int, boolean, int, boolean, long)

acquire

public boolean acquire(java.lang.Object ownerId,
                       int targetLockLevel,
                       boolean wait,
                       int compatibility,
                       boolean preferred,
                       long timeoutMSecs)
                throws java.lang.InterruptedException
Description copied from interface: MultiLevelLock2
Tries to acquire a certain lock level on this lock. Does the same as MultiLevelLock.acquire(java.lang.Object, int, boolean, boolean, long) except that it allows for different compatibility settings. There is an additional compatibility mode MultiLevelLock2.COMPATIBILITY_SUPPORTthat allows equal lock levels not to interfere with each other. This is like an additional shared compatibility and useful when you only want to make sure not to interfer with lowe levels, but are fine with the same.

Specified by:
acquire in interface MultiLevelLock2
Parameters:
ownerId - a unique id identifying the entity that wants to acquire a certain lock level on this lock
targetLockLevel - the lock level to acquire
wait - true if this method shall block when the desired lock level can not be acquired
compatibility - MultiLevelLock2.COMPATIBILITY_NONEif no additional compatibility is desired (same as reentrant set to false) , MultiLevelLock2.COMPATIBILITY_REENTRANTif lock level by the same owner shall not affect compatibility (same as reentrant set to true), or MultiLevelLock2.COMPATIBILITY_SUPPORTif lock levels that are the same as the desired shall not affect compatibility, or finally MultiLevelLock2.COMPATIBILITY_REENTRANT_AND_SUPPORTwhich is a combination of reentrant and support
preferred - in case this lock request is incompatible with existing ones and we wait, it shall be granted before other waiting requests that are not preferred
timeoutMSecs - if blocking is enabled by the wait parameter this specifies the maximum wait time in milliseconds
Returns:
true if the lock actually was acquired
Throws:
java.lang.InterruptedException - when the thread waiting on this method is interrupted
Since:
1.1
See Also:
MultiLevelLock2.acquire(Object, int, boolean, int, boolean, long)

registerWaiter

protected void registerWaiter(GenericLock.LockOwner waitingOwner)

unregisterWaiter

protected void unregisterWaiter(GenericLock.LockOwner waitingOwner)

release

public boolean release(java.lang.Object ownerId)
Description copied from interface: MultiLevelLock
Releases any lock levels the specified owner may hold on this lock.

Specified by:
release in interface MultiLevelLock
Parameters:
ownerId - a unique id identifying the entity that wants to release all lock levels
Returns:
true if the lock actually was released, false in case there was no lock held by the owner
See Also:
MultiLevelLock.release(Object)

getLockLevel

public int getLockLevel(java.lang.Object ownerId)
Description copied from interface: MultiLevelLock
Retuns the highest lock level the specified owner holds on this lock or 0 if it holds no locks at all.

Specified by:
getLockLevel in interface MultiLevelLock
Parameters:
ownerId - a unique id identifying the entity that wants to know its highest lock level
Returns:
the highest lock level
See Also:
MultiLevelLock.getLockLevel(Object)

getResourceId

public java.lang.Object getResourceId()
Gets the resource assotiated to this lock.

Returns:
identifier for the resource associated to this lock

getLevelMinLock

public int getLevelMinLock()
Gets the lowest lock level possible.

Returns:
minimum lock level

getLevelMaxLock

public int getLevelMaxLock()
Gets the highst lock level possible.

Returns:
maximum lock level

getOwner

public java.lang.Object getOwner()

toString

public java.lang.String toString()
Overrides:
toString in class java.lang.Object

getMaxLevelOwner

protected GenericLock.LockOwner getMaxLevelOwner()

getMaxLevelOwner

protected GenericLock.LockOwner getMaxLevelOwner(GenericLock.LockOwner reentrantOwner,
                                                 boolean preferred)

getMaxLevelOwner

protected GenericLock.LockOwner getMaxLevelOwner(int supportLockLevel,
                                                 boolean preferred)

getMaxLevelOwner

protected GenericLock.LockOwner getMaxLevelOwner(GenericLock.LockOwner reentrantOwner,
                                                 int supportLockLevel,
                                                 boolean preferred)

setLockLevel

protected void setLockLevel(java.lang.Object ownerId,
                            GenericLock.LockOwner lock,
                            int targetLockLevel,
                            int compatibility,
                            boolean intention)

tryLock

protected boolean tryLock(java.lang.Object ownerId,
                          int targetLockLevel,
                          int compatibility,
                          boolean preferred)

tryLock

protected boolean tryLock(java.lang.Object ownerId,
                          int targetLockLevel,
                          int compatibility,
                          boolean preferred,
                          boolean tryOnly)

isCompatible

protected boolean isCompatible(int targetLockLevel,
                               int currentLockLevel)

getConflictingOwners

protected java.util.Set getConflictingOwners(java.lang.Object ownerId,
                                             int targetLockLevel,
                                             int compatibility)

getConflictingWaiters

protected java.util.Collection getConflictingWaiters(java.lang.Object ownerId)

getConflictingOwners

protected java.util.Set getConflictingOwners(GenericLock.LockOwner myOwner,
                                             java.util.Collection ownersToTest)


Copyright ? 2004 The Apache Software Foundation. All Rights Reserved.