GNU Classpath (0.97.2) | |
Frames | No Frames |
1: /* 2: * Written by Doug Lea with assistance from members of JCP JSR-166 3: * Expert Group and released to the public domain, as explained at 4: * http://creativecommons.org/licenses/publicdomain 5: */ 6: 7: package java.util.concurrent.atomic; 8: import sun.misc.Unsafe; 9: import java.util.*; 10: 11: /** 12: * A <tt>long</tt> array in which elements may be updated atomically. 13: * See the {@link java.util.concurrent.atomic} package specification 14: * for description of the properties of atomic variables. 15: * @since 1.5 16: * @author Doug Lea 17: */ 18: public class AtomicLongArray implements java.io.Serializable { 19: private static final long serialVersionUID = -2308431214976778248L; 20: 21: // setup to use Unsafe.compareAndSwapInt for updates 22: private static final Unsafe unsafe = Unsafe.getUnsafe(); 23: private static final int base = unsafe.arrayBaseOffset(long[].class); 24: private static final int scale = unsafe.arrayIndexScale(long[].class); 25: private final long[] array; 26: 27: private long rawIndex(int i) { 28: if (i < 0 || i >= array.length) 29: throw new IndexOutOfBoundsException("index " + i); 30: return base + i * scale; 31: } 32: 33: /** 34: * Creates a new AtomicLongArray of given length. 35: * 36: * @param length the length of the array 37: */ 38: public AtomicLongArray(int length) { 39: array = new long[length]; 40: // must perform at least one volatile write to conform to JMM 41: if (length > 0) 42: unsafe.putLongVolatile(array, rawIndex(0), 0); 43: } 44: 45: /** 46: * Creates a new AtomicLongArray with the same length as, and 47: * all elements copied from, the given array. 48: * 49: * @param array the array to copy elements from 50: * @throws NullPointerException if array is null 51: */ 52: public AtomicLongArray(long[] array) { 53: if (array == null) 54: throw new NullPointerException(); 55: int length = array.length; 56: this.array = new long[length]; 57: if (length > 0) { 58: int last = length-1; 59: for (int i = 0; i < last; ++i) 60: this.array[i] = array[i]; 61: // Do the last write as volatile 62: unsafe.putLongVolatile(this.array, rawIndex(last), array[last]); 63: } 64: } 65: 66: /** 67: * Returns the length of the array. 68: * 69: * @return the length of the array 70: */ 71: public final int length() { 72: return array.length; 73: } 74: 75: /** 76: * Gets the current value at position <tt>i</tt>. 77: * 78: * @param i the index 79: * @return the current value 80: */ 81: public final long get(int i) { 82: return unsafe.getLongVolatile(array, rawIndex(i)); 83: } 84: 85: /** 86: * Sets the element at position <tt>i</tt> to the given value. 87: * 88: * @param i the index 89: * @param newValue the new value 90: */ 91: public final void set(int i, long newValue) { 92: unsafe.putLongVolatile(array, rawIndex(i), newValue); 93: } 94: 95: /** 96: * Eventually sets the element at position <tt>i</tt> to the given value. 97: * 98: * @param i the index 99: * @param newValue the new value 100: * @since 1.6 101: */ 102: public final void lazySet(int i, long newValue) { 103: unsafe.putOrderedLong(array, rawIndex(i), newValue); 104: } 105: 106: 107: /** 108: * Atomically sets the element at position <tt>i</tt> to the given value 109: * and returns the old value. 110: * 111: * @param i the index 112: * @param newValue the new value 113: * @return the previous value 114: */ 115: public final long getAndSet(int i, long newValue) { 116: while (true) { 117: long current = get(i); 118: if (compareAndSet(i, current, newValue)) 119: return current; 120: } 121: } 122: 123: /** 124: * Atomically sets the value to the given updated value 125: * if the current value <tt>==</tt> the expected value. 126: * 127: * @param i the index 128: * @param expect the expected value 129: * @param update the new value 130: * @return true if successful. False return indicates that 131: * the actual value was not equal to the expected value. 132: */ 133: public final boolean compareAndSet(int i, long expect, long update) { 134: return unsafe.compareAndSwapLong(array, rawIndex(i), 135: expect, update); 136: } 137: 138: /** 139: * Atomically sets the value to the given updated value 140: * if the current value <tt>==</tt> the expected value. 141: * May fail spuriously and does not provide ordering guarantees, 142: * so is only rarely an appropriate alternative to <tt>compareAndSet</tt>. 143: * 144: * @param i the index 145: * @param expect the expected value 146: * @param update the new value 147: * @return true if successful. 148: */ 149: public final boolean weakCompareAndSet(int i, long expect, long update) { 150: return compareAndSet(i, expect, update); 151: } 152: 153: /** 154: * Atomically increments by one the element at index <tt>i</tt>. 155: * 156: * @param i the index 157: * @return the previous value 158: */ 159: public final long getAndIncrement(int i) { 160: while (true) { 161: long current = get(i); 162: long next = current + 1; 163: if (compareAndSet(i, current, next)) 164: return current; 165: } 166: } 167: 168: /** 169: * Atomically decrements by one the element at index <tt>i</tt>. 170: * 171: * @param i the index 172: * @return the previous value 173: */ 174: public final long getAndDecrement(int i) { 175: while (true) { 176: long current = get(i); 177: long next = current - 1; 178: if (compareAndSet(i, current, next)) 179: return current; 180: } 181: } 182: 183: /** 184: * Atomically adds the given value to the element at index <tt>i</tt>. 185: * 186: * @param i the index 187: * @param delta the value to add 188: * @return the previous value 189: */ 190: public final long getAndAdd(int i, long delta) { 191: while (true) { 192: long current = get(i); 193: long next = current + delta; 194: if (compareAndSet(i, current, next)) 195: return current; 196: } 197: } 198: 199: /** 200: * Atomically increments by one the element at index <tt>i</tt>. 201: * 202: * @param i the index 203: * @return the updated value 204: */ 205: public final long incrementAndGet(int i) { 206: while (true) { 207: long current = get(i); 208: long next = current + 1; 209: if (compareAndSet(i, current, next)) 210: return next; 211: } 212: } 213: 214: /** 215: * Atomically decrements by one the element at index <tt>i</tt>. 216: * 217: * @param i the index 218: * @return the updated value 219: */ 220: public final long decrementAndGet(int i) { 221: while (true) { 222: long current = get(i); 223: long next = current - 1; 224: if (compareAndSet(i, current, next)) 225: return next; 226: } 227: } 228: 229: /** 230: * Atomically adds the given value to the element at index <tt>i</tt>. 231: * 232: * @param i the index 233: * @param delta the value to add 234: * @return the updated value 235: */ 236: public long addAndGet(int i, long delta) { 237: while (true) { 238: long current = get(i); 239: long next = current + delta; 240: if (compareAndSet(i, current, next)) 241: return next; 242: } 243: } 244: 245: /** 246: * Returns the String representation of the current values of array. 247: * @return the String representation of the current values of array. 248: */ 249: public String toString() { 250: if (array.length > 0) // force volatile read 251: get(0); 252: return Arrays.toString(array); 253: } 254: 255: }
GNU Classpath (0.97.2) |