| /******************************************************************************* |
| * Copyright (c) 2009, 2015 Oracle. All rights reserved. |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License 2.0, which accompanies this distribution |
| * and is available at https://www.eclipse.org/legal/epl-2.0/. |
| * |
| * Contributors: |
| * Oracle - initial API and implementation |
| ******************************************************************************/ |
| package org.eclipse.jpt.common.utility.internal.reference; |
| |
| import java.io.Serializable; |
| import org.eclipse.jpt.common.utility.command.Command; |
| import org.eclipse.jpt.common.utility.internal.BitTools; |
| import org.eclipse.jpt.common.utility.internal.predicate.int_.IntPredicateTools; |
| import org.eclipse.jpt.common.utility.predicate.IntPredicate; |
| import org.eclipse.jpt.common.utility.reference.IntReference; |
| import org.eclipse.jpt.common.utility.reference.ModifiableIntReference; |
| |
| /** |
| * This class provides synchronized access to an <code>int</code>. |
| * It also provides protocol for suspending a thread until the |
| * value is set to a specified value, with optional time-outs. |
| * |
| * @see SimpleIntReference |
| */ |
| public class SynchronizedInt |
| implements ModifiableIntReference, Cloneable, Serializable |
| { |
| /** Backing <code>int</code>. */ |
| private int value; |
| |
| /** Object to synchronize on. */ |
| private final Object mutex; |
| |
| private static final long serialVersionUID = 1L; |
| |
| |
| // ********** constructors ********** |
| |
| /** |
| * Create a synchronized integer with the specified initial value |
| * and mutex. |
| */ |
| public SynchronizedInt(int value, Object mutex) { |
| super(); |
| this.value = value; |
| this.mutex = mutex; |
| } |
| |
| /** |
| * Create a synchronized integer with the specified initial value. |
| * The synchronized integer itself will be the mutex. |
| */ |
| public SynchronizedInt(int value) { |
| super(); |
| this.value = value; |
| this.mutex = this; |
| } |
| |
| /** |
| * Create a synchronized integer with an initial value of zero |
| * and the specified mutex. |
| */ |
| public SynchronizedInt(Object mutex) { |
| this(0, mutex); |
| } |
| |
| /** |
| * Create a synchronized object with an initial value of zero. |
| * The synchronized integer itself will be the mutex. |
| */ |
| public SynchronizedInt() { |
| this(0); |
| } |
| |
| |
| // ********** IntReference ********** |
| |
| public int getValue() { |
| synchronized (this.mutex) { |
| return this.value; |
| } |
| } |
| |
| public boolean equals(int i) { |
| synchronized (this.mutex) { |
| return this.value == i; |
| } |
| } |
| |
| public boolean notEqual(int i) { |
| synchronized (this.mutex) { |
| return this.value != i; |
| } |
| } |
| |
| public boolean isZero() { |
| synchronized (this.mutex) { |
| return this.value == 0; |
| } |
| } |
| |
| public boolean isNotZero() { |
| synchronized (this.mutex) { |
| return this.value != 0; |
| } |
| } |
| |
| public boolean isGreaterThan(int i) { |
| synchronized (this.mutex) { |
| return this.value > i; |
| } |
| } |
| |
| public boolean isGreaterThanOrEqual(int i) { |
| synchronized (this.mutex) { |
| return this.value >= i; |
| } |
| } |
| |
| public boolean isLessThan(int i) { |
| synchronized (this.mutex) { |
| return this.value < i; |
| } |
| } |
| |
| public boolean isLessThanOrEqual(int i) { |
| synchronized (this.mutex) { |
| return this.value <= i; |
| } |
| } |
| |
| public boolean isPositive() { |
| return this.isGreaterThan(0); |
| } |
| |
| public boolean isNotPositive() { |
| return this.isLessThanOrEqual(0); |
| } |
| |
| public boolean isNegative() { |
| return this.isLessThan(0); |
| } |
| |
| public boolean isNotNegative() { |
| return this.isGreaterThanOrEqual(0); |
| } |
| |
| public boolean isMemberOf(IntPredicate predicate) { |
| synchronized (this.mutex) { |
| return predicate.evaluate(this.value); |
| } |
| } |
| |
| public boolean isNotMemberOf(IntPredicate predicate) { |
| synchronized (this.mutex) { |
| return ! predicate.evaluate(this.value); |
| } |
| } |
| |
| |
| // ********** ModifiableIntReference ********** |
| |
| /** |
| * If the value changes, all waiting threads are notified. |
| */ |
| public int setValue(int value) { |
| synchronized (this.mutex) { |
| return this.setValue_(value); |
| } |
| } |
| |
| /** |
| * Pre-condition: synchronized |
| */ |
| private int setValue_(int v) { |
| int old = this.value; |
| return (old == v) ? old : this.setValue_(v, old); |
| } |
| |
| /** |
| * Pre-condition: synchronized and new value is different |
| */ |
| private int setChangedValue_(int v) { |
| return this.setValue_(v, this.value); |
| } |
| |
| /** |
| * Pre-condition: synchronized and new value is different |
| */ |
| private int setValue_(int v, int old) { |
| this.value = v; |
| this.mutex.notifyAll(); |
| return old; |
| } |
| |
| public int setZero() { |
| return this.setValue(0); |
| } |
| |
| public int increment() { |
| synchronized (this.mutex) { |
| this.value++; |
| this.mutex.notifyAll(); |
| return this.value; |
| } |
| } |
| |
| public int incrementExact() { |
| synchronized (this.mutex) { |
| this.value = Math.incrementExact(this.value); |
| this.mutex.notifyAll(); |
| return this.value; |
| } |
| } |
| |
| public int decrement() { |
| synchronized (this.mutex) { |
| this.value--; |
| this.mutex.notifyAll(); |
| return this.value; |
| } |
| } |
| |
| public int decrementExact() { |
| synchronized (this.mutex) { |
| this.value = Math.decrementExact(this.value); |
| this.mutex.notifyAll(); |
| return this.value; |
| } |
| } |
| |
| public int halve() { |
| synchronized (this.mutex) { |
| return this.halve_(); |
| } |
| } |
| |
| /** |
| * Pre-condition: synchronized |
| */ |
| private int halve_() { |
| int old = this.value; |
| this.value = BitTools.half(old); |
| if (this.value != old) { |
| this.mutex.notifyAll(); |
| } |
| return this.value; |
| } |
| |
| public int twice() { |
| synchronized (this.mutex) { |
| return this.twice_(); |
| } |
| } |
| |
| /** |
| * Pre-condition: synchronized |
| */ |
| private int twice_() { |
| int old = this.value; |
| this.value = BitTools.twice(old); |
| if (this.value != old) { |
| this.mutex.notifyAll(); |
| } |
| return this.value; |
| } |
| |
| public int twiceExact() { |
| synchronized (this.mutex) { |
| return this.twiceExact_(); |
| } |
| } |
| |
| /** |
| * Pre-condition: synchronized |
| */ |
| private int twiceExact_() { |
| int old = this.value; |
| this.value = Math.multiplyExact(old, 2); |
| if (this.value != old) { |
| this.mutex.notifyAll(); |
| } |
| return this.value; |
| } |
| |
| public int abs() { |
| synchronized (this.mutex) { |
| return this.abs_(); |
| } |
| } |
| |
| /** |
| * Pre-condition: synchronized |
| */ |
| private int abs_() { |
| int old = this.value; |
| this.value = Math.abs(old); |
| if (this.value != old) { |
| this.mutex.notifyAll(); |
| } |
| return this.value; |
| } |
| |
| public int negate() { |
| synchronized (this.mutex) { |
| this.value = -this.value; |
| this.mutex.notifyAll(); |
| return this.value; |
| } |
| } |
| |
| public int negateExact() { |
| synchronized (this.mutex) { |
| this.value = Math.negateExact(this.value); |
| this.mutex.notifyAll(); |
| return this.value; |
| } |
| } |
| |
| public int add(int i) { |
| synchronized (this.mutex) { |
| return this.add_(i); |
| } |
| } |
| |
| /** |
| * Pre-condition: synchronized |
| */ |
| private int add_(int i) { |
| int old = this.value; |
| this.value += i; |
| if (this.value != old) { |
| this.mutex.notifyAll(); |
| } |
| return this.value; |
| } |
| |
| public int addExact(int i) { |
| synchronized (this.mutex) { |
| return this.addExact_(i); |
| } |
| } |
| |
| /** |
| * Pre-condition: synchronized |
| */ |
| private int addExact_(int i) { |
| int old = this.value; |
| this.value = Math.addExact(this.value, i); |
| if (this.value != old) { |
| this.mutex.notifyAll(); |
| } |
| return this.value; |
| } |
| |
| public int subtract(int i) { |
| synchronized (this.mutex) { |
| return this.subtract_(i); |
| } |
| } |
| |
| /** |
| * Pre-condition: synchronized |
| */ |
| private int subtract_(int i) { |
| int old = this.value; |
| this.value -= i; |
| if (this.value != old) { |
| this.mutex.notifyAll(); |
| } |
| return this.value; |
| } |
| |
| public int subtractExact(int i) { |
| synchronized (this.mutex) { |
| return this.subtractExact_(i); |
| } |
| } |
| |
| /** |
| * Pre-condition: synchronized |
| */ |
| private int subtractExact_(int i) { |
| int old = this.value; |
| this.value = Math.subtractExact(this.value, i); |
| if (this.value != old) { |
| this.mutex.notifyAll(); |
| } |
| return this.value; |
| } |
| |
| public int multiply(int i) { |
| synchronized (this.mutex) { |
| return this.multiply_(i); |
| } |
| } |
| |
| /** |
| * Pre-condition: synchronized |
| */ |
| private int multiply_(int i) { |
| int old = this.value; |
| this.value = this.value * i; |
| if (this.value != old) { |
| this.mutex.notifyAll(); |
| } |
| return this.value; |
| } |
| |
| public int multiplyExact(int i) { |
| synchronized (this.mutex) { |
| return this.multiplyExact_(i); |
| } |
| } |
| |
| /** |
| * Pre-condition: synchronized |
| */ |
| private int multiplyExact_(int i) { |
| int old = this.value; |
| this.value = Math.multiplyExact(this.value, i); |
| if (this.value != old) { |
| this.mutex.notifyAll(); |
| } |
| return this.value; |
| } |
| |
| public int divide(int i) { |
| synchronized (this.mutex) { |
| return this.divide_(i); |
| } |
| } |
| |
| /** |
| * Pre-condition: synchronized |
| */ |
| private int divide_(int i) { |
| int old = this.value; |
| this.value = this.value / i; |
| if (this.value != old) { |
| this.mutex.notifyAll(); |
| } |
| return this.value; |
| } |
| |
| public int floorDivide(int i) { |
| synchronized (this.mutex) { |
| return this.floorDivide_(i); |
| } |
| } |
| |
| /** |
| * Pre-condition: synchronized |
| */ |
| private int floorDivide_(int i) { |
| int old = this.value; |
| this.value = Math.floorDiv(this.value, i); |
| if (this.value != old) { |
| this.mutex.notifyAll(); |
| } |
| return this.value; |
| } |
| |
| public int remainder(int i) { |
| synchronized (this.mutex) { |
| return this.remainder_(i); |
| } |
| } |
| |
| /** |
| * Pre-condition: synchronized |
| */ |
| private int remainder_(int i) { |
| int old = this.value; |
| this.value = this.value % i; |
| if (this.value != old) { |
| this.mutex.notifyAll(); |
| } |
| return this.value; |
| } |
| |
| public int floorRemainder(int i) { |
| synchronized (this.mutex) { |
| return this.floorRemainder_(i); |
| } |
| } |
| |
| /** |
| * Pre-condition: synchronized |
| */ |
| private int floorRemainder_(int i) { |
| int old = this.value; |
| this.value = Math.floorMod(this.value, i); |
| if (this.value != old) { |
| this.mutex.notifyAll(); |
| } |
| return this.value; |
| } |
| |
| public int min(int i) { |
| synchronized (this.mutex) { |
| return this.min_(i); |
| } |
| } |
| |
| /** |
| * Pre-condition: synchronized |
| */ |
| private int min_(int i) { |
| int old = this.value; |
| this.value = Math.min(this.value, i); |
| if (this.value != old) { |
| this.mutex.notifyAll(); |
| } |
| return this.value; |
| } |
| |
| public int max(int i) { |
| synchronized (this.mutex) { |
| return this.max_(i); |
| } |
| } |
| |
| /** |
| * Pre-condition: synchronized |
| */ |
| private int max_(int i) { |
| int old = this.value; |
| this.value = Math.max(this.value, i); |
| if (this.value != old) { |
| this.mutex.notifyAll(); |
| } |
| return this.value; |
| } |
| |
| public boolean commit(int newValue, int expectedValue) { |
| synchronized (this.mutex) { |
| return this.commit_(newValue, expectedValue); |
| } |
| } |
| |
| /** |
| * Pre-condition: synchronized |
| */ |
| private boolean commit_(int newValue, int expectedValue) { |
| if (this.value == expectedValue) { |
| this.setValue_(newValue); |
| return true; |
| } |
| return false; |
| } |
| |
| public int swap(ModifiableIntReference other) { |
| if (other == this) { |
| return this.getValue(); |
| } |
| if (other instanceof SynchronizedInt) { |
| return this.swap_((SynchronizedInt) other); |
| } |
| |
| int thisValue = 0; |
| int otherValue = other.getValue(); |
| synchronized (this.mutex) { |
| thisValue = this.value; |
| if (thisValue != otherValue) { |
| this.setChangedValue_(otherValue); |
| } |
| } |
| other.setValue(thisValue); |
| return otherValue; |
| } |
| |
| /** |
| * Atomically swap the value of this synchronized int with the value of |
| * the specified synchronized int. Make assumptions about the value of |
| * <em>identity hash code</em> to avoid deadlock when two synchronized |
| * ints swap values with each other simultaneously. |
| * If either value changes, the corresponding waiting threads are notified. |
| * Return the new value. |
| */ |
| public int swap(SynchronizedInt other) { |
| return (other == this) ? this.getValue() : this.swap_(other); |
| } |
| |
| /** |
| * Pre-condition: not same object |
| */ |
| private int swap_(SynchronizedInt other) { |
| boolean thisFirst = System.identityHashCode(this) < System.identityHashCode(other); |
| SynchronizedInt first = thisFirst ? this : other; |
| SynchronizedInt second = thisFirst ? other : this; |
| synchronized (first.mutex) { |
| synchronized (second.mutex) { |
| int thisValue = this.value; |
| int otherValue = other.value; |
| if (thisValue == otherValue) { |
| return thisValue; // nothing changes |
| } |
| other.setChangedValue_(thisValue); |
| this.setChangedValue_(otherValue); |
| return otherValue; |
| } |
| } |
| } |
| |
| /** |
| * Return the object the synchronized integer locks on while performing |
| * its operations. |
| */ |
| public Object getMutex() { |
| return this.mutex; |
| } |
| |
| |
| // ********** indefinite waits ********** |
| |
| /** |
| * Suspend the current thread until the value changes |
| * to belong to the set specified by the specified predicate. |
| * If the value already belongs to the set, return immediately. |
| */ |
| public void waitUntil(IntPredicate predicate) throws InterruptedException { |
| synchronized (this.mutex) { |
| this.waitUntil_(predicate); |
| } |
| } |
| |
| /** |
| * Pre-condition: synchronized |
| */ |
| private void waitUntil_(IntPredicate predicate) throws InterruptedException { |
| while ( ! predicate.evaluate(this.value)) { |
| this.mutex.wait(); |
| } |
| } |
| |
| /** |
| * Suspend the current thread until the value changes |
| * to no longer belong to the set specified by the specified predicate. |
| * If the value already does not belong to the set, return immediately. |
| */ |
| public void waitUntilNot(IntPredicate predicate) throws InterruptedException { |
| this.waitUntil(IntPredicateTools.not(predicate)); |
| } |
| |
| /** |
| * Suspend the current thread until the value changes |
| * to the specified value. If the value is already the |
| * specified value, return immediately. |
| */ |
| public void waitUntilEqual(int i) throws InterruptedException { |
| this.waitUntil(IntPredicateTools.isEqual(i)); |
| } |
| |
| /** |
| * Suspend the current thread until the value changes |
| * to something other than the specified value. If the |
| * value is already <em>not</em> the specified value, |
| * return immediately. |
| */ |
| public void waitUntilNotEqual(int i) throws InterruptedException { |
| this.waitUntil(IntPredicateTools.notEqual(i)); |
| } |
| |
| /** |
| * Suspend the current thread until the value changes to zero. |
| * If the value is already zero, return immediately. |
| */ |
| public void waitUntilZero() throws InterruptedException { |
| this.waitUntilEqual(0); |
| } |
| |
| /** |
| * Suspend the current thread until the value changes |
| * to something other than zero. |
| * If the value is already <em>not</em> zero, |
| * return immediately. |
| */ |
| public void waitUntilNotZero() throws InterruptedException { |
| this.waitUntilNotEqual(0); |
| } |
| |
| /** |
| * Suspend the current thread until the value changes |
| * to a value greater than the specified value. If the value is already |
| * greater than the specified value, return immediately. |
| */ |
| public void waitUntilGreaterThan(int i) throws InterruptedException { |
| this.waitUntil(IntPredicateTools.isGreaterThan(i)); |
| } |
| |
| /** |
| * Suspend the current thread until the value changes |
| * to a value greater than or equal to the specified value. If the value is already |
| * greater than or equal the specified value, return immediately. |
| */ |
| public void waitUntilGreaterThanOrEqual(int i) throws InterruptedException { |
| this.waitUntil(IntPredicateTools.isGreaterThanOrEqual(i)); |
| } |
| |
| /** |
| * Suspend the current thread until the value changes |
| * to a value less than the specified value. If the value is already |
| * less than the specified value, return immediately. |
| */ |
| public void waitUntilLessThan(int i) throws InterruptedException { |
| this.waitUntil(IntPredicateTools.isLessThan(i)); |
| } |
| |
| /** |
| * Suspend the current thread until the value changes |
| * to a value less than or equal to the specified value. If the value is already |
| * less than or equal the specified value, return immediately. |
| */ |
| public void waitUntilLessThanOrEqual(int i) throws InterruptedException { |
| this.waitUntil(IntPredicateTools.isLessThanOrEqual(i)); |
| } |
| |
| /** |
| * Suspend the current thread until the value is positive. |
| * If the value is already positive, return immediately. |
| */ |
| public void waitUntilPositive() throws InterruptedException { |
| this.waitUntilGreaterThan(0); |
| } |
| |
| /** |
| * Suspend the current thread until the value is not positive |
| * (i.e. negative or zero). |
| * If the value is already <em>not</em> positive, |
| * return immediately. |
| */ |
| public void waitUntilNotPositive() throws InterruptedException { |
| this.waitUntilLessThanOrEqual(0); |
| } |
| |
| /** |
| * Suspend the current thread until the value is negative. |
| * If the value is already negative, return immediately. |
| */ |
| public void waitUntilNegative() throws InterruptedException { |
| this.waitUntilLessThan(0); |
| } |
| |
| /** |
| * Suspend the current thread until the value is not negative |
| * (i.e. zero or positive). |
| * If the value is already <em>not</em> negative, |
| * return immediately. |
| */ |
| public void waitUntilNotNegative() throws InterruptedException { |
| this.waitUntilGreaterThanOrEqual(0); |
| } |
| |
| /** |
| * Suspend the current thread until the value changes to |
| * something other than the specified value, then change |
| * it back to the specified value and continue executing. |
| * If the value is already <em>not</em> the specified value, set |
| * the value immediately. |
| * Return the previous value. |
| */ |
| public int waitToSetValue(int i) throws InterruptedException { |
| synchronized (this.mutex) { |
| this.waitUntil_(IntPredicateTools.notEqual(i)); |
| return this.setChangedValue_(i); |
| } |
| } |
| |
| /** |
| * Suspend the current thread until the value changes to |
| * something other than zero, then change it |
| * back to zero and continue executing. |
| * If the value is already <em>not</em> zero, |
| * set the value to zero immediately. |
| * Return the previous value. |
| */ |
| public int waitToSetZero() throws InterruptedException { |
| return this.waitToSetValue(0); |
| } |
| |
| /** |
| * Suspend the current thread until the value changes to |
| * the specified expected value, then change it |
| * to the specified new value and continue executing. |
| * If the value is already the specified expected value, |
| * set the value to the specified new value immediately. |
| * Return the previous value. |
| */ |
| public int waitToCommit(int newValue, int expectedValue) throws InterruptedException { |
| synchronized (this.mutex) { |
| this.waitUntil_(IntPredicateTools.isEqual(expectedValue)); |
| return this.setValue_(newValue); |
| } |
| } |
| |
| |
| // ********** timed waits ********** |
| |
| /** |
| * Suspend the current thread until the value changes |
| * to belong to the set specified by the specified predicate |
| * or the specified time-out occurs. |
| * The time-out is specified in milliseconds. Return <code>true</code> |
| * if the value now beloongs to the set; return <code>false</code> |
| * if a time-out occurred. If the value already belongs to the set, |
| * return <code>true</code> immediately. |
| * If the time-out is zero, wait indefinitely. |
| */ |
| public boolean waitUntil(IntPredicate predicate, long timeout) throws InterruptedException { |
| synchronized (this.mutex) { |
| return this.waitUntil_(predicate, timeout); |
| } |
| } |
| |
| /** |
| * Pre-condition: synchronized |
| */ |
| private boolean waitUntil_(IntPredicate predicate, long timeout) throws InterruptedException { |
| if (timeout == 0L) { |
| this.waitUntil_(predicate); // wait indefinitely until notified |
| return true; // if it ever comes back, the condition was met |
| } |
| |
| long stop = System.currentTimeMillis() + timeout; |
| long remaining = timeout; |
| while (( ! predicate.evaluate(this.value)) && (remaining > 0L)) { |
| this.mutex.wait(remaining); |
| remaining = stop - System.currentTimeMillis(); |
| } |
| return predicate.evaluate(this.value); |
| } |
| |
| /** |
| * Suspend the current thread until the value changes |
| * to belong to the set specified by the specified predicate |
| * or the specified time-out occurs. |
| * The time-out is specified in milliseconds. Return <code>true</code> |
| * if the value now beloongs to the set; return <code>false</code> |
| * if a time-out occurred. If the value already belongs to the set, |
| * return <code>true</code> immediately. |
| * If the time-out is zero, wait indefinitely. |
| */ |
| public boolean waitUntilNot(IntPredicate predicate, long timeout) throws InterruptedException { |
| return this.waitUntil(IntPredicateTools.not(predicate), timeout); |
| } |
| |
| /** |
| * Suspend the current thread until the value changes |
| * to the specified value or the specified time-out occurs. |
| * The time-out is specified in milliseconds. Return <code>true</code> |
| * if the specified value was achieved; return <code>false</code> |
| * if a time-out occurred. |
| * If the value is already the specified value, return true immediately. |
| * If the time-out is zero, wait indefinitely. |
| */ |
| public boolean waitUntilEqual(int i, long timeout) throws InterruptedException { |
| return this.waitUntil(IntPredicateTools.isEqual(i), timeout); |
| } |
| |
| /** |
| * Suspend the current thread until the value changes to something |
| * other than the specified value or the specified time-out occurs. |
| * The time-out is specified in milliseconds. Return <code>true</code> |
| * if the specified value was removed; return <code>false</code> if a |
| * time-out occurred. If the value is already <em>not</em> the specified |
| * value, return <code>true</code> immediately. |
| * If the time-out is zero, wait indefinitely. |
| */ |
| public boolean waitUntilNotEqual(int i, long timeout) throws InterruptedException { |
| return this.waitUntil(IntPredicateTools.notEqual(i), timeout); |
| } |
| |
| /** |
| * Suspend the current thread until the value changes |
| * to zero or the specified time-out occurs. |
| * The time-out is specified in milliseconds. Return <code>true</code> |
| * if the value is now zero; return <code>false</code> |
| * if a time-out occurred. If the value is already zero, |
| * return <code>true</code> immediately. |
| * If the time-out is zero, wait indefinitely. |
| */ |
| public boolean waitUntilZero(long timeout) throws InterruptedException { |
| return this.waitUntilEqual(0, timeout); |
| } |
| |
| /** |
| * Suspend the current thread until the value changes |
| * to something other than zero or the specified time-out occurs. |
| * The time-out is specified in milliseconds. Return <code>true</code> |
| * if the value is now not zero; return <code>false</code> |
| * if a time-out occurred. If the value is already <em>not</em> |
| * zero, return <code>true</code> immediately. |
| * If the time-out is zero, wait indefinitely. |
| */ |
| public boolean waitUntilNotZero(long timeout) throws InterruptedException { |
| return this.waitUntilNotEqual(0, timeout); |
| } |
| |
| /** |
| * Suspend the current thread until the value changes to a value greater |
| * than the specified value or the specified time-out occurs. |
| * The time-out is specified in milliseconds. Return <code>true</code> |
| * if the specified value was achieved; return <code>false</code> |
| * if a time-out occurred. |
| * If the value is already greater than the specified value, return immediately. |
| * If the time-out is zero, wait indefinitely. |
| */ |
| public boolean waitUntilGreaterThan(int i, long timeout) throws InterruptedException { |
| return this.waitUntil(IntPredicateTools.isGreaterThan(i), timeout); |
| } |
| |
| /** |
| * Suspend the current thread until the value changes to a value greater |
| * than or equal to the specified value or the specified time-out occurs. |
| * The time-out is specified in milliseconds. Return <code>true</code> |
| * if the specified value was achieved; return <code>false</code> |
| * if a time-out occurred. |
| * If the value is already greater than or equal to the specified value, |
| * return immediately. |
| * If the time-out is zero, wait indefinitely. |
| */ |
| public boolean waitUntilGreaterThanOrEqual(int i, long timeout) throws InterruptedException { |
| return this.waitUntil(IntPredicateTools.isGreaterThanOrEqual(i), timeout); |
| } |
| |
| /** |
| * Suspend the current thread until the value changes to a value less |
| * than the specified value or the specified time-out occurs. |
| * The time-out is specified in milliseconds. Return <code>true</code> |
| * if the specified value was achieved; return <code>false</code> |
| * if a time-out occurred. |
| * If the value is already less than the specified value, return immediately. |
| * If the time-out is zero, wait indefinitely. |
| */ |
| public boolean waitUntilLessThan(int i, long timeout) throws InterruptedException { |
| return this.waitUntil(IntPredicateTools.isLessThan(i), timeout); |
| } |
| |
| /** |
| * Suspend the current thread until the value changes to a value less |
| * than or equal to the specified value or the specified time-out occurs. |
| * The time-out is specified in milliseconds. Return <code>true</code> |
| * if the specified value was achieved; return <code>false</code> |
| * if a time-out occurred. |
| * If the value is already less than or equal to the specified value, |
| * return immediately. |
| * If the time-out is zero, wait indefinitely. |
| */ |
| public boolean waitUntilLessThanOrEqual(int i, long timeout) throws InterruptedException { |
| return this.waitUntil(IntPredicateTools.isLessThanOrEqual(i), timeout); |
| } |
| |
| /** |
| * Suspend the current thread until the value is positive |
| * or the specified time-out occurs. |
| * The time-out is specified in milliseconds. Return <code>true</code> |
| * if the value is now positive; return <code>false</code> |
| * if a time-out occurred. If the value is already positive, |
| * return <code>true</code> immediately. |
| * If the time-out is zero, wait indefinitely. |
| */ |
| public boolean waitUntilPositive(long timeout) throws InterruptedException { |
| return this.waitUntilGreaterThan(0, timeout); |
| } |
| |
| /** |
| * Suspend the current thread until the value is not positive |
| * or the specified time-out occurs. |
| * The time-out is specified in milliseconds. Return <code>true</code> |
| * if the value is now not positive; return <code>false</code> |
| * if a time-out occurred. If the value is already not positive, |
| * return <code>true</code> immediately. |
| * If the time-out is zero, wait indefinitely. |
| */ |
| public boolean waitUntilNotPositive(long timeout) throws InterruptedException { |
| return this.waitUntilLessThanOrEqual(0, timeout); |
| } |
| |
| /** |
| * Suspend the current thread until the value is negative |
| * or the specified time-out occurs. |
| * The time-out is specified in milliseconds. Return <code>true</code> |
| * if the value is now negative; return <code>false</code> |
| * if a time-out occurred. If the value is already negative, |
| * return <code>true</code> immediately. |
| * If the time-out is zero, wait indefinitely. |
| */ |
| public boolean waitUntilNegative(long timeout) throws InterruptedException { |
| return this.waitUntilLessThan(0, timeout); |
| } |
| |
| /** |
| * Suspend the current thread until the value is not negative |
| * or the specified time-out occurs. |
| * The time-out is specified in milliseconds. Return <code>true</code> |
| * if the value is now not negative; return <code>false</code> |
| * if a time-out occurred. If the value is already not negative, |
| * return <code>true</code> immediately. |
| * If the time-out is zero, wait indefinitely. |
| */ |
| public boolean waitUntilNotNegative(long timeout) throws InterruptedException { |
| return this.waitUntilGreaterThanOrEqual(0, timeout); |
| } |
| |
| /** |
| * Suspend the current thread until the value changes to |
| * something other than the specified value, then change |
| * it back to the specified value and continue executing. |
| * If the value does not change to something other than the |
| * specified value before the time-out, simply continue executing |
| * without changing the value. |
| * The time-out is specified in milliseconds. Return <code>true</code> |
| * if the value was set to the specified value; return <code>false</code> |
| * if a time-out occurred. |
| * If the value is already something other than the specified value, set |
| * the value immediately and return <code>true</code>. |
| * If the time-out is zero, wait indefinitely. |
| */ |
| public boolean waitToSetValue(int i, long timeout) throws InterruptedException { |
| synchronized (this.mutex) { |
| boolean success = this.waitUntil_(IntPredicateTools.notEqual(i), timeout); |
| if (success) { |
| this.setChangedValue_(i); |
| } |
| return success; |
| } |
| } |
| |
| /** |
| * Suspend the current thread until the value changes to something |
| * other than zero, then change it back to zero |
| * and continue executing. If the value does not change to something |
| * other than zero before the time-out, simply continue |
| * executing without changing the value. |
| * The time-out is specified in milliseconds. Return <code>true</code> |
| * if the value was set to zero; return <code>false</code> |
| * if a time-out occurred. |
| * If the value is already something other than zero, set |
| * the value to zero immediately and return <code>true</code>. |
| * If the time-out is zero, wait indefinitely. |
| */ |
| public boolean waitToSetZero(long timeout) throws InterruptedException { |
| return this.waitToSetValue(0, timeout); |
| } |
| |
| /** |
| * Suspend the current thread until the value changes to |
| * the specified expected value, then change it |
| * to the specified new value and continue executing. |
| * If the value does not change to the specified expected value |
| * before the time-out, simply continue executing without changing |
| * the value. |
| * The time-out is specified in milliseconds. Return <code>true</code> |
| * if the value was set to the specified new value; return |
| * <code>false</code> if a time-out occurred. |
| * If the value is already the specified expected value, |
| * set the value to the specified new value immediately. |
| * Return the previous value. |
| * If the time-out is zero, wait indefinitely. |
| */ |
| public boolean waitToCommit(int newValue, int expectedValue, long timeout) throws InterruptedException { |
| synchronized (this.mutex) { |
| boolean success = this.waitUntil_(IntPredicateTools.isEqual(expectedValue), timeout); |
| if (success) { |
| this.setValue_(newValue); |
| } |
| return success; |
| } |
| } |
| |
| |
| // ********** synchronized behavior ********** |
| |
| /** |
| * If current thread is not interrupted, execute the specified command |
| * with the mutex locked. This is useful for initializing the value from another |
| * thread. |
| */ |
| public void execute(Command command) throws InterruptedException { |
| if (Thread.currentThread().isInterrupted()) { |
| throw new InterruptedException(); |
| } |
| synchronized (this.mutex) { |
| command.execute(); |
| } |
| } |
| |
| |
| // ********** Comparable implementation ********** |
| |
| public int compareTo(IntReference other) { |
| int thisValue = this.getValue(); |
| int otherValue = other.getValue(); |
| return (thisValue < otherValue) ? -1 : ((thisValue == otherValue) ? 0 : 1); |
| } |
| |
| |
| // ********** standard methods ********** |
| |
| @Override |
| public SynchronizedInt clone() { |
| try { |
| synchronized (this.mutex) { |
| return (SynchronizedInt) super.clone(); |
| } |
| } catch (CloneNotSupportedException ex) { |
| throw new InternalError(); |
| } |
| } |
| |
| /** |
| * Object identity is critical to int references. |
| * There is no reason for two different int references to be |
| * <em>equal</em>. |
| * |
| * @see #equals(int) |
| */ |
| @Override |
| public boolean equals(Object obj) { |
| return super.equals(obj); |
| } |
| |
| /** |
| * @see #equals(Object) |
| */ |
| @Override |
| public int hashCode() { |
| return super.hashCode(); |
| } |
| |
| @Override |
| public String toString() { |
| return '[' + String.valueOf(this.getValue()) + ']'; |
| } |
| |
| private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException { |
| synchronized (this.mutex) { |
| s.defaultWriteObject(); |
| } |
| } |
| } |