shz.core.lock.ActionAndWait Maven / Gradle / Ivy
package shz.core.lock;
import java.time.Duration;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Supplier;
public final class ActionAndWait {
private final Lock lock;
private final long sleepMillis;
private final Condition waiter;
private final AtomicInteger state;
private volatile boolean running;
public ActionAndWait(Lock lock, long sleepMillis) {
this.lock = lock;
this.sleepMillis = sleepMillis;
waiter = lock.newCondition();
state = new AtomicInteger();
}
public ActionAndWait() {
this(new ReentrantLock(), 0L);
}
public void execute(Supplier action) {
try {
lock.lockInterruptibly();
long waitTime = 0L;
do {
state.set(0);
running = true;
try {
Duration duration = action.get();
waitTime = duration == null ? 0L : duration.toNanos();
} catch (Exception ignored) {
}
} while (!state.compareAndSet(0, 1));
try {
if (waitTime <= 0L) waiter.await();
else waiter.await(waitTime, TimeUnit.NANOSECONDS);
} catch (InterruptedException ignored) {
}
state.set(2);
running = false;
if (sleepMillis > 0L) TimeUnit.MILLISECONDS.sleep(sleepMillis);
} catch (InterruptedException ignored) {
} finally {
lock.unlock();
}
}
public void awaken() {
do {
if (state.get() == 2) break;
if (lock.tryLock()) {
try {
waiter.signal();
} finally {
lock.unlock();
}
break;
}
} while (state.get() == 1 || !state.compareAndSet(0, 2));
}
public boolean isRunning() {
return running;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy