Threads Java

/*
 * Copyright 2005 MBARI
 *
 * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE, Version 2.1 
 * (the "License"); you may not use this file except in compliance 
 * with the License. You may obtain a copy of the License at
 *
 * http://www.gnu.org/copyleft/lesser.html
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
//package org.mbari.util;
//~--- classes ----------------------------------------------------------------
/**
 * 

The BooleanLock class provides a useful encapsulation of a boolean variable
 * that is easily and safely accessed from multiple theads. These threads can
 * test and set an internal value and wait for it to change. The wait/notify
 * mechanism is used internally to support waiting for the value to change, and
 * frees external classes from the error-prone complexity of properly implementing this mechanism.


 *
 *@author     MBARI
 *@version    $Id: BooleanLock.java 332 2006-08-01 18:38:46Z hohonuuli $
 */
public class BooleanLock {
    /**
   * @uml.property  name="value"
   */
    private boolean value;
    //~--- constructors -------------------------------------------------------
    /**
     * Constructor. Assigns the inital value to false.
     */
    public BooleanLock() {
        this(false);
    }
    /**
     * Constructor
     *
     * @param  initialValue  The intial value to assign to the BooleanLock
     */
    public BooleanLock(boolean initialValue) {
        value = initialValue;
    }
    //~--- get methods --------------------------------------------------------
    /**
     * @return    true if the lock value is false
     */
    public synchronized boolean isFalse() {
        return !value;
    }
    /**
     * @return    true if the lock value is true
     */
    public synchronized boolean isTrue() {
        return value;
    }
    //~--- set methods --------------------------------------------------------
    /**
   * Sets the value of this lock. Issues a notifyAll() call if the value is changed. (i.e the new value does not equal the current value.
   * @param  newValue
   * @uml.property  name="value"
   */
    public synchronized void setValue(boolean newValue) {
        if (newValue != value) {
            value = newValue;
            notifyAll();
        }
    }
    //~--- methods ------------------------------------------------------------
    /**
     * Attempts to change the value of the lock to false. This method will wait
     * for the specified duration until attempting the change.
     *
     * @param  msTimeout              The time (in milliseconds) to wait before changing the value to true
     * @return                        True is the change is a success
     * @throws  InterruptedException
     */
    public synchronized boolean waitToSetFalse(long msTimeout)
            throws InterruptedException {
        boolean success = waitUntilTrue(msTimeout);
        if (success) {
            setValue(false);
        }
        return success;
    }
    /**
     * Attempts to change the value of the lock to true. This method will wait
     * for the specified duration until attempting the change.
     *
     * @param  msTimeout              The time (in milliseconds) to wait before changing the value to true
     * @return                        True is the change is a success
     * @throws  InterruptedException
     */
    public synchronized boolean waitToSetTrue(long msTimeout)
            throws InterruptedException {
        boolean success = waitUntilFalse(msTimeout);
        if (success) {
            setValue(true);
        }
        return success;
    }
    /**
     * @param  msTimeout
     * @return
     * @throws  InterruptedException
     */
    public synchronized boolean waitUntilFalse(long msTimeout)
            throws InterruptedException {
        return waitUntilStateIs(false, msTimeout);
    }
    /**
     * @param  state
     * @param  msTimeout
     * @return
     * @throws  InterruptedException
     */
    public synchronized boolean waitUntilStateIs(boolean state, long msTimeout)
            throws InterruptedException {
        if (msTimeout == 0L) {
            while (value != state) {
                wait();
                // wait indefinitely until notified
            }
            // condition has finally been met
            return true;
        }
        // only wait for the specified amount of time
        long endTime = System.currentTimeMillis() + msTimeout;
        long msRemaining = msTimeout;
        while ((value != state) && (msRemaining > 0L)) {
            wait(msRemaining);
            msRemaining = endTime - System.currentTimeMillis();
        }
        // May have timed out, or value may have met value, calculate return
        // value
        return (value == state);
    }
    /**
     * @param  msTimeout
     * @return
     * @throws  InterruptedException
     */
    public synchronized boolean waitUntilTrue(long msTimeout)
            throws InterruptedException {
        return waitUntilStateIs(true, msTimeout);
    }
}