Author: manik.surtani(a)jboss.com
Date: 2009-03-19 06:06:23 -0400 (Thu, 19 Mar 2009)
New Revision: 7921
Modified:
core/branches/flat/src/main/java/org/horizon/util/concurrent/locks/containers/AbstractPerEntryLockContainer.java
Log:
HORIZON-40 - Create a lock-per-entry lock manager
Modified:
core/branches/flat/src/main/java/org/horizon/util/concurrent/locks/containers/AbstractPerEntryLockContainer.java
===================================================================
---
core/branches/flat/src/main/java/org/horizon/util/concurrent/locks/containers/AbstractPerEntryLockContainer.java 2009-03-19
09:59:50 UTC (rev 7920)
+++
core/branches/flat/src/main/java/org/horizon/util/concurrent/locks/containers/AbstractPerEntryLockContainer.java 2009-03-19
10:06:23 UTC (rev 7921)
@@ -17,11 +17,14 @@
protected abstract Lock newLock();
- public Lock getLock(Object key) {
- Lock l = newLock();
- Lock tmp = locks.putIfAbsent(key, l);
- if (tmp != null) l = tmp;
- return l;
+ public final Lock getLock(Object key) {
+ // this is an optimisation. It is not foolproof as we may still be creating new
locks unnecessarily (thrown away
+ // when we do a putIfAbsent) but it minimises the chances somewhat, for the cost of
an extra CHM get.
+ Lock lock = locks.get(key);
+ if (lock == null) lock = newLock();
+ Lock existingLock = locks.putIfAbsent(key, lock);
+ if (existingLock != null) lock = existingLock;
+ return lock;
}
public int getNumLocksHeld() {
@@ -33,13 +36,23 @@
}
public boolean acquireLock(Object key, long timeout, TimeUnit unit) throws
InterruptedException {
- Lock l = getLock(key);
- boolean success = l.tryLock(timeout, unit);
- if (l != locks.get(key)) {
- l.unlock();
- success = acquireLock(key, timeout, unit); // todo avoid recursion here, this
could get ugly!
+ while (true) {
+ Lock lock = getLock(key);
+ if (lock.tryLock(timeout, unit)) {
+ // lock acquired. Now check if it is the *correct* lock!
+ Lock existingLock = locks.putIfAbsent(key, lock);
+ if (existingLock != null && existingLock != lock) {
+ // we have the wrong lock! Unlock and retry.
+ lock.unlock();
+ } else {
+ // we got the right lock.
+ return true;
+ }
+ } else {
+ // we couldn't acquire the lock within the timeout period
+ return false;
+ }
}
- return success;
}
public void releaseLock(Object key) {