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