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