All Downloads are FREE. Search and download functionalities are using the official Maven repository.

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