1 package net.mograsim.logic.model.util;
3 import java.lang.invoke.VarHandle;
4 import java.util.ArrayList;
6 import java.util.concurrent.atomic.AtomicReference;
7 import java.util.function.Consumer;
8 import java.util.function.UnaryOperator;
10 public class ObservableAtomicReference<V>
12 private final AtomicReference<V> ref;
14 private final List<Consumer<ObservableAtomicReference<V>>> observers;
16 public ObservableAtomicReference()
18 ref = new AtomicReference<>();
19 observers = new ArrayList<>();
22 public ObservableAtomicReference(V initialValue)
24 ref = new AtomicReference<>(initialValue);
25 observers = new ArrayList<>();
29 * Returns the current value, with memory effects as specified by {@link VarHandle#getVolatile}.
31 * @return the current value
39 * Sets the value to {@code newValue}, with memory effects as specified by {@link VarHandle#setVolatile}.
41 * @param newValue the new value
43 public void set(V newValue)
50 * Atomically sets the value to {@code newValue} and returns the old value, with memory effects as specified by
51 * {@link VarHandle#getAndSet}.
53 * @param newValue the new value
54 * @return the previous value
56 public V getAndSet(V newValue)
58 V oldValue = ref.getAndSet(newValue);
64 * Atomically updates (with memory effects as specified by {@link VarHandle#compareAndSet}) the current value with the results of
65 * applying the given function, returning the updated value. The function should be side-effect-free, since it may be re-applied when
66 * attempted updates fail due to contention among threads.
68 * @param updateFunction a side-effect-free function
69 * @return the updated value
71 public V updateAndGet(UnaryOperator<V> updateFunction)
73 V updatedValue = ref.updateAndGet(updateFunction);
78 public void addObserver(Consumer<ObservableAtomicReference<V>> obs)
83 public void removeObserver(Consumer<ObservableAtomicReference<V>> obs)
88 private void callObservers()
90 observers.forEach(o -> o.accept(this));