view src/cachingfilter/Locker.java @ 0:7ecd1a4ef557

add content
author Franklin Schmidt <fschmidt@gmail.com>
date Thu, 21 Mar 2019 19:15:52 -0600
parents
children
line wrap: on
line source

package cachingfilter;

import java.util.Map;
import java.util.HashMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;


public final class Locker<T> {

	private static class Tracker {
		final ReentrantLock lock = new ReentrantLock();
		int waiters = 0;
	}

	private final Map<T,Tracker> map = new HashMap<T,Tracker>();

	public void lock(T obj) {
		Tracker t;
		synchronized(map) {
			t = map.get(obj);
			if( t == null ) {
				t = new Tracker();
				map.put(obj,t);
			}
			t.waiters++;
		}
		try {
			t.lock.lock();
		} finally {
			synchronized(map) {
				t.waiters--;
			}
		}
	}

	public boolean unlock(T obj) {
		synchronized(map) {
			Tracker t = map.get(obj);
			if( t == null || !t.lock.isHeldByCurrentThread() )
				return false;
			t.lock.unlock();
			if( t.waiters==0 ) {
				map.remove(obj);
			}
			return true;
		}
	}

}