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