package org.smartly.commons.mutex;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
/**
* Main mutex dispenser.
* Mutex are objects you can synchronize using "synchronize" keyword.
* <code>synchronize(mymutex){... code ...}</code>
* <p/>
* To retrieve a mutex object call get().
*/
public class MutexPool {
private static final long TIMEOUT = 30 * 1000;
private final Map<Object, Mutex> _pool;
private MutexGarbageCollector _gc;
public MutexPool() {
_pool = Collections.synchronizedMap(new HashMap<Object, Mutex>());
_gc = new MutexGarbageCollector(this);
_gc.start();
}
@Override
protected void finalize() throws Throwable {
try {
this.close();
} catch (Throwable ignored) {
} finally {
super.finalize();
}
}
public void close() {
synchronized (_pool) {
_pool.clear();
if (null != _gc) {
_gc.interrupt();
_gc = null;
}
}
}
public Mutex get(final Object key) {
synchronized (_pool) {
if (null != _gc) {
if (!_pool.containsKey(key)) {
_pool.put(key, new Mutex(TIMEOUT));
}
return _pool.get(key).wakeUp();
} else {
// never null
return new Mutex(TIMEOUT);
}
}
}
// ------------------------------------------------------------------------
// p r i v a t e
// ------------------------------------------------------------------------
// ------------------------------------------------------------------------
// S T A T I C
// ------------------------------------------------------------------------
private static class MutexGarbageCollector extends Thread {
private final MutexPool _mutexPool;
public MutexGarbageCollector(final MutexPool pool) {
_mutexPool = pool;
super.setPriority(Thread.NORM_PRIORITY);
super.setDaemon(true);
}
@Override
public void run() {
try {
while (!super.isInterrupted()) {
Thread.sleep(TIMEOUT);
this.garbage();
}
} catch (InterruptedException ignored) {
}
}
// ------------------------------------------------------------------------
// p r i v a t e
// ------------------------------------------------------------------------
private void garbage() {
synchronized (_mutexPool._pool) {
final Iterator<Object> i = _mutexPool._pool.keySet().iterator();
while (i.hasNext()) {
final Object key = i.next();
final Mutex mutex = _mutexPool._pool.get(key);
if (mutex.isExpired()) {
i.remove();
// System.out.println("removed: " + mutex);
}
}
}
}
}
}