package edu.berkeley.thebes.common.persistence.util; import com.google.common.collect.Maps; import java.util.Map; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class LockManager { private class LockWaiting { private long numWaiters; private Condition condition; public LockWaiting(Condition condition) { numWaiters = 0; this.condition = condition; } public boolean isEmpty() { return numWaiters == 0; } public void signalWaiter() { assert(numWaiters > 0); condition.signal(); } public void waitInterruptibly() { numWaiters++; condition.awaitUninterruptibly(); numWaiters--; } } public int getSize() { return lockTable.size(); } private Map<String, LockWaiting> lockTable; private Lock tableLock = new ReentrantLock(); public LockManager() { lockTable = Maps.newHashMap(); } public void lock(String key) { tableLock.lock(); if(!lockTable.containsKey(key)) lockTable.put(key, new LockWaiting(tableLock.newCondition())); else lockTable.get(key).waitInterruptibly(); tableLock.unlock(); } public void unlock(String key) { tableLock.lock(); if(lockTable.get(key).isEmpty()) lockTable.remove(key); else lockTable.get(key).signalWaiter(); tableLock.unlock(); } }