rework BooleanReferences
diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/reference/SimpleBooleanReference.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/reference/SimpleBooleanReference.java
index 8160468..0d935a2 100644
--- a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/reference/SimpleBooleanReference.java
+++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/reference/SimpleBooleanReference.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2008, 2012 Oracle. All rights reserved.
+ * Copyright (c) 2008, 2015 Oracle. All rights reserved.
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0, which accompanies this distribution
  * and is available at http://www.eclipse.org/legal/epl-v10.html.
@@ -77,8 +77,20 @@
 		return this.value = ! this.value;
 	}
 
-	public boolean setNot(boolean v) {
-		return this.setValue( ! v);
+	public boolean and(boolean b) {
+		return this.value &= b;
+	}
+
+	public boolean or(boolean b) {
+		return this.value |= b;
+	}
+
+	public boolean xor(boolean b) {
+		return this.value ^= b;
+	}
+
+	public boolean setNot(boolean b) {
+		return this.setValue( ! b);
 	}
 
 	public boolean setTrue() {
@@ -89,6 +101,27 @@
 		return this.setValue(false);
 	}
 
+	public boolean commit(boolean newValue, boolean expectedValue) {
+		if (this.value == expectedValue) {
+			this.value = newValue;
+			return true;
+		}
+		return false;
+	}
+
+	public boolean swap(ModifiableBooleanReference other) {
+	    if (other == this) {
+	        return this.value;
+	    }
+	    boolean thisValue = this.value;
+	    boolean otherValue = other.getValue();
+	    if (thisValue != otherValue) {
+	        other.setValue(thisValue);
+	        this.value = otherValue;
+	    }
+	    return otherValue;
+	}
+
 
 	// ********** standard methods **********
 
diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/reference/SynchronizedBoolean.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/reference/SynchronizedBoolean.java
index 043d884..931479e 100644
--- a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/reference/SynchronizedBoolean.java
+++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/internal/reference/SynchronizedBoolean.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2007, 2012 Oracle. All rights reserved.
+ * Copyright (c) 2007, 2015 Oracle. All rights reserved.
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0, which accompanies this distribution
  * and is available at http://www.eclipse.org/legal/epl-v10.html.
@@ -131,7 +131,6 @@
 
 	/**
 	 * If the value changes, all waiting threads are notified.
-	 * Return the new value.
 	 */
 	public boolean flip() {
 		synchronized (this.mutex) {
@@ -140,7 +139,6 @@
 	}
 
 	/**
-	 * Set the value to <code>value & b</code> and return the new value.
 	 * If the value changes, all waiting threads are notified.
 	 */
 	public boolean and(boolean b) {
@@ -150,7 +148,6 @@
 	}
 
 	/**
-	 * Set the value to <code>value | b</code> and return the new value.
 	 * If the value changes, all waiting threads are notified.
 	 */
 	public boolean or(boolean b) {
@@ -160,7 +157,6 @@
 	}
 
 	/**
-	 * Set the value to <code>value ^ b</code> and return the new value.
 	 * If the value changes, all waiting threads are notified.
 	 */
 	public boolean xor(boolean b) {
@@ -200,21 +196,49 @@
 	}
 
 	/**
-	 * Set the value to the specified new value if it is currently the specified
-	 * expected value. If the value changes, all waiting threads are notified.
-	 * Return whether the commit was successful.
+	 * If the value changes, all waiting threads are notified.
 	 */
-	public boolean commit(boolean expectedValue, boolean newValue) {
+	public boolean commit(boolean newValue, boolean expectedValue) {
 		synchronized (this.mutex) {
-			boolean success = (this.value == expectedValue);
-			if (success) {
-				this.setValue_(newValue);
-			}
-			return success;
+			return this.commit_(newValue, expectedValue);
 		}
 	}
 
 	/**
+	 * Pre-condition: synchronized
+	 */
+	private boolean commit_(boolean newValue, boolean expectedValue) {
+		if (this.value == expectedValue) {
+			this.setValue_(newValue);
+			return true;
+		}
+		return false;
+	}
+
+	/**
+	 * If the value changes, all waiting threads are notified.
+	 */
+	public boolean swap(ModifiableBooleanReference other) {
+		if (other == this) {
+			return this.getValue();
+		}
+		if (other instanceof SynchronizedBoolean) {
+			return this.swap_((SynchronizedBoolean) other);
+		}
+
+		boolean thisValue = false;
+	    boolean 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 boolean with the value of
 	 * the specified synchronized boolean. Make assumptions about the value of
 	 * <em>identity hash code</em> to avoid deadlock when two synchronized
@@ -223,9 +247,13 @@
 	 * Return the new value.
 	 */
 	public boolean swap(SynchronizedBoolean other) {
-		if (other == this) {
-			return this.getValue();
-		}
+		return (other == this) ? this.getValue() : this.swap_(other);
+	}
+
+	/**
+	 * Pre-condition: not same object
+	 */
+	private boolean swap_(SynchronizedBoolean other) {
 		boolean thisFirst = System.identityHashCode(this) < System.identityHashCode(other);
 		SynchronizedBoolean first = thisFirst ? this : other;
 		SynchronizedBoolean second = thisFirst ? other : this;
@@ -319,6 +347,17 @@
 
 	/**
 	 * Suspend the current thread until the <code>boolean</code> value
+	 * changes to the specified value,
+	 * then change it back to the NOT of the specified value and continue executing.
+	 * If the <code>boolean</code> value is already the specified value,
+	 * set the value to the NOT of the specified value immediately.
+	 */
+	public void waitToSetValueNot(boolean b) throws InterruptedException {
+		this.waitToSetValue( ! b);
+	}
+
+	/**
+	 * Suspend the current thread until the <code>boolean</code> value
 	 * changes to <code>false</code>,
 	 * then change it back to <code>true</code> and continue executing.
 	 * If the <code>boolean</code> value is already <code>false</code>,
@@ -346,11 +385,9 @@
 	 * If the <code>boolean</code> value is already equal to the specified
 	 * value, execute the specified command immediately.
 	 */
-	public void whenEqual(boolean b, InterruptibleCommand command) throws InterruptedException {
-		synchronized (this.mutex) {
-			this.waitUntilValueIs_(b);
-			command.execute();
-		}
+	public void whenValueIs(boolean b, InterruptibleCommand command) throws InterruptedException {
+		this.waitUntilValueIs(b);
+		command.execute();
 	}
 
 	/**
@@ -360,8 +397,8 @@
 	 * If the <code>boolean</code> value is already the NOT of the specified
 	 * value, execute the specified command immediately.
 	 */
-	public void whenNotEqual(boolean b, InterruptibleCommand command) throws InterruptedException {
-		this.whenEqual( ! b, command);
+	public void whenValueIsNot(boolean b, InterruptibleCommand command) throws InterruptedException {
+		this.whenValueIs( ! b, command);
 	}
 
 	/**
@@ -371,8 +408,8 @@
 	 * If the <code>boolean</code> value is already <code>true</code>,
 	 * execute the specified command immediately.
 	 */
-	public void whenTrue(InterruptibleCommand command) throws InterruptedException {
-		this.whenEqual(true, command);
+	public void whenTrueExecute(InterruptibleCommand command) throws InterruptedException {
+		this.whenValueIs(true, command);
 	}
 
 	/**
@@ -382,8 +419,8 @@
 	 * If the <code>boolean</code> value is already <code>false</code>,
 	 * execute the specified command immediately.
 	 */
-	public void whenFalse(InterruptibleCommand command) throws InterruptedException {
-		this.whenEqual(false, command);
+	public void whenFalseExecute(InterruptibleCommand command) throws InterruptedException {
+		this.whenValueIs(false, command);
 	}
 
 
@@ -469,7 +506,7 @@
 	 * Suspend the current thread until the <code>boolean</code> value changes
 	 * to the NOT of the specified value, then change it back to the specified
 	 * value and continue executing. If the <code>boolean</code> value does not
-	 * change to <code>false</code> before the time-out, simply continue
+	 * change to the NOT of the specified 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>
@@ -491,6 +528,24 @@
 
 	/**
 	 * Suspend the current thread until the <code>boolean</code> value changes
+	 * to the specified value, then change it back to the NOT of the specified
+	 * value and continue executing. If the <code>boolean</code> value does not
+	 * change to the specified 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 NOT of the specified value; return <code>false</code>
+	 * if a time-out occurred.
+	 * If the <code>boolean</code> value is already
+	 * the specified value, set the value to the NOT of the specified value
+	 * immediately and return <code>true</code>.
+	 * If the time-out is zero, wait indefinitely.
+	 */
+	public void waitToSetValueNot(boolean b, long timeout) throws InterruptedException {
+		this.waitToSetValue( ! b, timeout);
+	}
+
+	/**
+	 * Suspend the current thread until the <code>boolean</code> value changes
 	 * to <code>false</code>, then change it back to <code>true</code> and
 	 * continue executing. If the <code>boolean</code> value does not change to
 	 * <code>false</code> before the time-out, simply continue executing without
@@ -534,14 +589,15 @@
 	 * execute the specified command immediately and return <code>true</code>.
 	 * If the time-out is zero, wait indefinitely.
 	 */
-	public boolean whenEqual(boolean b, InterruptibleCommand command, long timeout) throws InterruptedException {
+	public boolean whenValueIs(boolean b, InterruptibleCommand command, long timeout) throws InterruptedException {
+		boolean success = false;
 		synchronized (this.mutex) {
-			boolean success = this.waitUntilValueIs_(b, timeout);
-			if (success) {
-				command.execute();
-			}
-			return success;
+			success = this.waitUntilValueIs_(b, timeout);
 		}
+		if (success) {
+			command.execute();
+		}
+		return success;
 	}
 
 	/**
@@ -555,8 +611,8 @@
 	 * execute the specified command immediately and return <code>true</code>.
 	 * If the time-out is zero, wait indefinitely.
 	 */
-	public boolean whenNotEqual(boolean b, InterruptibleCommand command, long timeout) throws InterruptedException {
-		return this.whenEqual( ! b, command, timeout);
+	public boolean whenValueIsNot(boolean b, InterruptibleCommand command, long timeout) throws InterruptedException {
+		return this.whenValueIs( ! b, command, timeout);
 	}
 
 	/**
@@ -570,8 +626,8 @@
 	 * execute the specified command immediately and return <code>true</code>.
 	 * If the time-out is zero, wait indefinitely.
 	 */
-	public boolean whenTrue(InterruptibleCommand command, long timeout) throws InterruptedException {
-		return this.whenEqual(true, command, timeout);
+	public boolean whenTrueExecute(InterruptibleCommand command, long timeout) throws InterruptedException {
+		return this.whenValueIs(true, command, timeout);
 	}
 
 	/**
@@ -585,8 +641,8 @@
 	 * execute the specified command immediately and return <code>true</code>.
 	 * If the time-out is zero, wait indefinitely.
 	 */
-	public boolean whenFalse(InterruptibleCommand command, long timeout) throws InterruptedException {
-		return this.whenEqual(false, command, timeout);
+	public boolean whenFalseExecute(InterruptibleCommand command, long timeout) throws InterruptedException {
+		return this.whenValueIs(false, command, timeout);
 	}
 
 
diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/reference/BooleanReference.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/reference/BooleanReference.java
index ba09502..c46a84d 100644
--- a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/reference/BooleanReference.java
+++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/reference/BooleanReference.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2010, 2013 Oracle. All rights reserved.
+ * Copyright (c) 2010, 2015 Oracle. All rights reserved.
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0, which accompanies this distribution
  * and is available at http://www.eclipse.org/legal/epl-v10.html.
@@ -31,13 +31,13 @@
 	 * Return whether the current <code>boolean</code> value is equal to the
 	 * specified value.
 	 */
-	boolean is(boolean value);
+	boolean is(boolean b);
 
 	/**
 	 * Return whether the current <code>boolean</code> value is not equal to
 	 * the specified value.
 	 */
-	boolean isNot(boolean value);
+	boolean isNot(boolean b);
 
 	/**
 	 * Return whether the current <code>boolean</code> value is
diff --git a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/reference/ModifiableBooleanReference.java b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/reference/ModifiableBooleanReference.java
index 296c9a5..23f5897 100644
--- a/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/reference/ModifiableBooleanReference.java
+++ b/common/plugins/org.eclipse.jpt.common.utility/src/org/eclipse/jpt/common/utility/reference/ModifiableBooleanReference.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2010, 2012 Oracle. All rights reserved.
+ * Copyright (c) 2010, 2015 Oracle. All rights reserved.
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0, which accompanies this distribution
  * and is available at http://www.eclipse.org/legal/epl-v10.html.
@@ -35,10 +35,31 @@
 	boolean flip();
 
 	/**
+	 * Set the <code>boolean</code> value to the AND of the current value and
+	 * the specified value.
+	 * Return the new value.
+	 */
+	boolean and(boolean b);
+
+	/**
+	 * Set the <code>boolean</code> value to the OR of the current value and
+	 * the specified value.
+	 * Return the new value.
+	 */
+	boolean or(boolean b);
+
+	/**
+	 * Set the <code>boolean</code> value to the XOR of the current value and
+	 * the specified value.
+	 * Return the new value.
+	 */
+	boolean xor(boolean b);
+
+	/**
 	 * Set the <code>boolean</code> value to the NOT of the specified value.
 	 * Return the previous value.
 	 */
-	boolean setNot(boolean v);
+	boolean setNot(boolean b);
 
 	/**
 	 * Set the <code>boolean</code> value to <code>true</code>.
@@ -51,4 +72,18 @@
 	 * Return the previous value.
 	 */
 	boolean setFalse();
+
+	/**
+	 * Set the <code>boolean</code> value to the specified new value if it is
+	 * currently the specified expected value.
+	 * Return whether the set was successful.
+	 */
+	boolean commit(boolean newValue, boolean expectedValue);
+
+	/**
+ 	 * Swap the <code>boolean</code> value of the <code>boolean</code> reference with
+ 	 * the value of the specified <code>boolean</code> reference.
+ 	 * Return the new value.
+	 */
+	boolean swap(ModifiableBooleanReference other);
 }
diff --git a/common/tests/org.eclipse.jpt.common.utility.tests/src/org/eclipse/jpt/common/utility/tests/internal/reference/AbstractBooleanReferenceTests.java b/common/tests/org.eclipse.jpt.common.utility.tests/src/org/eclipse/jpt/common/utility/tests/internal/reference/AbstractBooleanReferenceTests.java
new file mode 100644
index 0000000..12be659
--- /dev/null
+++ b/common/tests/org.eclipse.jpt.common.utility.tests/src/org/eclipse/jpt/common/utility/tests/internal/reference/AbstractBooleanReferenceTests.java
@@ -0,0 +1,77 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0, which accompanies this distribution
+ * and is available at http://www.eclipse.org/legal/epl-v10.html.
+ * 
+ * Contributors:
+ *     Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.common.utility.tests.internal.reference;
+
+import org.eclipse.jpt.common.utility.internal.reference.AbstractBooleanReference;
+import junit.framework.TestCase;
+
+@SuppressWarnings("nls")
+public class AbstractBooleanReferenceTests
+	extends TestCase
+{
+	public AbstractBooleanReferenceTests(String name) {
+		super(name);
+	}
+
+	public void testGetValue() {
+		LocalBooleanReference br = new LocalBooleanReference();
+		assertTrue(br.getValue());
+	}
+
+	public void testIs() {
+		LocalBooleanReference br = new LocalBooleanReference();
+		assertTrue(br.is(true));
+		assertFalse(br.is(false));
+	}
+
+	public void testIsNot() {
+		LocalBooleanReference br = new LocalBooleanReference();
+		assertFalse(br.isNot(true));
+		assertTrue(br.isNot(false));
+	}
+
+	public void testIsTrue() {
+		LocalBooleanReference br = new LocalBooleanReference();
+		assertTrue(br.isTrue());
+	}
+
+	public void testIsFalse() {
+		LocalBooleanReference br = new LocalBooleanReference();
+		assertFalse(br.isFalse());
+	}
+
+	public void testEquals() {
+		LocalBooleanReference br1 = new LocalBooleanReference();
+		LocalBooleanReference br2 = new LocalBooleanReference();
+		assertTrue(br1.equals(br1));
+		assertFalse(br1.equals(br2));
+	}
+
+	public void testHashCode() {
+		LocalBooleanReference br = new LocalBooleanReference();
+		assertEquals(br.hashCode(), br.hashCode());
+	}
+
+	public void testToString() {
+		LocalBooleanReference br = new LocalBooleanReference();
+		assertEquals("[true]", br.toString());
+	}
+
+	private class LocalBooleanReference
+		extends AbstractBooleanReference
+	{
+		LocalBooleanReference() {
+			super();
+		}
+		public boolean getValue() {
+			return true;
+		}
+	}
+}
diff --git a/common/tests/org.eclipse.jpt.common.utility.tests/src/org/eclipse/jpt/common/utility/tests/internal/reference/JptCommonUtilityReferenceTests.java b/common/tests/org.eclipse.jpt.common.utility.tests/src/org/eclipse/jpt/common/utility/tests/internal/reference/JptCommonUtilityReferenceTests.java
index 5e3cf51..719d019 100644
--- a/common/tests/org.eclipse.jpt.common.utility.tests/src/org/eclipse/jpt/common/utility/tests/internal/reference/JptCommonUtilityReferenceTests.java
+++ b/common/tests/org.eclipse.jpt.common.utility.tests/src/org/eclipse/jpt/common/utility/tests/internal/reference/JptCommonUtilityReferenceTests.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2012 Oracle. All rights reserved.
+ * Copyright (c) 2012, 2015 Oracle. All rights reserved.
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0, which accompanies this distribution
  * and is available at http://www.eclipse.org/legal/epl-v10.html.
@@ -20,6 +20,7 @@
 	public static Test suite() {
 		TestSuite suite = new TestSuite(JptCommonUtilityReferenceTests.class.getPackage().getName());
 
+		suite.addTestSuite(AbstractBooleanReferenceTests.class);
 		suite.addTestSuite(SimpleBooleanReferenceTests.class);
 		suite.addTestSuite(SimpleIntReferenceTests.class);
 		suite.addTestSuite(SimpleObjectReferenceTests.class);
diff --git a/common/tests/org.eclipse.jpt.common.utility.tests/src/org/eclipse/jpt/common/utility/tests/internal/reference/SimpleBooleanReferenceTests.java b/common/tests/org.eclipse.jpt.common.utility.tests/src/org/eclipse/jpt/common/utility/tests/internal/reference/SimpleBooleanReferenceTests.java
index 27f9c32..ba9b630 100644
--- a/common/tests/org.eclipse.jpt.common.utility.tests/src/org/eclipse/jpt/common/utility/tests/internal/reference/SimpleBooleanReferenceTests.java
+++ b/common/tests/org.eclipse.jpt.common.utility.tests/src/org/eclipse/jpt/common/utility/tests/internal/reference/SimpleBooleanReferenceTests.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2008, 2010 Oracle. All rights reserved.
+ * Copyright (c) 2008, 2015 Oracle. All rights reserved.
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0, which accompanies this distribution
  * and is available at http://www.eclipse.org/legal/epl-v10.html.
@@ -13,8 +13,9 @@
 import org.eclipse.jpt.common.utility.internal.reference.SimpleBooleanReference;
 
 @SuppressWarnings("nls")
-public class SimpleBooleanReferenceTests extends TestCase {
-
+public class SimpleBooleanReferenceTests
+	extends TestCase
+{
 	public SimpleBooleanReferenceTests(String name) {
 		super(name);
 	}
@@ -69,6 +70,55 @@
 		assertTrue(br.getValue());
 	}
 
+	public void testAnd() {
+		SimpleBooleanReference br = new SimpleBooleanReference(true);
+		assertTrue(br.and(true));
+		assertTrue(br.getValue());
+
+		assertFalse(br.and(false));
+		assertFalse(br.getValue());
+
+		assertFalse(br.and(true));
+		assertFalse(br.getValue());
+
+		assertFalse(br.and(false));
+		assertFalse(br.getValue());
+	}
+
+	public void testOr() {
+		SimpleBooleanReference br = new SimpleBooleanReference(true);
+		assertTrue(br.or(true));
+		assertTrue(br.getValue());
+
+		assertTrue(br.or(false));
+		assertTrue(br.getValue());
+
+		assertTrue(br.setValue(false));
+		assertFalse(br.or(false));
+		assertFalse(br.getValue());
+
+		assertTrue(br.or(true));
+		assertTrue(br.getValue());
+	}
+
+	public void testXor() {
+		SimpleBooleanReference br = new SimpleBooleanReference(true);
+		assertFalse(br.xor(true));
+		assertFalse(br.getValue());
+
+		assertFalse(br.setValue(true));
+		assertTrue(br.xor(false));
+		assertTrue(br.getValue());
+
+		assertTrue(br.setValue(false));
+		assertFalse(br.xor(false));
+		assertFalse(br.getValue());
+
+		assertFalse(br.setValue(false));
+		assertTrue(br.xor(true));
+		assertTrue(br.getValue());
+	}
+
 	public void testSetNotBoolean() {
 		SimpleBooleanReference br = new SimpleBooleanReference(false);
 		assertFalse(br.getValue());
@@ -94,6 +144,70 @@
 		assertFalse(br.getValue());
 	}
 
+	public void testCommit() {
+		SimpleBooleanReference br = new SimpleBooleanReference(true);
+		assertTrue(br.commit(false, true));
+		assertFalse(br.getValue());
+
+		assertFalse(br.commit(false, true));
+		assertFalse(br.getValue());
+
+		assertTrue(br.commit(true, false));
+		assertTrue(br.getValue());
+
+		assertFalse(br.commit(true, false));
+		assertTrue(br.getValue());
+
+		assertFalse(br.commit(false, false));
+		assertTrue(br.getValue());
+
+		assertTrue(br.setValue(false));
+		assertFalse(br.commit(true, true));
+		assertFalse(br.getValue());
+	}
+
+	public void testSwap_sameObject() {
+		SimpleBooleanReference br = new SimpleBooleanReference(true);
+		assertTrue(br.swap(br));
+		assertTrue(br.getValue());
+	}
+
+	public void testSwap_sameValues() {
+		SimpleBooleanReference br1 = new SimpleBooleanReference(true);
+		SimpleBooleanReference br2 = new SimpleBooleanReference(true);
+		assertTrue(br1.swap(br2));
+		assertTrue(br1.getValue());
+		assertTrue(br2.getValue());
+	}
+
+	public void testSwap_differentValues1() {
+		SimpleBooleanReference br1 = new SimpleBooleanReference(true);
+		SimpleBooleanReference br2 = new SimpleBooleanReference(false);
+		assertFalse(br1.swap(br2));
+		assertFalse(br1.getValue());
+		assertTrue(br2.getValue());
+	}
+
+	public void testSwap_differentValues2() {
+		SimpleBooleanReference br1 = new SimpleBooleanReference(false);
+		SimpleBooleanReference br2 = new SimpleBooleanReference(true);
+		assertTrue(br1.swap(br2));
+		assertTrue(br1.getValue());
+		assertFalse(br2.getValue());
+	}
+
+	public void testEquals() {
+		SimpleBooleanReference br1 = new SimpleBooleanReference(false);
+		SimpleBooleanReference br2 = new SimpleBooleanReference(true);
+		assertTrue(br1.equals(br1));
+		assertFalse(br1.equals(br2));
+	}
+
+	public void testHashCode() {
+		SimpleBooleanReference br1 = new SimpleBooleanReference(false);
+		assertEquals(br1.hashCode(), br1.hashCode());
+	}
+
 	public void testClone() {
 		SimpleBooleanReference br = new SimpleBooleanReference(true);
 		SimpleBooleanReference clone = br.clone();
@@ -106,5 +220,4 @@
 		br1.setFalse();
 		assertEquals("[false]", br1.toString());
 	}
-
 }
diff --git a/common/tests/org.eclipse.jpt.common.utility.tests/src/org/eclipse/jpt/common/utility/tests/internal/reference/SynchronizedBooleanTests.java b/common/tests/org.eclipse.jpt.common.utility.tests/src/org/eclipse/jpt/common/utility/tests/internal/reference/SynchronizedBooleanTests.java
index c4c9879..16f8d03 100644
--- a/common/tests/org.eclipse.jpt.common.utility.tests/src/org/eclipse/jpt/common/utility/tests/internal/reference/SynchronizedBooleanTests.java
+++ b/common/tests/org.eclipse.jpt.common.utility.tests/src/org/eclipse/jpt/common/utility/tests/internal/reference/SynchronizedBooleanTests.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2007, 2011 Oracle. All rights reserved.
+ * Copyright (c) 2007, 2015 Oracle. All rights reserved.
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0, which accompanies this distribution
  * and is available at http://www.eclipse.org/legal/epl-v10.html.
@@ -9,9 +9,14 @@
  ******************************************************************************/
 package org.eclipse.jpt.common.utility.tests.internal.reference;
 
+import org.eclipse.jpt.common.utility.internal.command.InterruptibleCommandAdapter;
+import org.eclipse.jpt.common.utility.internal.reference.SimpleBooleanReference;
 import org.eclipse.jpt.common.utility.internal.reference.SynchronizedBoolean;
+import org.eclipse.jpt.common.utility.reference.ModifiableBooleanReference;
 import org.eclipse.jpt.common.utility.tests.internal.MultiThreadedTestCase;
+import org.eclipse.jpt.common.utility.tests.internal.TestTools;
 
+@SuppressWarnings("nls")
 public class SynchronizedBooleanTests
 	extends MultiThreadedTestCase
 {
@@ -36,36 +41,50 @@
 
 	public void testGetValue() throws Exception {
 		assertFalse(this.sb.getValue());
+		assertFalse(this.sb.setValue(true));
+		assertTrue(this.sb.getValue());
 	}
 
 	public void testIs() throws Exception {
 		assertTrue(this.sb.is(false));
+		assertFalse(this.sb.is(true));
+		assertFalse(this.sb.setValue(true));
+		assertTrue(this.sb.is(true));
+		assertFalse(this.sb.is(false));
 	}
 
 	public void testIsNot() throws Exception {
 		assertTrue(this.sb.isNot(true));
+		assertFalse(this.sb.setValue(true));
+		assertTrue(this.sb.isNot(false));
 	}
 
 	public void testIsTrue() throws Exception {
 		assertFalse(this.sb.isTrue());
+		assertFalse(this.sb.setValue(true));
+		assertTrue(this.sb.isTrue());
 	}
 
 	public void testIsFalse() throws Exception {
 		assertTrue(this.sb.isFalse());
+		assertFalse(this.sb.setValue(true));
+		assertFalse(this.sb.isFalse());
 	}
 
 	public void testSetValueFalse() throws Exception {
-		this.sb.setValue(false);
+		assertFalse(this.sb.setValue(false));
 		assertFalse(this.sb.getValue());
 		assertFalse(this.sb.isTrue());
 		assertTrue(this.sb.isFalse());
+		assertFalse(this.sb.setValue(false));
 	}
 
 	public void testSetValueTrue() throws Exception {
-		this.sb.setValue(true);
+		assertFalse(this.sb.setValue(true));
 		assertTrue(this.sb.getValue());
 		assertTrue(this.sb.isTrue());
 		assertFalse(this.sb.isFalse());
+		assertTrue(this.sb.setValue(true));
 	}
 
 	public void testFlip() throws Exception {
@@ -173,12 +192,12 @@
 	}
 
 	public void testCommitTrueSuccess() throws Exception {
-		assertTrue(this.sb.commit(false, true));
+		assertTrue(this.sb.commit(true, false));
 		assertTrue(this.sb.getValue());
 	}
 
 	public void testCommitFalseFailure() throws Exception {
-		assertFalse(this.sb.commit(true, false));
+		assertFalse(this.sb.commit(false, true));
 		assertFalse(this.sb.getValue());
 	}
 
@@ -187,23 +206,64 @@
 		assertFalse(this.sb.getValue());
 	}
 
-	public void testSwapSame() throws Exception {
-		assertFalse(this.sb.swap(this.sb));
+	public void testSwapSame1() throws Exception {
+		assertFalse(this.sb.swap((ModifiableBooleanReference) this.sb));
 		assertFalse(this.sb.getValue());
 	}
 
-	public void testSwapSameValue() throws Exception {
-		SynchronizedBoolean sb2 = new SynchronizedBoolean();
+	public void testSwapSameValues1() throws Exception {
+		ModifiableBooleanReference sb2 = new SimpleBooleanReference(false);
 		assertFalse(this.sb.swap(sb2));
 		assertFalse(this.sb.getValue());
 		assertFalse(sb2.getValue());
 	}
 
-	public void testSwapDifferentValue() throws Exception {
+	public void testSwapDifferentValues1() throws Exception {
+		ModifiableBooleanReference sb2 = new SimpleBooleanReference(true);
+		assertTrue(this.sb.swap(sb2));
+		assertTrue(this.sb.getValue());
+		assertFalse(sb2.getValue());
+	}
+
+	public void testSwapSame2() throws Exception {
+		assertFalse(this.sb.swap(this.sb));
+		assertFalse(this.sb.getValue());
+	}
+
+	public void testSwapSameValues2() throws Exception {
+		SynchronizedBoolean sb2 = new SynchronizedBoolean();
+		assertFalse(this.sb.swap(sb2));
+		assertFalse(this.sb.getValue());
+		assertFalse(sb2.getValue());
+
+		assertFalse(sb2.swap(this.sb));
+		assertFalse(this.sb.getValue());
+		assertFalse(sb2.getValue());
+	}
+
+	public void testSwapDifferentValues2() throws Exception {
 		SynchronizedBoolean sb2 = new SynchronizedBoolean(true);
 		assertTrue(this.sb.swap(sb2));
 		assertTrue(this.sb.getValue());
 		assertFalse(sb2.getValue());
+
+		assertTrue(sb2.swap(this.sb));
+		assertFalse(this.sb.getValue());
+		assertTrue(sb2.getValue());
+	}
+
+	public void testSwpSameValues3() throws Exception {
+		ModifiableBooleanReference sb2 = new SynchronizedBoolean();
+		assertFalse(this.sb.swap(sb2));
+		assertFalse(this.sb.getValue());
+		assertFalse(sb2.getValue());
+	}
+
+	public void testSwapDifferentValues3() throws Exception {
+		ModifiableBooleanReference sb2 = new SynchronizedBoolean(true);
+		assertTrue(this.sb.swap(sb2));
+		assertTrue(this.sb.getValue());
+		assertFalse(sb2.getValue());
 	}
 
 	public void testGetMutexThis() throws Exception {
@@ -220,6 +280,16 @@
 	 * t2 will wait indefinitely until t1 sets the value to true
 	 */
 	public void testWaitUntilTrue() throws Exception {
+		this.verifyWaitUntilTrue(-1);  // explicit indefinite wait
+		// no timeout occurs...
+		assertFalse(this.timeoutOccurred);
+		// ...and the value should be set to true by t2
+		assertTrue(this.sb.getValue());
+		// make a reasonable guess about how long t2 took
+		assertTrue(this.calculateElapsedTime() > TICK);
+	}
+
+	public void testWaitUntilTrue2() throws Exception {
 		this.verifyWaitUntilTrue(0);  // 0 = indefinite wait
 		// no timeout occurs...
 		assertFalse(this.timeoutOccurred);
@@ -242,14 +312,225 @@
 		assertTrue(this.calculateElapsedTime() < THREE_TICKS);
 	}
 
+	/**
+	 * t2 will NOT time out waiting for t1 to set the value to true
+	 */
+	public void testWaitUntilTrueTimeout2() throws Exception {
+		this.verifyWaitUntilTrue(THREE_TICKS);
+		// no timeout occurs...
+		assertFalse(this.timeoutOccurred);
+		// ...and the value should be set to true by t2
+		assertTrue(this.sb.getValue());
+		// make a reasonable guess about how long t2 took
+		assertTrue(this.calculateElapsedTime() >= TWO_TICKS);
+	}
+
 	private void verifyWaitUntilTrue(long t2Timeout) throws Exception {
+		this.sb.setFalse();
 		this.executeThreads(this.buildSetTrueCommand(), this.buildWaitUntilTrueCommand(t2Timeout));
 	}
 
+	private Command buildWaitUntilTrueCommand(final long timeout) {
+		return new Command() {
+			public void execute(SynchronizedBoolean syncBool) throws InterruptedException {
+				SynchronizedBooleanTests.this.startTime = System.currentTimeMillis();
+				SynchronizedBooleanTests.this.timeoutOccurred = this.timeoutOccurred(syncBool);
+				SynchronizedBooleanTests.this.endTime = System.currentTimeMillis();
+			}
+			private boolean timeoutOccurred(SynchronizedBoolean syncBool) throws InterruptedException {
+				if (timeout < 0) {
+					syncBool.waitUntilTrue();
+					return false;
+				}
+				return ! syncBool.waitUntilTrue(timeout);
+			}
+		};
+	}
+
+	/**
+	 * t2 will wait indefinitely until t1 sets the value to false
+	 */
+	public void testWaitUntilFalse() throws Exception {
+		this.verifyWaitUntilFalse(-1);  // explicit indefinite wait
+		// no timeout occurs...
+		assertFalse(this.timeoutOccurred);
+		// ...and the value should be set to false by t2
+		assertFalse(this.sb.getValue());
+		// make a reasonable guess about how long t2 took
+		assertTrue(this.calculateElapsedTime() > TICK);
+	}
+
+	public void testWaitUntilFalse2() throws Exception {
+		this.verifyWaitUntilFalse(0);  // 0 = indefinite wait
+		// no timeout occurs...
+		assertFalse(this.timeoutOccurred);
+		// ...and the value should be set to false by t2
+		assertFalse(this.sb.getValue());
+		// make a reasonable guess about how long t2 took
+		assertTrue(this.calculateElapsedTime() > TICK);
+	}
+
+	/**
+	 * t2 will time out waiting for t1 to set the value to false
+	 */
+	public void testWaitUntilFalseTimeout() throws Exception {
+		this.verifyWaitUntilFalse(TICK);
+		// timeout occurs...
+		assertTrue(this.timeoutOccurred);
+		// ...and the value will eventually be set to false by t1
+		assertFalse(this.sb.getValue());
+		// make a reasonable guess about how long t2 took
+		assertTrue(this.calculateElapsedTime() < THREE_TICKS);
+	}
+
+	/**
+	 * t2 will NOT time out waiting for t1 to set the value to false
+	 */
+	public void testWaitUntilFalseTimeout2() throws Exception {
+		this.verifyWaitUntilFalse(THREE_TICKS);
+		// no timeout occurs...
+		assertFalse(this.timeoutOccurred);
+		// ...and the value should be set to false by t2
+		assertFalse(this.sb.getValue());
+		// make a reasonable guess about how long t2 took
+		assertTrue(this.calculateElapsedTime() >= TWO_TICKS);
+	}
+
+	private void verifyWaitUntilFalse(long t2Timeout) throws Exception {
+		this.sb.setTrue();
+		this.executeThreads(this.buildSetFalseCommand(), this.buildWaitUntilFalseCommand(t2Timeout));
+	}
+
+	private Command buildWaitUntilFalseCommand(final long timeout) {
+		return new Command() {
+			public void execute(SynchronizedBoolean syncBool) throws InterruptedException {
+				SynchronizedBooleanTests.this.startTime = System.currentTimeMillis();
+				SynchronizedBooleanTests.this.timeoutOccurred = this.timeoutOccurred(syncBool);
+				SynchronizedBooleanTests.this.endTime = System.currentTimeMillis();
+			}
+			private boolean timeoutOccurred(SynchronizedBoolean syncBool) throws InterruptedException {
+				if (timeout < 0) {
+					syncBool.waitUntilFalse();
+					return false;
+				}
+				return ! syncBool.waitUntilFalse(timeout);
+			}
+		};
+	}
+
+	public void testWaitUntilValueIsNotTrue() throws Exception {
+		this.sb.waitUntilValueIsNot(true);
+		assertFalse(this.sb.getValue());
+	}
+
+	public void testWaitUntilValueIsNotFalse() throws Exception {
+		this.sb.setTrue();
+		this.sb.waitUntilValueIsNot(false);
+		assertTrue(this.sb.getValue());
+	}
+
+	public void testWaitUntilValueIsNotTrueTimeout() throws Exception {
+		this.sb.waitUntilValueIsNot(true, 500);
+		assertFalse(this.sb.getValue());
+	}
+
+	public void testWaitUntilValueIsNotFalseTimeout() throws Exception {
+		this.sb.setTrue();
+		this.sb.waitUntilValueIsNot(false, 500);
+		assertTrue(this.sb.getValue());
+	}
+
+	/**
+	 * t2 will wait indefinitely until t1 sets the value to true
+	 */
+	public void testWaitToSetTrue() throws Exception {
+		this.verifyWaitToSetTrue(-1);  // explicit indefinite wait
+		// no timeout occurs...
+		assertFalse(this.timeoutOccurred);
+		// ...and the value should be set to true by t2
+		assertTrue(this.sb.getValue());
+		// make a reasonable guess about how long t2 took
+		assertTrue(this.calculateElapsedTime() > TICK);
+	}
+
+	/**
+	 * t2 will wait indefinitely until t1 sets the value to true
+	 */
+	public void testWaitToSetTrue2() throws Exception {
+		this.verifyWaitToSetTrue(0);  // 0 = indefinite wait
+		// no timeout occurs...
+		assertFalse(this.timeoutOccurred);
+		// ...and the value should be set to true by t2
+		assertTrue(this.sb.getValue());
+		// make a reasonable guess about how long t2 took
+		assertTrue(this.calculateElapsedTime() > TICK);
+	}
+
+	/**
+	 * t2 will time out waiting for t1 to set the value to true
+	 */
+	public void testWaitToSetTrueTimeout() throws Exception {
+		this.verifyWaitToSetTrue(TICK);
+		// timeout occurs...
+		assertTrue(this.timeoutOccurred);
+		// ...and the value will eventually be set to false by t1
+		assertFalse(this.sb.getValue());
+		// make a reasonable guess about how long t2 took
+		assertTrue(this.calculateElapsedTime() < THREE_TICKS);
+	}
+
+	/**
+	 * t2 will NOT time out waiting for t1 to set the value to true
+	 */
+	public void testWaitToSetTrueTimeout2() throws Exception {
+		this.verifyWaitUntilTrue(THREE_TICKS);
+		// no timeout occurs...
+		assertFalse(this.timeoutOccurred);
+		// ...and the value should be set to true by t2
+		assertTrue(this.sb.getValue());
+		// make a reasonable guess about how long t2 took
+		assertTrue(this.calculateElapsedTime() >= TWO_TICKS);
+	}
+
+	private void verifyWaitToSetTrue(long t2Timeout) throws Exception {
+		this.sb.setTrue();
+		this.executeThreads(this.buildSetFalseCommand(), this.buildWaitToSetTrueCommand(t2Timeout));
+	}
+
+	private Command buildWaitToSetTrueCommand(final long timeout) {
+		return new Command() {
+			public void execute(SynchronizedBoolean syncBool) throws InterruptedException {
+				SynchronizedBooleanTests.this.startTime = System.currentTimeMillis();
+				SynchronizedBooleanTests.this.timeoutOccurred = this.timeoutOccurred( syncBool);
+				SynchronizedBooleanTests.this.endTime = System.currentTimeMillis();
+			}
+			private boolean timeoutOccurred(SynchronizedBoolean syncBool) throws InterruptedException {
+				if (timeout < 0) {
+					syncBool.waitToSetTrue();
+					return false;
+				}
+				return ! syncBool.waitToSetTrue(timeout);
+			}
+		};
+	}
+
 	/**
 	 * t2 will wait indefinitely until t1 sets the value to false
 	 */
 	public void testWaitToSetFalse() throws Exception {
+		this.verifyWaitToSetFalse(-1);  // explicit indefinite wait
+		// no timeout occurs...
+		assertFalse(this.timeoutOccurred);
+		// ...and the value should be set to false by t2
+		assertFalse(this.sb.getValue());
+		// make a reasonable guess about how long t2 took
+		assertTrue(this.calculateElapsedTime() > TICK);
+	}
+
+	/**
+	 * t2 will wait indefinitely until t1 sets the value to false
+	 */
+	public void testWaitToSetFalse2() throws Exception {
 		this.verifyWaitToSetFalse(0);  // 0 = indefinite wait
 		// no timeout occurs...
 		assertFalse(this.timeoutOccurred);
@@ -272,12 +553,190 @@
 		assertTrue(this.calculateElapsedTime() < THREE_TICKS);
 	}
 
+	/**
+	 * t2 will NOT time out waiting for t1 to set the value to false
+	 */
+	public void testWaitToSetFalseTimeout2() throws Exception {
+		this.verifyWaitUntilFalse(THREE_TICKS);
+		// no timeout occurs...
+		assertFalse(this.timeoutOccurred);
+		// ...and the value should be set to false by t2
+		assertFalse(this.sb.getValue());
+		// make a reasonable guess about how long t2 took
+		assertTrue(this.calculateElapsedTime() >= TWO_TICKS);
+	}
+
 	private void verifyWaitToSetFalse(long t2Timeout) throws Exception {
+		this.sb.setFalse();
 		this.executeThreads(this.buildSetTrueCommand(), this.buildWaitToSetFalseCommand(t2Timeout));
 	}
 
-	private void executeThreads(Command t1Command, Command t2Command) throws Exception {
+	private Command buildWaitToSetFalseCommand(final long timeout) {
+		return new Command() {
+			public void execute(SynchronizedBoolean syncBool) throws InterruptedException {
+				SynchronizedBooleanTests.this.startTime = System.currentTimeMillis();
+				SynchronizedBooleanTests.this.timeoutOccurred = this.timeoutOccurred( syncBool);
+				SynchronizedBooleanTests.this.endTime = System.currentTimeMillis();
+			}
+			private boolean timeoutOccurred(SynchronizedBoolean syncBool) throws InterruptedException {
+				if (timeout < 0) {
+					syncBool.waitToSetFalse();
+					return false;
+				}
+				return ! syncBool.waitToSetFalse(timeout);
+			}
+		};
+	}
+
+	public void testWaitToSetValueNotTrue() throws Exception {
+		this.sb.waitToSetValueNot(false);
+		assertTrue(this.sb.getValue());
+	}
+
+	public void testWaitToSetValueNotFalse() throws Exception {
+		this.sb.setTrue();
+		this.sb.waitToSetValueNot(true);
+		assertFalse(this.sb.getValue());
+	}
+
+	public void testWaitToSetValueNotTrueTimeout() throws Exception {
+		this.sb.waitToSetValueNot(false, 500);
+		assertTrue(this.sb.getValue());
+	}
+
+	public void testWaitToSetValueNotFalseTimeout() throws Exception {
+		this.sb.setTrue();
+		this.sb.waitToSetValueNot(true, 500);
+		assertFalse(this.sb.getValue());
+	}
+
+	public void testWhenTrueExecute() throws Exception {
+		this.sb.setTrue();
+		final ModifiableBooleanReference done = new SimpleBooleanReference(false);
+		this.sb.whenTrueExecute(new InterruptibleCommandAdapter() {
+			@Override
+			public void execute() throws InterruptedException {
+				done.setTrue();
+			}
+		});
+		assertTrue(done.getValue());
+	}
+
+	public void testWhenFalseExecute() throws Exception {
 		this.sb.setFalse();
+		final ModifiableBooleanReference done = new SimpleBooleanReference(false);
+		this.sb.whenFalseExecute(new InterruptibleCommandAdapter() {
+			@Override
+			public void execute() throws InterruptedException {
+				done.setTrue();
+			}
+		});
+		assertTrue(done.getValue());
+	}
+
+	public void testWhenValueIsNotTrue() throws Exception {
+		this.sb.setFalse();
+		final ModifiableBooleanReference done = new SimpleBooleanReference(false);
+		this.sb.whenValueIsNot(true, new InterruptibleCommandAdapter() {
+			@Override
+			public void execute() throws InterruptedException {
+				done.setTrue();
+			}
+		});
+		assertTrue(done.getValue());
+	}
+
+	public void testWhenValueIsNotFalse() throws Exception {
+		this.sb.setTrue();
+		final ModifiableBooleanReference done = new SimpleBooleanReference(false);
+		this.sb.whenValueIsNot(false, new InterruptibleCommandAdapter() {
+			@Override
+			public void execute() throws InterruptedException {
+				done.setTrue();
+			}
+		});
+		assertTrue(done.getValue());
+	}
+
+	public void testWhenTrueExecuteTimeout() throws Exception {
+		this.sb.setTrue();
+		final ModifiableBooleanReference done = new SimpleBooleanReference(false);
+		this.sb.whenTrueExecute(new InterruptibleCommandAdapter() {
+			@Override
+			public void execute() throws InterruptedException {
+				done.setTrue();
+			}
+		}, 500);
+		assertTrue(done.getValue());
+	}
+
+	public void testWhenFalseExecuteTimeout() throws Exception {
+		this.sb.setFalse();
+		final ModifiableBooleanReference done = new SimpleBooleanReference(false);
+		this.sb.whenFalseExecute(new InterruptibleCommandAdapter() {
+			@Override
+			public void execute() throws InterruptedException {
+				done.setTrue();
+			}
+		}, 500);
+		assertTrue(done.getValue());
+	}
+
+	public void testWhenValueIsNotTrueTimeout() throws Exception {
+		this.sb.setFalse();
+		final ModifiableBooleanReference done = new SimpleBooleanReference(false);
+		this.sb.whenValueIsNot(true, new InterruptibleCommandAdapter() {
+			@Override
+			public void execute() throws InterruptedException {
+				done.setTrue();
+			}
+		}, 500);
+		assertTrue(done.getValue());
+	}
+
+	public void testWhenValueIsNotFalseTimeout() throws Exception {
+		this.sb.setTrue();
+		final ModifiableBooleanReference done = new SimpleBooleanReference(false);
+		this.sb.whenValueIsNot(false, new InterruptibleCommandAdapter() {
+			@Override
+			public void execute() throws InterruptedException {
+				done.setTrue();
+			}
+		}, 500);
+		assertTrue(done.getValue());
+	}
+
+	public void testWhenValueIsNotFalseTimeout2() throws Exception {
+		this.sb.setFalse();
+		final ModifiableBooleanReference done = new SimpleBooleanReference(false);
+		this.sb.whenValueIsNot(false, new InterruptibleCommandAdapter() {
+			@Override
+			public void execute() throws InterruptedException {
+				done.setTrue();
+			}
+		}, 500);
+		assertFalse(done.getValue()); // timeout
+	}
+
+	public void testExecute() throws Exception {
+		final ModifiableBooleanReference done = new SimpleBooleanReference(false);
+		this.sb.execute(new InterruptibleCommandAdapter() {
+			@Override
+			public void execute() throws InterruptedException {
+				done.setTrue();
+			}
+		});
+		assertTrue(done.getValue());
+	}
+
+	public void testSerialization() throws Exception {
+		this.sb.setTrue();
+		SynchronizedBoolean clone = TestTools.serialize(this.sb);
+		assertNotSame(this.sb, clone);
+		assertTrue(clone.getValue());
+	}
+
+	private void executeThreads(Command t1Command, Command t2Command) throws Exception {
 		Runnable r1 = this.buildRunnable(t1Command, this.sb, TWO_TICKS);
 		Runnable r2 = this.buildRunnable(t2Command, this.sb, 0);
 		Thread t1 = this.buildThread(r1);
@@ -296,22 +755,10 @@
 		};
 	}
 
-	private Command buildWaitUntilTrueCommand(final long timeout) {
+	private Command buildSetFalseCommand() {
 		return new Command() {
-			public void execute(SynchronizedBoolean syncBool) throws InterruptedException {
-				SynchronizedBooleanTests.this.startTime = System.currentTimeMillis();
-				SynchronizedBooleanTests.this.timeoutOccurred = ! syncBool.waitUntilTrue(timeout);
-				SynchronizedBooleanTests.this.endTime = System.currentTimeMillis();
-			}
-		};
-	}
-
-	private Command buildWaitToSetFalseCommand(final long timeout) {
-		return new Command() {
-			public void execute(SynchronizedBoolean syncBool) throws InterruptedException {
-				SynchronizedBooleanTests.this.startTime = System.currentTimeMillis();
-				SynchronizedBooleanTests.this.timeoutOccurred =  ! syncBool.waitToSetFalse(timeout);
-				SynchronizedBooleanTests.this.endTime = System.currentTimeMillis();
+			public void execute(SynchronizedBoolean syncBool) {
+				syncBool.setFalse();
 			}
 		};
 	}
@@ -339,4 +786,27 @@
 		void execute(SynchronizedBoolean syncBool) throws InterruptedException;
 	}
 
+
+	// ********** standard methods **********
+
+	public void testEquals() {
+		SynchronizedBoolean sb2 = new SynchronizedBoolean(true);
+		assertTrue(this.sb.equals(this.sb));
+		assertFalse(this.sb.equals(sb2));
+	}
+
+	public void testHashCode() {
+		assertEquals(this.sb.hashCode(), this.sb.hashCode());
+	}
+
+	public void testClone() {
+		SynchronizedBoolean clone = this.sb.clone();
+		assertFalse(clone.getValue());
+	}
+
+	public void testToString() {
+		assertEquals("[false]", this.sb.toString());
+		assertFalse(this.sb.setTrue());
+		assertEquals("[true]", this.sb.toString());
+	}
 }