1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * 4 * This code is free software; you can redistribute it and/or modify it 5 * under the terms of the GNU General Public License version 2 only, as 6 * published by the Free Software Foundation. Oracle designates this 7 * particular file as subject to the "Classpath" exception as provided 8 * by Oracle in the LICENSE file that accompanied this code. 9 * 10 * This code is distributed in the hope that it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 * version 2 for more details (a copy is included in the LICENSE file that 14 * accompanied this code). 15 * 16 * You should have received a copy of the GNU General Public License version 17 * 2 along with this work; if not, write to the Free Software Foundation, 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 * 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 * or visit www.oracle.com if you need additional information or have any 22 * questions. 23 */ 24 25 /* 26 * This file is available under and governed by the GNU General Public 27 * License version 2 only, as published by the Free Software Foundation. 28 * However, the following notice accompanied the original version of this 29 * file: 30 * 31 * Written by Doug Lea with assistance from members of JCP JSR-166 32 * Expert Group and released to the public domain, as explained at 33 * http://creativecommons.org/publicdomain/zero/1.0/ 34 */ 35 36 package java.util.concurrent.atomic; 37 import java.util.function.UnaryOperator; 38 import java.util.function.BinaryOperator; 39 import sun.misc.Unsafe; 40 41 /** 42 * An object reference that may be updated atomically. See the {@link 43 * java.util.concurrent.atomic} package specification for description 44 * of the properties of atomic variables. 45 * @since 1.5 46 * @author Doug Lea 47 * @param <V> The type of object referred to by this reference 48 */ 49 public class AtomicReference<V> implements java.io.Serializable { 50 private static final long serialVersionUID = -1848883965231344442L; 51 52 private static final Unsafe unsafe = Unsafe.getUnsafe(); 53 private static final long valueOffset; 54 55 static { 56 try { 57 valueOffset = unsafe.objectFieldOffset 58 (AtomicReference.class.getDeclaredField("value")); 59 } catch (Exception ex) { throw new Error(ex); } 60 } 61 62 private volatile V value; 63 64 /** 65 * Creates a new AtomicReference with the given initial value. 66 * 67 * @param initialValue the initial value 68 */ 69 public AtomicReference(V initialValue) { 70 value = initialValue; 71 } 72 73 /** 74 * Creates a new AtomicReference with null initial value. 75 */ 76 public AtomicReference() { 77 } 78 79 /** 80 * Gets the current value. 81 * 82 * @return the current value 83 */ 84 public final V get() { 85 return value; 86 } 87 88 /** 89 * Sets to the given value. 90 * 91 * @param newValue the new value 92 */ 93 public final void set(V newValue) { 94 value = newValue; 95 } 96 97 /** 98 * Eventually sets to the given value. 99 * 100 * @param newValue the new value 101 * @since 1.6 102 */ 103 public final void lazySet(V newValue) { 104 unsafe.putOrderedObject(this, valueOffset, newValue); 105 } 106 107 /** 108 * Atomically sets the value to the given updated value 109 * if the current value {@code ==} the expected value. 110 * @param expect the expected value 111 * @param update the new value 112 * @return true if successful. False return indicates that 113 * the actual value was not equal to the expected value. 114 */ 115 public final boolean compareAndSet(V expect, V update) { 116 return unsafe.compareAndSwapObject(this, valueOffset, expect, update); 117 } 118 119 /** 120 * Atomically sets the value to the given updated value 121 * if the current value {@code ==} the expected value. 122 * 123 * <p>May <a href="package-summary.html#Spurious">fail spuriously</a> 124 * and does not provide ordering guarantees, so is only rarely an 125 * appropriate alternative to {@code compareAndSet}. 126 * 127 * @param expect the expected value 128 * @param update the new value 129 * @return true if successful 130 */ 131 public final boolean weakCompareAndSet(V expect, V update) { 132 return unsafe.compareAndSwapObject(this, valueOffset, expect, update); 133 } 134 135 /** 136 * Atomically sets to the given value and returns the old value. 137 * 138 * @param newValue the new value 139 * @return the previous value 140 */ 141 @SuppressWarnings("unchecked") 142 public final V getAndSet(V newValue) { 143 return (V)unsafe.getAndSetObject(this, valueOffset, newValue); 144 } 145 146 /** 147 * Atomically updates the current value with the results of 148 * applying the given function. The function should be 149 * side-effect-free, since it may be re-applied when attempted 150 * updates fail due to contention among threads. 151 * 152 * @param updateFunction a side-effect-free function 153 * @return the previous value 154 * @since 1.8 155 */ 156 public final V getAndUpdate(UnaryOperator<V> updateFunction) { 157 V prev, next; 158 do { 159 prev = get(); 160 next = updateFunction.operate(prev); 161 } while (!compareAndSet(prev, next)); 162 return prev; 163 } 164 165 /** 166 * Atomically updates the current value with the results of 167 * applying the given function. The function should be 168 * side-effect-free, since it may be re-applied when attempted 169 * updates fail due to contention among threads. 170 * 171 * @param updateFunction a side-effect-free function 172 * @return the updated value 173 * @since 1.8 174 */ 175 public final V updateAndGet(UnaryOperator<V> updateFunction) { 176 V prev, next; 177 do { 178 prev = get(); 179 next = updateFunction.operate(prev); 180 } while (!compareAndSet(prev, next)); 181 return next; 182 } 183 184 /** 185 * Atomically updates the current value with the results of 186 * applying the given function to the current and given values. 187 * The function should be side-effect-free, since it may be 188 * re-applied when attempted updates fail due to contention among 189 * threads. The function is applied with the current value as its 190 * first argument, and the given update as the second argument. 191 * 192 * @param x the update value 193 * @param accumulatorFunction a side-effect-free function of two arguments 194 * @return the previous value 195 * @since 1.8 196 */ 197 public final V getAndAccumulate(V x, 198 BinaryOperator<V> accumulatorFunction) { 199 V prev, next; 200 do { 201 prev = get(); 202 next = accumulatorFunction.operate(prev, x); 203 } while (!compareAndSet(prev, next)); 204 return prev; 205 } 206 207 /** 208 * Atomically updates the current value with the results of 209 * applying the given function to the current and given values. 210 * The function should be side-effect-free, since it may be 211 * re-applied when attempted updates fail due to contention among 212 * threads. The function is applied with the current value as its 213 * first argument, and the given update as the second argument. 214 * 215 * @param x the update value 216 * @param accumulatorFunction a side-effect-free function of two arguments 217 * @return the updated value 218 * @since 1.8 219 */ 220 public final V accumulateAndGet(V x, 221 BinaryOperator<V> accumulatorFunction) { 222 V prev, next; 223 do { 224 prev = get(); 225 next = accumulatorFunction.operate(prev, x); 226 } while (!compareAndSet(prev, next)); 227 return next; 228 } 229 230 /** 231 * Returns the String representation of the current value. 232 * @return the String representation of the current value 233 */ 234 public String toString() { 235 return String.valueOf(get()); 236 } 237 238 }