001 /* 002 * Written by Doug Lea with assistance from members of JCP JSR-166 003 * Expert Group and released to the public domain, as explained at 004 * http://creativecommons.org/publicdomain/zero/1.0/ 005 */ 006 007 /* 008 * Source: 009 * http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/src/jsr166e/extra/AtomicDoubleArray.java?revision=1.5 010 * (Modified to adapt to guava coding conventions and 011 * to use AtomicLongArray instead of sun.misc.Unsafe) 012 */ 013 014 package com.google.common.util.concurrent; 015 016 import static java.lang.Double.doubleToRawLongBits; 017 import static java.lang.Double.longBitsToDouble; 018 019 import com.google.common.annotations.Beta; 020 021 import java.util.concurrent.atomic.AtomicLongArray; 022 023 /** 024 * A {@code double} array in which elements may be updated atomically. 025 * See the {@link java.util.concurrent.atomic} package specification 026 * for description of the properties of atomic variables. 027 * 028 * <p><a name="bitEquals">This class compares primitive {@code double} 029 * values in methods such as {@link #compareAndSet} by comparing their 030 * bitwise representation using {@link Double#doubleToRawLongBits}, 031 * which differs from both the primitive double {@code ==} operator 032 * and from {@link Double#equals}, as if implemented by: 033 * <pre> {@code 034 * static boolean bitEquals(double x, double y) { 035 * long xBits = Double.doubleToRawLongBits(x); 036 * long yBits = Double.doubleToRawLongBits(y); 037 * return xBits == yBits; 038 * }}</pre> 039 * 040 * @author Doug Lea 041 * @author Martin Buchholz 042 * @since 11.0 043 */ 044 @Beta 045 public class AtomicDoubleArray implements java.io.Serializable { 046 private static final long serialVersionUID = 0L; 047 048 // Making this non-final is the lesser evil according to Effective 049 // Java 2nd Edition Item 76: Write readObject methods defensively. 050 private transient AtomicLongArray longs; 051 052 /** 053 * Creates a new {@code AtomicDoubleArray} of the given length, 054 * with all elements initially zero. 055 * 056 * @param length the length of the array 057 */ 058 public AtomicDoubleArray(int length) { 059 this.longs = new AtomicLongArray(length); 060 } 061 062 /** 063 * Creates a new {@code AtomicDoubleArray} with the same length 064 * as, and all elements copied from, the given array. 065 * 066 * @param array the array to copy elements from 067 * @throws NullPointerException if array is null 068 */ 069 public AtomicDoubleArray(double[] array) { 070 final int len = array.length; 071 long[] longArray = new long[len]; 072 for (int i = 0; i < len; i++) { 073 longArray[i] = doubleToRawLongBits(array[i]); 074 } 075 this.longs = new AtomicLongArray(longArray); 076 } 077 078 /** 079 * Returns the length of the array. 080 * 081 * @return the length of the array 082 */ 083 public final int length() { 084 return longs.length(); 085 } 086 087 /** 088 * Gets the current value at position {@code i}. 089 * 090 * @param i the index 091 * @return the current value 092 */ 093 public final double get(int i) { 094 return longBitsToDouble(longs.get(i)); 095 } 096 097 /** 098 * Sets the element at position {@code i} to the given value. 099 * 100 * @param i the index 101 * @param newValue the new value 102 */ 103 public final void set(int i, double newValue) { 104 long next = doubleToRawLongBits(newValue); 105 longs.set(i, next); 106 } 107 108 /** 109 * Eventually sets the element at position {@code i} to the given value. 110 * 111 * @param i the index 112 * @param newValue the new value 113 */ 114 public final void lazySet(int i, double newValue) { 115 set(i, newValue); 116 // TODO(user): replace with code below when jdk5 support is dropped. 117 // long next = doubleToRawLongBits(newValue); 118 // longs.lazySet(i, next); 119 } 120 121 /** 122 * Atomically sets the element at position {@code i} to the given value 123 * and returns the old value. 124 * 125 * @param i the index 126 * @param newValue the new value 127 * @return the previous value 128 */ 129 public final double getAndSet(int i, double newValue) { 130 long next = doubleToRawLongBits(newValue); 131 return longBitsToDouble(longs.getAndSet(i, next)); 132 } 133 134 /** 135 * Atomically sets the element at position {@code i} to the given 136 * updated value 137 * if the current value is <a href="#bitEquals">bitwise equal</a> 138 * to the expected value. 139 * 140 * @param i the index 141 * @param expect the expected value 142 * @param update the new value 143 * @return true if successful. False return indicates that 144 * the actual value was not equal to the expected value. 145 */ 146 public final boolean compareAndSet(int i, double expect, double update) { 147 return longs.compareAndSet(i, 148 doubleToRawLongBits(expect), 149 doubleToRawLongBits(update)); 150 } 151 152 /** 153 * Atomically sets the element at position {@code i} to the given 154 * updated value 155 * if the current value is <a href="#bitEquals">bitwise equal</a> 156 * to the expected value. 157 * 158 * <p>May <a 159 * href="http://download.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/package-summary.html#Spurious"> 160 * fail spuriously</a> 161 * and does not provide ordering guarantees, so is only rarely an 162 * appropriate alternative to {@code compareAndSet}. 163 * 164 * @param i the index 165 * @param expect the expected value 166 * @param update the new value 167 * @return true if successful 168 */ 169 public final boolean weakCompareAndSet(int i, double expect, double update) { 170 return longs.weakCompareAndSet(i, 171 doubleToRawLongBits(expect), 172 doubleToRawLongBits(update)); 173 } 174 175 /** 176 * Atomically adds the given value to the element at index {@code i}. 177 * 178 * @param i the index 179 * @param delta the value to add 180 * @return the previous value 181 */ 182 public final double getAndAdd(int i, double delta) { 183 while (true) { 184 long current = longs.get(i); 185 double currentVal = longBitsToDouble(current); 186 double nextVal = currentVal + delta; 187 long next = doubleToRawLongBits(nextVal); 188 if (longs.compareAndSet(i, current, next)) { 189 return currentVal; 190 } 191 } 192 } 193 194 /** 195 * Atomically adds the given value to the element at index {@code i}. 196 * 197 * @param i the index 198 * @param delta the value to add 199 * @return the updated value 200 */ 201 public double addAndGet(int i, double delta) { 202 while (true) { 203 long current = longs.get(i); 204 double currentVal = longBitsToDouble(current); 205 double nextVal = currentVal + delta; 206 long next = doubleToRawLongBits(nextVal); 207 if (longs.compareAndSet(i, current, next)) { 208 return nextVal; 209 } 210 } 211 } 212 213 /** 214 * Returns the String representation of the current values of array. 215 * @return the String representation of the current values of array 216 */ 217 public String toString() { 218 int iMax = length() - 1; 219 if (iMax == -1) { 220 return "[]"; 221 } 222 223 // Double.toString(Math.PI).length() == 17 224 StringBuilder b = new StringBuilder((17 + 2) * (iMax + 1)); 225 b.append('['); 226 for (int i = 0;; i++) { 227 b.append(longBitsToDouble(longs.get(i))); 228 if (i == iMax) { 229 return b.append(']').toString(); 230 } 231 b.append(',').append(' '); 232 } 233 } 234 235 /** 236 * Saves the state to a stream (that is, serializes it). 237 * 238 * @serialData The length of the array is emitted (int), followed by all 239 * of its elements (each a {@code double}) in the proper order. 240 */ 241 private void writeObject(java.io.ObjectOutputStream s) 242 throws java.io.IOException { 243 s.defaultWriteObject(); 244 245 // Write out array length 246 int length = length(); 247 s.writeInt(length); 248 249 // Write out all elements in the proper order. 250 for (int i = 0; i < length; i++) { 251 s.writeDouble(get(i)); 252 } 253 } 254 255 /** 256 * Reconstitutes the instance from a stream (that is, deserializes it). 257 */ 258 private void readObject(java.io.ObjectInputStream s) 259 throws java.io.IOException, ClassNotFoundException { 260 s.defaultReadObject(); 261 262 // Read in array length and allocate array 263 int length = s.readInt(); 264 this.longs = new AtomicLongArray(length); 265 266 // Read in all elements in the proper order. 267 for (int i = 0; i < length; i++) { 268 set(i, s.readDouble()); 269 } 270 } 271 }