summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKjetil Ørbekk <kjetil.orbekk@gmail.com>2012-02-28 14:17:17 +0100
committerKjetil Ørbekk <kjetil.orbekk@gmail.com>2012-02-28 14:17:17 +0100
commit7be826174d1837629c0ad33c7b6d4dfb3bc63a47 (patch)
tree133fa0b734f7b83906125e6e6081dbc3e7361449
parent95f52f078e618e8c2cc0ccfd0b995051fe9bb5a7 (diff)
Add VariableUpdaterTask.
VariableUpdaterTask updates a variable countinously.
-rw-r--r--same/src/main/java/com/orbekk/same/VariableUpdaterTask.java63
-rw-r--r--same/src/test/java/com/orbekk/same/VariableUpdaterTaskTest.java62
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");
+ }
+}