Source for java.util.concurrent.atomic.AtomicLongArray

   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: }