Commit f48fd1e1 authored by Pete Matern's avatar Pete Matern Committed by pete

Another pass at LocalLockFactory to store both locks and counts in one map.

git-svn-id: http://svn.igniterealtime.org/svn/repos/openfire/trunk@8332 b35dd754-fafc-0310-a699-88a17e54d16e
parent 5f9af5a8
...@@ -30,8 +30,7 @@ import java.util.concurrent.locks.Condition; ...@@ -30,8 +30,7 @@ import java.util.concurrent.locks.Condition;
*/ */
public class LocalLockFactory implements LockFactory { public class LocalLockFactory implements LockFactory {
private Map<Object, ReentrantLock> locks = new ConcurrentHashMap<Object, ReentrantLock>(); private Map<Object, LockAndCount> locks = new ConcurrentHashMap<Object, LockAndCount>();
private Map<Object, Integer> counts = new ConcurrentHashMap<Object, Integer>();
public Lock getLock(Object key) { public Lock getLock(Object key) {
Object lockKey = key; Object lockKey = key;
...@@ -43,62 +42,48 @@ public class LocalLockFactory implements LockFactory { ...@@ -43,62 +42,48 @@ public class LocalLockFactory implements LockFactory {
} }
private void acquireLock(Object key) { private void acquireLock(Object key) {
ReentrantLock lock; ReentrantLock lock = lookupLockForAcquire(key);
synchronized (key) {
lock = lookupLockForAcquire(key);
}
lock.lock(); lock.lock();
} }
private void releaseLock(Object key) { private void releaseLock(Object key) {
ReentrantLock lock; ReentrantLock lock = lookupLockForRelease(key);
synchronized (key) {
lock = lookupLockForRelease(key);
if (lock.getHoldCount() <= 1 && !counts.containsKey(key)) {
locks.remove(key);
}
}
lock.unlock(); lock.unlock();
} }
private ReentrantLock lookupLockForAcquire(Object key) { private ReentrantLock lookupLockForAcquire(Object key) {
ReentrantLock lock = locks.get(key); synchronized(key) {
if (lock == null) { LockAndCount lac = locks.get(key);
lock = new ReentrantLock(); if (lac == null) {
locks.put(key, lock); lac = new LockAndCount(new ReentrantLock());
} lac.count = 1;
locks.put(key, lac);
Integer count = counts.get(key); }
if (count == null) { else {
counts.put(key, 1); lac.count++;
} }
else {
counts.put(key, ++count); return lac.lock;
} }
}
return lock;
}
private ReentrantLock lookupLockForRelease(Object key) { private ReentrantLock lookupLockForRelease(Object key) {
ReentrantLock lock = locks.get(key); synchronized(key) {
if (lock == null) { LockAndCount lac = locks.get(key);
throw new IllegalStateException("No lock found for object " + key); if (lac == null) {
} throw new IllegalStateException("No lock found for object " + key);
}
Integer count = counts.get(key);
if (count == null) { if (lac.count <= 1) {
throw new IllegalStateException("No count found for object " + key); locks.remove(key);
} }
else {
if (count == 1) { lac.count--;
counts.remove(key); }
}
else { return lac.lock;
counts.put(key, --count); }
} }
return lock;
}
private class LocalLock implements Lock { private class LocalLock implements Lock {
...@@ -133,4 +118,13 @@ public class LocalLockFactory implements LockFactory { ...@@ -133,4 +118,13 @@ public class LocalLockFactory implements LockFactory {
} }
} }
private static class LockAndCount {
final ReentrantLock lock;
int count;
LockAndCount(ReentrantLock lock) {
this.lock = lock;
}
}
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment