/***************************************************************************
* Copyright (c) 2014 VMware, Inc. All Rights Reserved.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
***************************************************************************/
package com.vmware.bdd.service.event;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.locks.ReentrantLock;
/**
* Author: Xiaoding Bian
* Date: 1/2/14
* Time: 11:22 AM
*/
public class KeyedReentrantLock<K> {
private ConcurrentMap<K, ReentrantLock> lockMap;
private boolean fairSchedule;
public KeyedReentrantLock() {
this(false);
}
public KeyedReentrantLock(boolean fairSchedule) {
lockMap = new ConcurrentHashMap<K, ReentrantLock>();
this.fairSchedule = fairSchedule;
}
/**
* blocking if lock is held by another thread
* @param key
*/
public void lock(K key) {
getLockInstance(key).lock();
}
/**
* unblocking lock request
* @param key
* @return
*/
public boolean tryLock(K key) {
return getLockInstance(key).tryLock();
}
/**
* unlock TODO: throw exception if does not contain this key
* @param key
*/
public void unlock(K key) {
getLockInstance(key).unlock();
}
/**
* check if locked
* @param key
* @return
*/
public boolean isLocked(K key) {
return getLockInstance(key).isLocked();
}
public boolean isHeldByCurrentThread(K key) {
return getLockInstance(key).isHeldByCurrentThread();
}
private ReentrantLock getLockInstance(K key) {
if (!lockMap.containsKey(key)) {
ReentrantLock lock = new ReentrantLock(fairSchedule);
lockMap.putIfAbsent(key, lock);
}
return lockMap.get(key);
}
/**
* inspect this instance, not an atomic info
* @return
*/
@Override
public String toString() {
StringBuffer stringBuffer = new StringBuffer();
for (K key : lockMap.keySet()) {
stringBuffer.append(" key: " + key.toString() + ", locked: " + getLockInstance(key).isLocked()
+ ", isHeldedByCurrentThread: " + getLockInstance(key).isHeldByCurrentThread()
+ ", queueLength: " + getLockInstance(key).getQueueLength() + "\n");
}
return stringBuffer.toString();
}
//TODO: whenever a lock is initialized, it will never been destroyed, add an cleanup method to free memory
}