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/publicdomain/zero/1.0/ 5 */ 6 7/* 8 * Source: 9 * http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/src/jsr166e/extra/AtomicDoubleArray.java?revision=1.5 10 * (Modified to adapt to guava coding conventions and 11 * to use AtomicLongArray instead of sun.misc.Unsafe) 12 */ 13 14package com.google.common.util.concurrent; 15 16import com.google.common.annotations.Beta; 17 18import static java.lang.Double.doubleToRawLongBits; 19import static java.lang.Double.longBitsToDouble; 20import java.util.concurrent.atomic.AtomicLongArray; 21 22/** 23 * A {@code double} array in which elements may be updated atomically. 24 * See the {@link java.util.concurrent.atomic} package specification 25 * for description of the properties of atomic variables. 26 * 27 * <p><a name="bitEquals">This class compares primitive {@code double} 28 * values in methods such as {@link #compareAndSet} by comparing their 29 * bitwise representation using {@link Double#doubleToRawLongBits}, 30 * which differs from both the primitive double {@code ==} operator 31 * and from {@link Double#equals}, as if implemented by: 32 * <pre> {@code 33 * static boolean bitEquals(double x, double y) { 34 * long xBits = Double.doubleToRawLongBits(x); 35 * long yBits = Double.doubleToRawLongBits(y); 36 * return xBits == yBits; 37 * }}</pre> 38 * 39 * @author Doug Lea 40 * @author Martin Buchholz 41 * @since 11.0 42 */ 43@Beta 44public class AtomicDoubleArray implements java.io.Serializable { 45 private static final long serialVersionUID = 0L; 46 47 // Making this non-final is the lesser evil according to Effective 48 // Java 2nd Edition Item 76: Write readObject methods defensively. 49 private transient AtomicLongArray longs; 50 51 /** 52 * Creates a new {@code AtomicDoubleArray} of the given length, 53 * with all elements initially zero. 54 * 55 * @param length the length of the array 56 */ 57 public AtomicDoubleArray(int length) { 58 this.longs = new AtomicLongArray(length); 59 } 60 61 /** 62 * Creates a new {@code AtomicDoubleArray} with the same length 63 * as, and all elements copied from, the given array. 64 * 65 * @param array the array to copy elements from 66 * @throws NullPointerException if array is null 67 */ 68 public AtomicDoubleArray(double[] array) { 69 final int len = array.length; 70 long[] longArray = new long[len]; 71 for (int i = 0; i < len; i++) { 72 longArray[i] = doubleToRawLongBits(array[i]); 73 } 74 this.longs = new AtomicLongArray(longArray); 75 } 76 77 /** 78 * Returns the length of the array. 79 * 80 * @return the length of the array 81 */ 82 public final int length() { 83 return longs.length(); 84 } 85 86 /** 87 * Gets the current value at position {@code i}. 88 * 89 * @param i the index 90 * @return the current value 91 */ 92 public final double get(int i) { 93 return longBitsToDouble(longs.get(i)); 94 } 95 96 /** 97 * Sets the element at position {@code i} to the given value. 98 * 99 * @param i the index 100 * @param newValue the new value 101 */ 102 public final void set(int i, double newValue) { 103 long next = doubleToRawLongBits(newValue); 104 longs.set(i, next); 105 } 106 107 /** 108 * Eventually sets the element at position {@code i} to the given value. 109 * 110 * @param i the index 111 * @param newValue the new value 112 */ 113 public final void lazySet(int i, double newValue) { 114 set(i, newValue); 115 // TODO(user): replace with code below when jdk5 support is dropped. 116 // long next = doubleToRawLongBits(newValue); 117 // longs.lazySet(i, next); 118 } 119 120 /** 121 * Atomically sets the element at position {@code i} to the given value 122 * and returns the old value. 123 * 124 * @param i the index 125 * @param newValue the new value 126 * @return the previous value 127 */ 128 public final double getAndSet(int i, double newValue) { 129 long next = doubleToRawLongBits(newValue); 130 return longBitsToDouble(longs.getAndSet(i, next)); 131 } 132 133 /** 134 * Atomically sets the element at position {@code i} to the given 135 * updated value 136 * if the current value is <a href="#bitEquals">bitwise equal</a> 137 * to the expected value. 138 * 139 * @param i the index 140 * @param expect the expected value 141 * @param update the new value 142 * @return true if successful. False return indicates that 143 * the actual value was not equal to the expected value. 144 */ 145 public final boolean compareAndSet(int i, double expect, double update) { 146 return longs.compareAndSet(i, 147 doubleToRawLongBits(expect), 148 doubleToRawLongBits(update)); 149 } 150 151 /** 152 * Atomically sets the element at position {@code i} to the given 153 * updated value 154 * if the current value is <a href="#bitEquals">bitwise equal</a> 155 * to the expected value. 156 * 157 * <p>May <a 158 * href="http://download.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/package-summary.html#Spurious"> 159 * fail spuriously</a> 160 * and does not provide ordering guarantees, so is only rarely an 161 * appropriate alternative to {@code compareAndSet}. 162 * 163 * @param i the index 164 * @param expect the expected value 165 * @param update the new value 166 * @return true if successful 167 */ 168 public final boolean weakCompareAndSet(int i, double expect, double update) { 169 return longs.weakCompareAndSet(i, 170 doubleToRawLongBits(expect), 171 doubleToRawLongBits(update)); 172 } 173 174 /** 175 * Atomically adds the given value to the element at index {@code i}. 176 * 177 * @param i the index 178 * @param delta the value to add 179 * @return the previous value 180 */ 181 public final double getAndAdd(int i, double delta) { 182 while (true) { 183 long current = longs.get(i); 184 double currentVal = longBitsToDouble(current); 185 double nextVal = currentVal + delta; 186 long next = doubleToRawLongBits(nextVal); 187 if (longs.compareAndSet(i, current, next)) { 188 return currentVal; 189 } 190 } 191 } 192 193 /** 194 * Atomically adds the given value to the element at index {@code i}. 195 * 196 * @param i the index 197 * @param delta the value to add 198 * @return the updated value 199 */ 200 public double addAndGet(int i, double delta) { 201 while (true) { 202 long current = longs.get(i); 203 double currentVal = longBitsToDouble(current); 204 double nextVal = currentVal + delta; 205 long next = doubleToRawLongBits(nextVal); 206 if (longs.compareAndSet(i, current, next)) { 207 return nextVal; 208 } 209 } 210 } 211 212 /** 213 * Returns the String representation of the current values of array. 214 * @return the String representation of the current values of array 215 */ 216 public String toString() { 217 int iMax = length() - 1; 218 if (iMax == -1) { 219 return "[]"; 220 } 221 222 // Double.toString(Math.PI).length() == 17 223 StringBuilder b = new StringBuilder((17 + 2) * (iMax + 1)); 224 b.append('['); 225 for (int i = 0;; i++) { 226 b.append(longBitsToDouble(longs.get(i))); 227 if (i == iMax) { 228 return b.append(']').toString(); 229 } 230 b.append(',').append(' '); 231 } 232 } 233 234 /** 235 * Saves the state to a stream (that is, serializes it). 236 * 237 * @serialData The length of the array is emitted (int), followed by all 238 * of its elements (each a {@code double}) in the proper order. 239 */ 240 private void writeObject(java.io.ObjectOutputStream s) 241 throws java.io.IOException { 242 s.defaultWriteObject(); 243 244 // Write out array length 245 int length = length(); 246 s.writeInt(length); 247 248 // Write out all elements in the proper order. 249 for (int i = 0; i < length; i++) { 250 s.writeDouble(get(i)); 251 } 252 } 253 254 /** 255 * Reconstitutes the instance from a stream (that is, deserializes it). 256 */ 257 private void readObject(java.io.ObjectInputStream s) 258 throws java.io.IOException, ClassNotFoundException { 259 s.defaultReadObject(); 260 261 // Read in array length and allocate array 262 int length = s.readInt(); 263 this.longs = new AtomicLongArray(length); 264 265 // Read in all elements in the proper order. 266 for (int i = 0; i < length; i++) { 267 set(i, s.readDouble()); 268 } 269 } 270} 271