diff options
Diffstat (limited to 'libjava/classpath/external/jsr166/java/util/concurrent/atomic/AtomicLongArray.java')
-rw-r--r-- | libjava/classpath/external/jsr166/java/util/concurrent/atomic/AtomicLongArray.java | 255 |
1 files changed, 255 insertions, 0 deletions
diff --git a/libjava/classpath/external/jsr166/java/util/concurrent/atomic/AtomicLongArray.java b/libjava/classpath/external/jsr166/java/util/concurrent/atomic/AtomicLongArray.java new file mode 100644 index 000000000..c582cba54 --- /dev/null +++ b/libjava/classpath/external/jsr166/java/util/concurrent/atomic/AtomicLongArray.java @@ -0,0 +1,255 @@ +/* + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/licenses/publicdomain + */ + +package java.util.concurrent.atomic; +import sun.misc.Unsafe; +import java.util.*; + +/** + * A <tt>long</tt> array in which elements may be updated atomically. + * See the {@link java.util.concurrent.atomic} package specification + * for description of the properties of atomic variables. + * @since 1.5 + * @author Doug Lea + */ +public class AtomicLongArray implements java.io.Serializable { + private static final long serialVersionUID = -2308431214976778248L; + + // setup to use Unsafe.compareAndSwapInt for updates + private static final Unsafe unsafe = Unsafe.getUnsafe(); + private static final int base = unsafe.arrayBaseOffset(long[].class); + private static final int scale = unsafe.arrayIndexScale(long[].class); + private final long[] array; + + private long rawIndex(int i) { + if (i < 0 || i >= array.length) + throw new IndexOutOfBoundsException("index " + i); + return base + i * scale; + } + + /** + * Creates a new AtomicLongArray of given length. + * + * @param length the length of the array + */ + public AtomicLongArray(int length) { + array = new long[length]; + // must perform at least one volatile write to conform to JMM + if (length > 0) + unsafe.putLongVolatile(array, rawIndex(0), 0); + } + + /** + * Creates a new AtomicLongArray with the same length as, and + * all elements copied from, the given array. + * + * @param array the array to copy elements from + * @throws NullPointerException if array is null + */ + public AtomicLongArray(long[] array) { + if (array == null) + throw new NullPointerException(); + int length = array.length; + this.array = new long[length]; + if (length > 0) { + int last = length-1; + for (int i = 0; i < last; ++i) + this.array[i] = array[i]; + // Do the last write as volatile + unsafe.putLongVolatile(this.array, rawIndex(last), array[last]); + } + } + + /** + * Returns the length of the array. + * + * @return the length of the array + */ + public final int length() { + return array.length; + } + + /** + * Gets the current value at position <tt>i</tt>. + * + * @param i the index + * @return the current value + */ + public final long get(int i) { + return unsafe.getLongVolatile(array, rawIndex(i)); + } + + /** + * Sets the element at position <tt>i</tt> to the given value. + * + * @param i the index + * @param newValue the new value + */ + public final void set(int i, long newValue) { + unsafe.putLongVolatile(array, rawIndex(i), newValue); + } + + /** + * Eventually sets the element at position <tt>i</tt> to the given value. + * + * @param i the index + * @param newValue the new value + * @since 1.6 + */ + public final void lazySet(int i, long newValue) { + unsafe.putOrderedLong(array, rawIndex(i), newValue); + } + + + /** + * Atomically sets the element at position <tt>i</tt> to the given value + * and returns the old value. + * + * @param i the index + * @param newValue the new value + * @return the previous value + */ + public final long getAndSet(int i, long newValue) { + while (true) { + long current = get(i); + if (compareAndSet(i, current, newValue)) + return current; + } + } + + /** + * Atomically sets the value to the given updated value + * if the current value <tt>==</tt> the expected value. + * + * @param i the index + * @param expect the expected value + * @param update the new value + * @return true if successful. False return indicates that + * the actual value was not equal to the expected value. + */ + public final boolean compareAndSet(int i, long expect, long update) { + return unsafe.compareAndSwapLong(array, rawIndex(i), + expect, update); + } + + /** + * Atomically sets the value to the given updated value + * if the current value <tt>==</tt> the expected value. + * May fail spuriously and does not provide ordering guarantees, + * so is only rarely an appropriate alternative to <tt>compareAndSet</tt>. + * + * @param i the index + * @param expect the expected value + * @param update the new value + * @return true if successful. + */ + public final boolean weakCompareAndSet(int i, long expect, long update) { + return compareAndSet(i, expect, update); + } + + /** + * Atomically increments by one the element at index <tt>i</tt>. + * + * @param i the index + * @return the previous value + */ + public final long getAndIncrement(int i) { + while (true) { + long current = get(i); + long next = current + 1; + if (compareAndSet(i, current, next)) + return current; + } + } + + /** + * Atomically decrements by one the element at index <tt>i</tt>. + * + * @param i the index + * @return the previous value + */ + public final long getAndDecrement(int i) { + while (true) { + long current = get(i); + long next = current - 1; + if (compareAndSet(i, current, next)) + return current; + } + } + + /** + * Atomically adds the given value to the element at index <tt>i</tt>. + * + * @param i the index + * @param delta the value to add + * @return the previous value + */ + public final long getAndAdd(int i, long delta) { + while (true) { + long current = get(i); + long next = current + delta; + if (compareAndSet(i, current, next)) + return current; + } + } + + /** + * Atomically increments by one the element at index <tt>i</tt>. + * + * @param i the index + * @return the updated value + */ + public final long incrementAndGet(int i) { + while (true) { + long current = get(i); + long next = current + 1; + if (compareAndSet(i, current, next)) + return next; + } + } + + /** + * Atomically decrements by one the element at index <tt>i</tt>. + * + * @param i the index + * @return the updated value + */ + public final long decrementAndGet(int i) { + while (true) { + long current = get(i); + long next = current - 1; + if (compareAndSet(i, current, next)) + return next; + } + } + + /** + * Atomically adds the given value to the element at index <tt>i</tt>. + * + * @param i the index + * @param delta the value to add + * @return the updated value + */ + public long addAndGet(int i, long delta) { + while (true) { + long current = get(i); + long next = current + delta; + if (compareAndSet(i, current, next)) + return next; + } + } + + /** + * Returns the String representation of the current values of array. + * @return the String representation of the current values of array. + */ + public String toString() { + if (array.length > 0) // force volatile read + get(0); + return Arrays.toString(array); + } + +} |