
com.seeq.utilities.AutoResetEvent Maven / Gradle / Ivy
package com.seeq.utilities;
import java.time.Duration;
/**
* This class is a copy of the C# AutoResetEvent class. The .NET Framework source code is not available, so behavior was
* determined by reading the documentation.
*
* See https://msdn.microsoft.com/en-us/library/system.threading.autoresetevent(v=vs.110).aspx for more info.
*/
public class AutoResetEvent {
private final Object lock = new Object();
private volatile boolean isSignaled = false;
/**
* Initializes a new instance of the AutoResetEvent class with a boolean value indicating whether to set the initial
* state to signaled.
*
* @param initialState
* true to set the initial state to signaled; false to set the initial state to non-signaled.
*/
public AutoResetEvent(boolean initialState) {
this.isSignaled = initialState;
}
/**
* Blocks the current thread until the signal is received.
*
* @return true if the current instance receives a signal. If the current instance is never signaled, waitOne()
* never returns.
* @throws InterruptedException
* thrown if thread is interrupted
*/
public boolean waitOne() throws InterruptedException {
synchronized (this.lock) {
// For a full treatment on why this is a while loop, read
// http://coding.derkeiler.com/Archive/Java/comp.lang.java.programmer/2006-01/msg01130.html
while (!this.isSignaled) {
this.lock.wait();
}
this.isSignaled = false;
return true;
}
}
/**
* Blocks the current thread until the signal is received or the timeout is reached.
*
* @param timeoutMilliseconds
* The number of milliseconds to wait, or -1 to wait indefinitely.
* @return true if the current instance receives a signal; otherwise, false.
* @throws InterruptedException
* thrown if thread is interrupted
*/
public boolean waitOne(long timeoutMilliseconds) throws InterruptedException {
if (timeoutMilliseconds == 0) {
// To match C# behavior, we do not enter a wait state here. In other words, using a zero for the
// timeout means that an InterruptedException will not be thrown.
return this.isSignaled;
}
if (timeoutMilliseconds == -1) {
// -1 means "wait forever" in the C# AutoResetEvent.
return this.waitOne();
}
long t = System.currentTimeMillis();
synchronized (this.lock) {
// For a full treatment on why this is a while loop, read
// http://coding.derkeiler.com/Archive/Java/comp.lang.java.programmer/2006-01/msg01130.html
while (!this.isSignaled) {
this.lock.wait(timeoutMilliseconds);
long elapsed = System.currentTimeMillis() - t;
if (this.isSignaled) {
this.isSignaled = false;
return true;
} else if (elapsed >= timeoutMilliseconds) {
// Note that we have to check if the timeout has actually elapsed, because there are
// "spurious wakeups" that can occur when using Object.wait().
return false;
} else {
timeoutMilliseconds = Math.max(1, timeoutMilliseconds - elapsed);
}
}
this.isSignaled = false;
return true;
}
}
/**
* Blocks the current thread until the signal is received or the timeout is reached.
*
* @param timeout
* The duration to wait.
* @return true if the current instance receives a signal; otherwise, false.
* @throws InterruptedException
* thrown if thread is interrupted
*/
public boolean waitOne(Duration timeout) throws InterruptedException {
return this.waitOne(timeout.toMillis());
}
/**
* Sets the state of the event to signaled, allowing one waiting thread to proceed.
*
* @return true if the operation succeeds; otherwise, false.
*/
public boolean set() {
synchronized (this.lock) {
this.isSignaled = true;
// Note: Important to use notify() instead of notifyAll() to mimic C# behavior.
// http://blog.mikejmcguire.com/2014/12/22/using-the-autoresetevent-class-to-wake-multiple-threads-in-c/
this.lock.notify();
return true;
}
}
/**
* Sets the state of the event to nonsignaled, causing threads to block.
*
* @return true if the operation succeeds; otherwise, false.
*/
public boolean reset() {
synchronized (this.lock) {
this.isSignaled = false;
return true;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy