package com.tandbergtv.watchpoint.pmm.util.lock;

import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

import org.apache.log4j.Logger;

/**
 * This singleton implementation of ILockService holds one lock per object.
 * Only one thread can hold lock on the object.
 * The lock has to be released to be acquired agian.
 * The lock is not on a particular instance. If an object is locked, any other object
 *  that is equal to the locked object will be considered as locked.
 *  
 * @author Raj Prakash
 */
public class LockService implements ILockService {

	private static final Logger logger = Logger.getLogger(LockService.class);
	private static final LockService _instance = new LockService();
	
	private Set<Object> holders;
	
	private LockService() {
		holders = Collections.synchronizedSet(new HashSet<Object>());
	}
	
	/**
	 * Gets the singleton instance of this class.
	 */
	public static final LockService getInstance() {
		return _instance;
	}
	
	/* (non-Javadoc)
	 * @see com.tandbergtv.watchpoint.pmm.util.lock.ILockService#lock(java.lang.Object)
	 */
	public boolean lock(Object holder) {
		boolean lockAcquired = holders.add(holder);
		if(lockAcquired)
			logger.debug("Locked on: " + holder);
		else
			logger.debug("Unable to lock on: " + holder);
		return lockAcquired;
	}

	/* (non-Javadoc)
	 * @see com.tandbergtv.watchpoint.pmm.util.lock.ILockService#unlock(java.lang.Object)
	 */
	public boolean unlock(Object holder) {
		boolean lockReleased = holders.remove(holder);
		if(lockReleased)
			logger.debug("Lock released on: " + holder);
		else
			logger.debug("No lock found on: " + holder + " to release.");
		return lockReleased;
	}
}
