diff options
author | Kjetil Ørbekk <kjetil.orbekk@gmail.com> | 2012-02-28 14:17:17 +0100 |
---|---|---|
committer | Kjetil Ørbekk <kjetil.orbekk@gmail.com> | 2012-02-28 14:17:17 +0100 |
commit | 7be826174d1837629c0ad33c7b6d4dfb3bc63a47 (patch) | |
tree | 133fa0b734f7b83906125e6e6081dbc3e7361449 | |
parent | 95f52f078e618e8c2cc0ccfd0b995051fe9bb5a7 (diff) |
Add VariableUpdaterTask.
VariableUpdaterTask updates a variable countinously.
-rw-r--r-- | same/src/main/java/com/orbekk/same/VariableUpdaterTask.java | 63 | ||||
-rw-r--r-- | same/src/test/java/com/orbekk/same/VariableUpdaterTaskTest.java | 62 |
2 files changed, 125 insertions, 0 deletions
diff --git a/same/src/main/java/com/orbekk/same/VariableUpdaterTask.java b/same/src/main/java/com/orbekk/same/VariableUpdaterTask.java new file mode 100644 index 0000000..44f63fe --- /dev/null +++ b/same/src/main/java/com/orbekk/same/VariableUpdaterTask.java @@ -0,0 +1,63 @@ +package com.orbekk.same; + +import java.util.concurrent.atomic.AtomicBoolean; + +/** Updates a variable on-demand. + */ +public class VariableUpdaterTask<T> extends Thread + implements Variable.OnChangeListener<T> { + private Variable<T> variable; + private T newValue; + private AtomicBoolean hasNewValue = new AtomicBoolean(false); + private AtomicBoolean isReady = new AtomicBoolean(true); + + public VariableUpdaterTask(Variable<T> variable) { + this.variable = variable; + } + + public synchronized void set(T newValue) { + this.newValue = newValue; + hasNewValue.set(true); + notifyAll(); + } + + /** Update the variable once. */ + public void performWork() { + boolean shouldDoWork = false; + synchronized(this) { + shouldDoWork = hasNewValue.get() && isReady.get(); + hasNewValue.set(false); + isReady.set(false); + } + if (shouldDoWork) { + variable.set(newValue); + } + } + + private synchronized void waitFor(AtomicBoolean v) { + while(!v.get()) { + try { + wait(); + } catch (InterruptedException e) { + return; + } + } + } + + public void run() { + while (true) { + waitFor(isReady); + waitFor(hasNewValue); + if (Thread.interrupted()) { + break; + } + performWork(); + } + } + + @Override + public synchronized void valueChanged(Variable<T> unused) { + isReady.set(true); + notifyAll(); + } +}
\ No newline at end of file diff --git a/same/src/test/java/com/orbekk/same/VariableUpdaterTaskTest.java b/same/src/test/java/com/orbekk/same/VariableUpdaterTaskTest.java new file mode 100644 index 0000000..3ecf444 --- /dev/null +++ b/same/src/test/java/com/orbekk/same/VariableUpdaterTaskTest.java @@ -0,0 +1,62 @@ +package com.orbekk.same; + +import static org.junit.Assert.*; + +import org.junit.Before; +import org.junit.Test; +import static org.mockito.Mockito.*; + +public class VariableUpdaterTaskTest { + Variable<String> v; + VariableUpdaterTask<String> updater; + + @Before public void setUp() { + v = mock(Variable.class); + updater = new VariableUpdaterTask<String>(v); + } + + @Test + public void updatesValue() { + updater.set("FirstValue"); + updater.performWork(); + verify(v).set("FirstValue"); + } + + @Test + public void noUpdateIfNotSet() { + updater.set("FirstValue"); + updater.performWork(); + reset(v); + updater.performWork(); + verify(v, never()).set(anyString()); + } + + @Test + public void noUpdateIfNotReady() { + updater.set("FirstValue"); + updater.performWork(); + reset(v); + updater.set("SecondValue"); + updater.performWork(); + verify(v, never()).set(anyString()); + } + + @Test + public void updatesWhenReady() { + updater.set("Value1"); + updater.performWork(); + reset(v); + updater.valueChanged(null); + updater.set("Value2"); + updater.performWork(); + verify(v).set("Value2"); + } + + @Test + public void choosesLastUpdate() { + updater.set("FirstValue"); + updater.set("SecondValue"); + updater.performWork(); + verify(v).set("SecondValue"); + } +} |