package org.zenoss.zep.utils;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class AtomicThresholdCounter
{
private long value;
private final ReentrantLock lock = new ReentrantLock();
private final Condition incremented = lock.newCondition();
public AtomicThresholdCounter(int initialValue) {
this.value = initialValue;
}
public void increment() {
increment(1);
}
public void increment(int value) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
this.value += value;
incremented.signalAll();
} finally { lock.unlock(); }
}
public void incrementTo(int value) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
if (this.value < value) {
this.value = value;
incremented.signalAll();
}
} finally { lock.unlock(); }
}
public boolean awaitAndDecrement(int value, long timeout, TimeUnit unit)
throws InterruptedException {
long nanoseconds = unit.toNanos(timeout);
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
while (this.value < value && nanoseconds > 0) {
nanoseconds = incremented.awaitNanos(nanoseconds);
}
if (this.value >= value) {
this.value -= value;
return true;
}
} finally { lock.unlock(); }
return false;
}
public boolean awaitAndReset(int value, long timeout, TimeUnit unit)
throws InterruptedException {
long nanoseconds = unit.toNanos(timeout);
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
while (this.value < value && nanoseconds > 0) {
nanoseconds = incremented.awaitNanos(nanoseconds);
}
if (this.value >= value) {
this.value = 0;
return true;
}
} finally { lock.unlock(); }
return false;
}
}