package tc.oc.commons.core.concurrent;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import javax.inject.Inject;
import javax.inject.Provider;
import tc.oc.commons.core.util.CheckedCloseable;
public class LockMap<K, L extends Lock> {
private final ConcurrentMap<K, L> locks = new ConcurrentHashMap<>();
private final Provider<L> lockProvider;
private final boolean reuseLocks;
@Inject public LockMap(Provider<L> lockProvider, boolean reuseLocks) {
this.lockProvider = lockProvider;
this.reuseLocks = reuseLocks;
}
public CheckedCloseable lock(K key) {
final L lock = locks.computeIfAbsent(key, k -> lockProvider.get());
lock.lock();
return () -> {
if(!reuseLocks) locks.remove(key);
lock.unlock();
};
}
public static <K> LockMap<K, ReentrantLock> newReentrantLockMap(boolean reuseLocks) {
return new LockMap<>(ReentrantLock::new, reuseLocks);
}
}