1 /*
2  * Written by Doug Lea with assistance from members of JCP JSR-166
3  * Expert Group and released to the public domain, as explained at
4  * http://creativecommons.org/publicdomain/zero/1.0/
5  */
6 
7 package java.util.concurrent.atomic;
8 
9 import java.util.function.BinaryOperator;
10 import java.util.function.UnaryOperator;
11 
12 /**
13  * An object reference that may be updated atomically. See the {@link
14  * java.util.concurrent.atomic} package specification for description
15  * of the properties of atomic variables.
16  * @since 1.5
17  * @author Doug Lea
18  * @param <V> The type of object referred to by this reference
19  */
20 public class AtomicReference<V> implements java.io.Serializable {
21     private static final long serialVersionUID = -1848883965231344442L;
22 
23     private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
24     private static final long VALUE;
25 
26     static {
27         try {
28             VALUE = U.objectFieldOffset
29                 (AtomicReference.class.getDeclaredField("value"));
30         } catch (ReflectiveOperationException e) {
31             throw new Error(e);
32         }
33     }
34 
35     private volatile V value;
36 
37     /**
38      * Creates a new AtomicReference with the given initial value.
39      *
40      * @param initialValue the initial value
41      */
AtomicReference(V initialValue)42     public AtomicReference(V initialValue) {
43         value = initialValue;
44     }
45 
46     /**
47      * Creates a new AtomicReference with null initial value.
48      */
AtomicReference()49     public AtomicReference() {
50     }
51 
52     /**
53      * Gets the current value.
54      *
55      * @return the current value
56      */
get()57     public final V get() {
58         return value;
59     }
60 
61     /**
62      * Sets to the given value.
63      *
64      * @param newValue the new value
65      */
set(V newValue)66     public final void set(V newValue) {
67         value = newValue;
68     }
69 
70     /**
71      * Eventually sets to the given value.
72      *
73      * @param newValue the new value
74      * @since 1.6
75      */
lazySet(V newValue)76     public final void lazySet(V newValue) {
77         U.putOrderedObject(this, VALUE, newValue);
78     }
79 
80     /**
81      * Atomically sets the value to the given updated value
82      * if the current value {@code ==} the expected value.
83      * @param expect the expected value
84      * @param update the new value
85      * @return {@code true} if successful. False return indicates that
86      * the actual value was not equal to the expected value.
87      */
compareAndSet(V expect, V update)88     public final boolean compareAndSet(V expect, V update) {
89         return U.compareAndSwapObject(this, VALUE, expect, update);
90     }
91 
92     /**
93      * Atomically sets the value to the given updated value
94      * if the current value {@code ==} the expected value.
95      *
96      * <p><a href="package-summary.html#weakCompareAndSet">May fail
97      * spuriously and does not provide ordering guarantees</a>, so is
98      * only rarely an appropriate alternative to {@code compareAndSet}.
99      *
100      * @param expect the expected value
101      * @param update the new value
102      * @return {@code true} if successful
103      */
weakCompareAndSet(V expect, V update)104     public final boolean weakCompareAndSet(V expect, V update) {
105         return U.compareAndSwapObject(this, VALUE, expect, update);
106     }
107 
108     /**
109      * Atomically sets to the given value and returns the old value.
110      *
111      * @param newValue the new value
112      * @return the previous value
113      */
114     @SuppressWarnings("unchecked")
getAndSet(V newValue)115     public final V getAndSet(V newValue) {
116         return (V)U.getAndSetObject(this, VALUE, newValue);
117     }
118 
119     /**
120      * Atomically updates the current value with the results of
121      * applying the given function, returning the previous value. The
122      * function should be side-effect-free, since it may be re-applied
123      * when attempted updates fail due to contention among threads.
124      *
125      * @param updateFunction a side-effect-free function
126      * @return the previous value
127      * @since 1.8
128      */
getAndUpdate(UnaryOperator<V> updateFunction)129     public final V getAndUpdate(UnaryOperator<V> updateFunction) {
130         V prev, next;
131         do {
132             prev = get();
133             next = updateFunction.apply(prev);
134         } while (!compareAndSet(prev, next));
135         return prev;
136     }
137 
138     /**
139      * Atomically updates the current value with the results of
140      * applying the given function, returning the updated value. The
141      * function should be side-effect-free, since it may be re-applied
142      * when attempted updates fail due to contention among threads.
143      *
144      * @param updateFunction a side-effect-free function
145      * @return the updated value
146      * @since 1.8
147      */
updateAndGet(UnaryOperator<V> updateFunction)148     public final V updateAndGet(UnaryOperator<V> updateFunction) {
149         V prev, next;
150         do {
151             prev = get();
152             next = updateFunction.apply(prev);
153         } while (!compareAndSet(prev, next));
154         return next;
155     }
156 
157     /**
158      * Atomically updates the current value with the results of
159      * applying the given function to the current and given values,
160      * returning the previous value. The function should be
161      * side-effect-free, since it may be re-applied when attempted
162      * updates fail due to contention among threads.  The function
163      * is applied with the current value as its first argument,
164      * and the given update as the second argument.
165      *
166      * @param x the update value
167      * @param accumulatorFunction a side-effect-free function of two arguments
168      * @return the previous value
169      * @since 1.8
170      */
getAndAccumulate(V x, BinaryOperator<V> accumulatorFunction)171     public final V getAndAccumulate(V x,
172                                     BinaryOperator<V> accumulatorFunction) {
173         V prev, next;
174         do {
175             prev = get();
176             next = accumulatorFunction.apply(prev, x);
177         } while (!compareAndSet(prev, next));
178         return prev;
179     }
180 
181     /**
182      * Atomically updates the current value with the results of
183      * applying the given function to the current and given values,
184      * returning the updated value. The function should be
185      * side-effect-free, since it may be re-applied when attempted
186      * updates fail due to contention among threads.  The function
187      * is applied with the current value as its first argument,
188      * and the given update as the second argument.
189      *
190      * @param x the update value
191      * @param accumulatorFunction a side-effect-free function of two arguments
192      * @return the updated value
193      * @since 1.8
194      */
accumulateAndGet(V x, BinaryOperator<V> accumulatorFunction)195     public final V accumulateAndGet(V x,
196                                     BinaryOperator<V> accumulatorFunction) {
197         V prev, next;
198         do {
199             prev = get();
200             next = accumulatorFunction.apply(prev, x);
201         } while (!compareAndSet(prev, next));
202         return next;
203     }
204 
205     /**
206      * Returns the String representation of the current value.
207      * @return the String representation of the current value
208      */
toString()209     public String toString() {
210         return String.valueOf(get());
211     }
212 
213 }
214