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: * An <tt>int</tt> array in which elements may be updated atomically. 13: * See the {@link java.util.concurrent.atomic} package 14: * specification for description of the properties of atomic 15: * variables. 16: * @since 1.5 17: * @author Doug Lea 18: */ 19: public class AtomicIntegerArray implements java.io.Serializable { 20: private static final long serialVersionUID = 2862133569453604235L; 21: 22: // setup to use Unsafe.compareAndSwapInt for updates 23: private static final Unsafe unsafe = Unsafe.getUnsafe(); 24: private static final int base = unsafe.arrayBaseOffset(int[].class); 25: private static final int scale = unsafe.arrayIndexScale(int[].class); 26: private final int[] array; 27: 28: private long rawIndex(int i) { 29: if (i < 0 || i >= array.length) 30: throw new IndexOutOfBoundsException("index " + i); 31: return base + i * scale; 32: } 33: 34: /** 35: * Creates a new AtomicIntegerArray of given length. 36: * 37: * @param length the length of the array 38: */ 39: public AtomicIntegerArray(int length) { 40: array = new int[length]; 41: // must perform at least one volatile write to conform to JMM 42: if (length > 0) 43: unsafe.putIntVolatile(array, rawIndex(0), 0); 44: } 45: 46: /** 47: * Creates a new AtomicIntegerArray with the same length as, and 48: * all elements copied from, the given array. 49: * 50: * @param array the array to copy elements from 51: * @throws NullPointerException if array is null 52: */ 53: public AtomicIntegerArray(int[] array) { 54: if (array == null) 55: throw new NullPointerException(); 56: int length = array.length; 57: this.array = new int[length]; 58: if (length > 0) { 59: int last = length-1; 60: for (int i = 0; i < last; ++i) 61: this.array[i] = array[i]; 62: // Do the last write as volatile 63: unsafe.putIntVolatile(this.array, rawIndex(last), array[last]); 64: } 65: } 66: 67: /** 68: * Returns the length of the array. 69: * 70: * @return the length of the array 71: */ 72: public final int length() { 73: return array.length; 74: } 75: 76: /** 77: * Gets the current value at position <tt>i</tt>. 78: * 79: * @param i the index 80: * @return the current value 81: */ 82: public final int get(int i) { 83: return unsafe.getIntVolatile(array, rawIndex(i)); 84: } 85: 86: /** 87: * Sets the element at position <tt>i</tt> to the given value. 88: * 89: * @param i the index 90: * @param newValue the new value 91: */ 92: public final void set(int i, int newValue) { 93: unsafe.putIntVolatile(array, rawIndex(i), newValue); 94: } 95: 96: /** 97: * Eventually sets the element at position <tt>i</tt> to the given value. 98: * 99: * @param i the index 100: * @param newValue the new value 101: * @since 1.6 102: */ 103: public final void lazySet(int i, int newValue) { 104: unsafe.putOrderedInt(array, rawIndex(i), newValue); 105: } 106: 107: /** 108: * Atomically sets the element at position <tt>i</tt> to the given 109: * value 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 int getAndSet(int i, int newValue) { 116: while (true) { 117: int current = get(i); 118: if (compareAndSet(i, current, newValue)) 119: return current; 120: } 121: } 122: 123: /** 124: * Atomically sets the element at position <tt>i</tt> to the given 125: * updated value 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, int expect, int update) { 134: return unsafe.compareAndSwapInt(array, rawIndex(i), 135: expect, update); 136: } 137: 138: /** 139: * Atomically sets the element at position <tt>i</tt> to the given 140: * updated value 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, int expect, int 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 int getAndIncrement(int i) { 160: while (true) { 161: int current = get(i); 162: int 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 int getAndDecrement(int i) { 175: while (true) { 176: int current = get(i); 177: int 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 int getAndAdd(int i, int delta) { 191: while (true) { 192: int current = get(i); 193: int 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 int incrementAndGet(int i) { 206: while (true) { 207: int current = get(i); 208: int 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 int decrementAndGet(int i) { 221: while (true) { 222: int current = get(i); 223: int 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 final int addAndGet(int i, int delta) { 237: while (true) { 238: int current = get(i); 239: int 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) |