package jp.agentec.abook.abv.bl.common;

import java.util.HashMap;
import java.util.Map;

/**
 * ID単位でロックを取得するためのロックオブジェクト取得クラス
 * 
 * @author tsukada
 *
 */
public class MultiLock {

	// 排他制御用マップ
	private final Map<Object, Lock> lockMap = new HashMap<Object, Lock>();

	// このセマフォの名前
	private String name;

	public MultiLock(String name) {
		this.name = name;
	}
	
	public String getName() {
		return name;
	}

	public class Lock {
		Object key;
		int count;

		private Lock(Object key) {
			this.key = key;
		}

		private boolean removable() {
			return count <= 0;
		}
	}

	/**
	 * ロックを取得する
	 * 
	 * @param key
	 * @return
	 */
	public synchronized Lock acquireLock(Object key) {
		Lock lock = lockMap.get(key);
		if (lock == null) {
			lock = new Lock(key);
			lockMap.put(key, lock);
		}
		lock.count++;
		return lock;
	}

	/**
	 * ロックを解放する
	 * 
	 * @param lock
	 */
	public synchronized void releaseLock(Lock lock) {
		if (lock == null) {
			return;
		}
		if (lockMap.containsValue(lock)) {
			lock.count--;
			if (lock.removable()) {
				lockMap.remove(lock.key);
			}
		}
	}
}
