Skip to content

Instantly share code, notes, and snippets.

@guidomedina
Created February 12, 2020 17:06
Show Gist options
  • Save guidomedina/83737faf213c8e321756975deff077dd to your computer and use it in GitHub Desktop.
Save guidomedina/83737faf213c8e321756975deff077dd to your computer and use it in GitHub Desktop.
Countdown latch with increment and decrement functionality
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
public class CountingLatch
{
/**
* Synchronization control for CountingLatch.
* Uses AQS state to represent count.
*/
private static final class Sync extends AbstractQueuedSynchronizer
{
private Sync()
{
}
private Sync(final int initialState)
{
setState(initialState);
}
int getCount()
{
return getState();
}
protected int tryAcquireShared(final int acquires)
{
return getState() == 0 ? 1 : -1;
}
protected boolean tryReleaseShared(final int delta)
{
// Decrement count; signal when transition to zero
for (; ; ) {
final int c = getState();
final int nextc = c + delta;
if (nextc < 0) {
return false;
}
if (compareAndSetState(c, nextc)) {
return nextc == 0;
}
}
}
}
private final Sync sync;
public CountingLatch()
{
sync = new Sync();
}
@SuppressWarnings("UnusedDeclaration")
public CountingLatch(final int initialCount)
{
sync = new Sync(initialCount);
}
public void increment()
{
sync.releaseShared(1);
}
public int getCount()
{
return sync.getCount();
}
public void decrement()
{
sync.releaseShared(-1);
}
public void await() throws InterruptedException
{
sync.acquireSharedInterruptibly(1);
}
public boolean await(final long timeout) throws InterruptedException
{
return sync.tryAcquireSharedNanos(1, TimeUnit.MILLISECONDS.toNanos(timeout));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment