common-utils/src/main/java/org/warp/commonutils/locks/TransitLock.java

54 lines
1.4 KiB
Java
Raw Normal View History

2021-01-22 03:15:14 +01:00
package org.warp.commonutils.locks;
import java.util.concurrent.Semaphore;
2021-01-22 04:22:58 +01:00
import java.util.concurrent.atomic.AtomicInteger;
2021-01-22 03:15:14 +01:00
public class TransitLock {
private final FlexibleCountDownLatch unfinishedTransits = new FlexibleCountDownLatch(0);
private final Semaphore permits = new Semaphore(Integer.MAX_VALUE);
2021-01-22 04:22:58 +01:00
private final AtomicInteger allowedTransits = new AtomicInteger(1);
2021-01-22 03:15:14 +01:00
private final Object synchronization = new Object();
public TransitLock() {
}
public void allowTransit() {
2021-01-22 04:22:58 +01:00
var allowedTransits = this.allowedTransits.incrementAndGet();
if (allowedTransits == 1) {
var permitsToRelease = Math.max(0, Integer.MAX_VALUE - (permits.availablePermits() + 10000));
permits.release(permitsToRelease);
} else if (allowedTransits > 1) {
throw new IllegalStateException("Already allowed transit!");
}
2021-01-22 03:15:14 +01:00
}
public void disallowTransit() {
synchronized (synchronization) {
2021-01-22 04:22:58 +01:00
var allowedTransits = this.allowedTransits.decrementAndGet();
if (allowedTransits == 0) {
unfinishedTransits.await();
permits.drainPermits();
} else if (allowedTransits > 0) {
throw new IllegalStateException("Transits are still allowed for an unknown reason!");
}
2021-01-22 03:15:14 +01:00
}
}
public void transit() {
startTransit();
endTransit();
}
public void startTransit() {
synchronized (synchronization) {
unfinishedTransits.grow();
permits.acquireUninterruptibly();
}
}
public void endTransit() {
unfinishedTransits.countDown();
}
}