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 38 import java.lang.invoke.MethodHandles; 39 import java.lang.invoke.VarHandle; 40 import java.lang.reflect.Array; 41 import java.lang.reflect.Field; 42 import java.util.Arrays; 43 import java.util.function.BinaryOperator; 44 import java.util.function.UnaryOperator; 45 46 /** 47 * An array of object references in which elements may be updated 48 * atomically. See the {@link VarHandle} specification for 49 * descriptions of the properties of atomic accesses. 50 * @since 1.5 51 * @author Doug Lea 52 * @param <E> The base class of elements held in this array 53 */ 54 public class AtomicReferenceArray<E> implements java.io.Serializable { 55 private static final long serialVersionUID = -6209656149925076980L; 56 private static final VarHandle AA 57 = MethodHandles.arrayElementVarHandle(Object[].class); 58 @SuppressWarnings("serial") // Conditionally serializable 59 private final Object[] array; // must have exact type Object[] 60 61 /** 62 * Creates a new AtomicReferenceArray of the given length, with all 63 * elements initially null. 64 * 65 * @param length the length of the array 66 */ AtomicReferenceArray(int length)67 public AtomicReferenceArray(int length) { 68 array = new Object[length]; 69 } 70 71 /** 72 * Creates a new AtomicReferenceArray with the same length as, and 73 * all elements copied from, the given array. 74 * 75 * @param array the array to copy elements from 76 * @throws NullPointerException if array is null 77 */ AtomicReferenceArray(E[] array)78 public AtomicReferenceArray(E[] array) { 79 // Visibility guaranteed by final field guarantees 80 this.array = Arrays.copyOf(array, array.length, Object[].class); 81 } 82 83 /** 84 * Returns the length of the array. 85 * 86 * @return the length of the array 87 */ length()88 public final int length() { 89 return array.length; 90 } 91 92 /** 93 * Returns the current value of the element at index {@code i}, 94 * with memory effects as specified by {@link VarHandle#getVolatile}. 95 * 96 * @param i the index 97 * @return the current value 98 */ 99 @SuppressWarnings("unchecked") get(int i)100 public final E get(int i) { 101 return (E)AA.getVolatile(array, i); 102 } 103 104 /** 105 * Sets the element at index {@code i} to {@code newValue}, 106 * with memory effects as specified by {@link VarHandle#setVolatile}. 107 * 108 * @param i the index 109 * @param newValue the new value 110 */ set(int i, E newValue)111 public final void set(int i, E newValue) { 112 AA.setVolatile(array, i, newValue); 113 } 114 115 /** 116 * Sets the element at index {@code i} to {@code newValue}, 117 * with memory effects as specified by {@link VarHandle#setRelease}. 118 * 119 * @param i the index 120 * @param newValue the new value 121 * @since 1.6 122 */ lazySet(int i, E newValue)123 public final void lazySet(int i, E newValue) { 124 AA.setRelease(array, i, newValue); 125 } 126 127 /** 128 * Atomically sets the element at index {@code i} to {@code 129 * newValue} and returns the old value, 130 * with memory effects as specified by {@link VarHandle#getAndSet}. 131 * 132 * @param i the index 133 * @param newValue the new value 134 * @return the previous value 135 */ 136 @SuppressWarnings("unchecked") getAndSet(int i, E newValue)137 public final E getAndSet(int i, E newValue) { 138 return (E)AA.getAndSet(array, i, newValue); 139 } 140 141 /** 142 * Atomically sets the element at index {@code i} to {@code newValue} 143 * if the element's current value {@code == expectedValue}, 144 * with memory effects as specified by {@link VarHandle#compareAndSet}. 145 * 146 * @param i the index 147 * @param expectedValue the expected value 148 * @param newValue the new value 149 * @return {@code true} if successful. False return indicates that 150 * the actual value was not equal to the expected value. 151 */ compareAndSet(int i, E expectedValue, E newValue)152 public final boolean compareAndSet(int i, E expectedValue, E newValue) { 153 return AA.compareAndSet(array, i, expectedValue, newValue); 154 } 155 156 /** 157 * Possibly atomically sets the element at index {@code i} to 158 * {@code newValue} if the element's current value {@code == expectedValue}, 159 * with memory effects as specified by {@link VarHandle#weakCompareAndSetPlain}. 160 * 161 * @deprecated This method has plain memory effects but the method 162 * name implies volatile memory effects (see methods such as 163 * {@link #compareAndExchange} and {@link #compareAndSet}). To avoid 164 * confusion over plain or volatile memory effects it is recommended that 165 * the method {@link #weakCompareAndSetPlain} be used instead. 166 * 167 * @param i the index 168 * @param expectedValue the expected value 169 * @param newValue the new value 170 * @return {@code true} if successful 171 * @see #weakCompareAndSetPlain 172 */ 173 @Deprecated(since="9") weakCompareAndSet(int i, E expectedValue, E newValue)174 public final boolean weakCompareAndSet(int i, E expectedValue, E newValue) { 175 return AA.weakCompareAndSetPlain(array, i, expectedValue, newValue); 176 } 177 178 /** 179 * Possibly atomically sets the element at index {@code i} to 180 * {@code newValue} if the element's current value {@code == expectedValue}, 181 * with memory effects as specified by {@link VarHandle#weakCompareAndSetPlain}. 182 * 183 * @param i the index 184 * @param expectedValue the expected value 185 * @param newValue the new value 186 * @return {@code true} if successful 187 * @since 9 188 */ weakCompareAndSetPlain(int i, E expectedValue, E newValue)189 public final boolean weakCompareAndSetPlain(int i, E expectedValue, E newValue) { 190 return AA.weakCompareAndSetPlain(array, i, expectedValue, newValue); 191 } 192 193 /** 194 * Atomically updates (with memory effects as specified by {@link 195 * VarHandle#compareAndSet}) the element at index {@code i} with 196 * the results of applying the given function, returning the 197 * previous value. The function should be side-effect-free, since 198 * it may be re-applied when attempted updates fail due to 199 * contention among threads. 200 * 201 * @param i the index 202 * @param updateFunction a side-effect-free function 203 * @return the previous value 204 * @since 1.8 205 */ getAndUpdate(int i, UnaryOperator<E> updateFunction)206 public final E getAndUpdate(int i, UnaryOperator<E> updateFunction) { 207 E prev = get(i), next = null; 208 for (boolean haveNext = false;;) { 209 if (!haveNext) 210 next = updateFunction.apply(prev); 211 if (weakCompareAndSetVolatile(i, prev, next)) 212 return prev; 213 haveNext = (prev == (prev = get(i))); 214 } 215 } 216 217 /** 218 * Atomically updates (with memory effects as specified by {@link 219 * VarHandle#compareAndSet}) the element at index {@code i} with 220 * the results of applying the given function, returning the 221 * updated value. The function should be side-effect-free, since it 222 * may be re-applied when attempted updates fail due to contention 223 * among threads. 224 * 225 * @param i the index 226 * @param updateFunction a side-effect-free function 227 * @return the updated value 228 * @since 1.8 229 */ updateAndGet(int i, UnaryOperator<E> updateFunction)230 public final E updateAndGet(int i, UnaryOperator<E> updateFunction) { 231 E prev = get(i), next = null; 232 for (boolean haveNext = false;;) { 233 if (!haveNext) 234 next = updateFunction.apply(prev); 235 if (weakCompareAndSetVolatile(i, prev, next)) 236 return next; 237 haveNext = (prev == (prev = get(i))); 238 } 239 } 240 241 /** 242 * Atomically updates (with memory effects as specified by {@link 243 * VarHandle#compareAndSet}) the element at index {@code i} with 244 * the results of applying the given function to the current and 245 * given values, returning the previous value. The function should 246 * be side-effect-free, since it may be re-applied when attempted 247 * updates fail due to contention among threads. The function is 248 * applied with the current value of the element at index {@code i} 249 * as its first argument, and the given update as the second 250 * argument. 251 * 252 * @param i the index 253 * @param x the update value 254 * @param accumulatorFunction a side-effect-free function of two arguments 255 * @return the previous value 256 * @since 1.8 257 */ getAndAccumulate(int i, E x, BinaryOperator<E> accumulatorFunction)258 public final E getAndAccumulate(int i, E x, 259 BinaryOperator<E> accumulatorFunction) { 260 E prev = get(i), next = null; 261 for (boolean haveNext = false;;) { 262 if (!haveNext) 263 next = accumulatorFunction.apply(prev, x); 264 if (weakCompareAndSetVolatile(i, prev, next)) 265 return prev; 266 haveNext = (prev == (prev = get(i))); 267 } 268 } 269 270 /** 271 * Atomically updates (with memory effects as specified by {@link 272 * VarHandle#compareAndSet}) the element at index {@code i} with 273 * the results of applying the given function to the current and 274 * given values, returning the updated value. The function should 275 * be side-effect-free, since it may be re-applied when attempted 276 * updates fail due to contention among threads. The function is 277 * applied with the current value of the element at index {@code i} 278 * as its first argument, and the given update as the second 279 * argument. 280 * 281 * @param i the index 282 * @param x the update value 283 * @param accumulatorFunction a side-effect-free function of two arguments 284 * @return the updated value 285 * @since 1.8 286 */ accumulateAndGet(int i, E x, BinaryOperator<E> accumulatorFunction)287 public final E accumulateAndGet(int i, E x, 288 BinaryOperator<E> accumulatorFunction) { 289 E prev = get(i), next = null; 290 for (boolean haveNext = false;;) { 291 if (!haveNext) 292 next = accumulatorFunction.apply(prev, x); 293 if (weakCompareAndSetVolatile(i, prev, next)) 294 return next; 295 haveNext = (prev == (prev = get(i))); 296 } 297 } 298 299 /** 300 * Returns the String representation of the current values of array. 301 * @return the String representation of the current values of array 302 */ toString()303 public String toString() { 304 int iMax = array.length - 1; 305 if (iMax == -1) 306 return "[]"; 307 308 StringBuilder b = new StringBuilder(); 309 b.append('['); 310 for (int i = 0; ; i++) { 311 b.append(get(i)); 312 if (i == iMax) 313 return b.append(']').toString(); 314 b.append(',').append(' '); 315 } 316 } 317 318 /** 319 * Reconstitutes the instance from a stream (that is, deserializes it). 320 * @param s the stream 321 * @throws ClassNotFoundException if the class of a serialized object 322 * could not be found 323 * @throws java.io.IOException if an I/O error occurs 324 */ readObject(java.io.ObjectInputStream s)325 private void readObject(java.io.ObjectInputStream s) 326 throws java.io.IOException, ClassNotFoundException { 327 // Note: This must be changed if any additional fields are defined 328 Object a = s.readFields().get("array", null); 329 if (a == null || !a.getClass().isArray()) 330 throw new java.io.InvalidObjectException("Not array type"); 331 if (a.getClass() != Object[].class) 332 a = Arrays.copyOf((Object[])a, Array.getLength(a), Object[].class); 333 @SuppressWarnings("removal") 334 Field arrayField = java.security.AccessController.doPrivileged( 335 (java.security.PrivilegedAction<Field>) () -> { 336 try { 337 Field f = AtomicReferenceArray.class 338 .getDeclaredField("array"); 339 f.setAccessible(true); 340 return f; 341 } catch (ReflectiveOperationException e) { 342 throw new Error(e); 343 }}); 344 try { 345 arrayField.set(this, a); 346 } catch (IllegalAccessException e) { 347 throw new Error(e); 348 } 349 } 350 351 // jdk9 352 353 /** 354 * Returns the current value of the element at index {@code i}, 355 * with memory semantics of reading as if the variable was declared 356 * non-{@code volatile}. 357 * 358 * @param i the index 359 * @return the value 360 * @since 9 361 */ getPlain(int i)362 public final E getPlain(int i) { 363 return (E)AA.get(array, i); 364 } 365 366 /** 367 * Sets the element at index {@code i} to {@code newValue}, 368 * with memory semantics of setting as if the variable was 369 * declared non-{@code volatile} and non-{@code final}. 370 * 371 * @param i the index 372 * @param newValue the new value 373 * @since 9 374 */ setPlain(int i, E newValue)375 public final void setPlain(int i, E newValue) { 376 AA.set(array, i, newValue); 377 } 378 379 /** 380 * Returns the current value of the element at index {@code i}, 381 * with memory effects as specified by {@link VarHandle#getOpaque}. 382 * 383 * @param i the index 384 * @return the value 385 * @since 9 386 */ getOpaque(int i)387 public final E getOpaque(int i) { 388 return (E)AA.getOpaque(array, i); 389 } 390 391 /** 392 * Sets the element at index {@code i} to {@code newValue}, 393 * with memory effects as specified by {@link VarHandle#setOpaque}. 394 * 395 * @param i the index 396 * @param newValue the new value 397 * @since 9 398 */ setOpaque(int i, E newValue)399 public final void setOpaque(int i, E newValue) { 400 AA.setOpaque(array, i, newValue); 401 } 402 403 /** 404 * Returns the current value of the element at index {@code i}, 405 * with memory effects as specified by {@link VarHandle#getAcquire}. 406 * 407 * @param i the index 408 * @return the value 409 * @since 9 410 */ getAcquire(int i)411 public final E getAcquire(int i) { 412 return (E)AA.getAcquire(array, i); 413 } 414 415 /** 416 * Sets the element at index {@code i} to {@code newValue}, 417 * with memory effects as specified by {@link VarHandle#setRelease}. 418 * 419 * @param i the index 420 * @param newValue the new value 421 * @since 9 422 */ setRelease(int i, E newValue)423 public final void setRelease(int i, E newValue) { 424 AA.setRelease(array, i, newValue); 425 } 426 427 /** 428 * Atomically sets the element at index {@code i} to {@code newValue} 429 * if the element's current value, referred to as the <em>witness 430 * value</em>, {@code == expectedValue}, 431 * with memory effects as specified by 432 * {@link VarHandle#compareAndExchange}. 433 * 434 * @param i the index 435 * @param expectedValue the expected value 436 * @param newValue the new value 437 * @return the witness value, which will be the same as the 438 * expected value if successful 439 * @since 9 440 */ compareAndExchange(int i, E expectedValue, E newValue)441 public final E compareAndExchange(int i, E expectedValue, E newValue) { 442 return (E)AA.compareAndExchange(array, i, expectedValue, newValue); 443 } 444 445 /** 446 * Atomically sets the element at index {@code i} to {@code newValue} 447 * if the element's current value, referred to as the <em>witness 448 * value</em>, {@code == expectedValue}, 449 * with memory effects as specified by 450 * {@link VarHandle#compareAndExchangeAcquire}. 451 * 452 * @param i the index 453 * @param expectedValue the expected value 454 * @param newValue the new value 455 * @return the witness value, which will be the same as the 456 * expected value if successful 457 * @since 9 458 */ compareAndExchangeAcquire(int i, E expectedValue, E newValue)459 public final E compareAndExchangeAcquire(int i, E expectedValue, E newValue) { 460 return (E)AA.compareAndExchangeAcquire(array, i, expectedValue, newValue); 461 } 462 463 /** 464 * Atomically sets the element at index {@code i} to {@code newValue} 465 * if the element's current value, referred to as the <em>witness 466 * value</em>, {@code == expectedValue}, 467 * with memory effects as specified by 468 * {@link VarHandle#compareAndExchangeRelease}. 469 * 470 * @param i the index 471 * @param expectedValue the expected value 472 * @param newValue the new value 473 * @return the witness value, which will be the same as the 474 * expected value if successful 475 * @since 9 476 */ compareAndExchangeRelease(int i, E expectedValue, E newValue)477 public final E compareAndExchangeRelease(int i, E expectedValue, E newValue) { 478 return (E)AA.compareAndExchangeRelease(array, i, expectedValue, newValue); 479 } 480 481 /** 482 * Possibly atomically sets the element at index {@code i} to 483 * {@code newValue} if the element's current value {@code == expectedValue}, 484 * with memory effects as specified by 485 * {@link VarHandle#weakCompareAndSet}. 486 * 487 * @param i the index 488 * @param expectedValue the expected value 489 * @param newValue the new value 490 * @return {@code true} if successful 491 * @since 9 492 */ weakCompareAndSetVolatile(int i, E expectedValue, E newValue)493 public final boolean weakCompareAndSetVolatile(int i, E expectedValue, E newValue) { 494 return AA.weakCompareAndSet(array, i, expectedValue, newValue); 495 } 496 497 /** 498 * Possibly atomically sets the element at index {@code i} to 499 * {@code newValue} if the element's current value {@code == expectedValue}, 500 * with memory effects as specified by 501 * {@link VarHandle#weakCompareAndSetAcquire}. 502 * 503 * @param i the index 504 * @param expectedValue the expected value 505 * @param newValue the new value 506 * @return {@code true} if successful 507 * @since 9 508 */ weakCompareAndSetAcquire(int i, E expectedValue, E newValue)509 public final boolean weakCompareAndSetAcquire(int i, E expectedValue, E newValue) { 510 return AA.weakCompareAndSetAcquire(array, i, expectedValue, newValue); 511 } 512 513 /** 514 * Possibly atomically sets the element at index {@code i} to 515 * {@code newValue} if the element's current value {@code == expectedValue}, 516 * with memory effects as specified by 517 * {@link VarHandle#weakCompareAndSetRelease}. 518 * 519 * @param i the index 520 * @param expectedValue the expected value 521 * @param newValue the new value 522 * @return {@code true} if successful 523 * @since 9 524 */ weakCompareAndSetRelease(int i, E expectedValue, E newValue)525 public final boolean weakCompareAndSetRelease(int i, E expectedValue, E newValue) { 526 return AA.weakCompareAndSetRelease(array, i, expectedValue, newValue); 527 } 528 529 } 530