Coverage Summary for Class: AtomicDouble (com.google.common.util.concurrent)

Class Class, % Method, % Line, %
AtomicDouble 100% (1/1) 11.1% (2/18) 9.1% (4/44)


1 /* 2  * Written by Doug Lea and Martin Buchholz with assistance from 3  * members of JCP JSR-166 Expert Group and released to the public 4  * domain, as explained at 5  * http://creativecommons.org/publicdomain/zero/1.0/ 6  */ 7  8 /* 9  * Source: 10  * http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/src/jsr166e/extra/AtomicDouble.java?revision=1.13 11  * (Modified to adapt to guava coding conventions and 12  * to use AtomicLongFieldUpdater instead of sun.misc.Unsafe) 13  */ 14  15 package com.google.common.util.concurrent; 16  17 import static java.lang.Double.doubleToRawLongBits; 18 import static java.lang.Double.longBitsToDouble; 19  20 import com.google.common.annotations.GwtIncompatible; 21 import com.google.errorprone.annotations.CanIgnoreReturnValue; 22 import com.google.j2objc.annotations.ReflectionSupport; 23 import java.util.concurrent.atomic.AtomicLongFieldUpdater; 24  25 /** 26  * A {@code double} value that may be updated atomically. See the {@link 27  * java.util.concurrent.atomic} package specification for description of the properties of atomic 28  * variables. An {@code AtomicDouble} is used in applications such as atomic accumulation, and 29  * cannot be used as a replacement for a {@link Double}. However, this class does extend {@code 30  * Number} to allow uniform access by tools and utilities that deal with numerically-based classes. 31  * 32  * <p><a id="bitEquals"></a>This class compares primitive {@code double} values in methods such as 33  * {@link #compareAndSet} by comparing their bitwise representation using {@link 34  * Double#doubleToRawLongBits}, which differs from both the primitive double {@code ==} operator and 35  * from {@link Double#equals}, as if implemented by: 36  * 37  * <pre>{@code 38  * static boolean bitEquals(double x, double y) { 39  * long xBits = Double.doubleToRawLongBits(x); 40  * long yBits = Double.doubleToRawLongBits(y); 41  * return xBits == yBits; 42  * } 43  * }</pre> 44  * 45  * <p>It is possible to write a more scalable updater, at the cost of giving up strict atomicity. 46  * See for example <a 47  * href="http://gee.cs.oswego.edu/dl/jsr166/dist/docs/java.base/java/util/concurrent/atomic/DoubleAdder.html"> 48  * DoubleAdder</a>. 49  * 50  * @author Doug Lea 51  * @author Martin Buchholz 52  * @since 11.0 53  */ 54 @GwtIncompatible 55 @ReflectionSupport(value = ReflectionSupport.Level.FULL) 56 @ElementTypesAreNonnullByDefault 57 public class AtomicDouble extends Number implements java.io.Serializable { 58  private static final long serialVersionUID = 0L; 59  60  private transient volatile long value; 61  62  private static final AtomicLongFieldUpdater<AtomicDouble> updater = 63  AtomicLongFieldUpdater.newUpdater(AtomicDouble.class, "value"); 64  65  /** 66  * Creates a new {@code AtomicDouble} with the given initial value. 67  * 68  * @param initialValue the initial value 69  */ 70  public AtomicDouble(double initialValue) { 71  value = doubleToRawLongBits(initialValue); 72  } 73  74  /** Creates a new {@code AtomicDouble} with initial value {@code 0.0}. */ 75  public AtomicDouble() { 76  // assert doubleToRawLongBits(0.0) == 0L; 77  } 78  79  /** 80  * Gets the current value. 81  * 82  * @return the current value 83  */ 84  public final double get() { 85  return longBitsToDouble(value); 86  } 87  88  /** 89  * Sets to the given value. 90  * 91  * @param newValue the new value 92  */ 93  public final void set(double newValue) { 94  long next = doubleToRawLongBits(newValue); 95  value = next; 96  } 97  98  /** 99  * Eventually sets to the given value. 100  * 101  * @param newValue the new value 102  */ 103  public final void lazySet(double newValue) { 104  long next = doubleToRawLongBits(newValue); 105  updater.lazySet(this, next); 106  } 107  108  /** 109  * Atomically sets to the given value and returns the old value. 110  * 111  * @param newValue the new value 112  * @return the previous value 113  */ 114  public final double getAndSet(double newValue) { 115  long next = doubleToRawLongBits(newValue); 116  return longBitsToDouble(updater.getAndSet(this, next)); 117  } 118  119  /** 120  * Atomically sets the value to the given updated value if the current value is <a 121  * href="#bitEquals">bitwise equal</a> to the expected value. 122  * 123  * @param expect the expected value 124  * @param update the new value 125  * @return {@code true} if successful. False return indicates that the actual value was not 126  * bitwise equal to the expected value. 127  */ 128  public final boolean compareAndSet(double expect, double update) { 129  return updater.compareAndSet(this, doubleToRawLongBits(expect), doubleToRawLongBits(update)); 130  } 131  132  /** 133  * Atomically sets the value to the given updated value if the current value is <a 134  * href="#bitEquals">bitwise equal</a> to the expected value. 135  * 136  * <p>May <a 137  * href="http://download.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/package-summary.html#Spurious"> 138  * fail spuriously</a> and does not provide ordering guarantees, so is only rarely an appropriate 139  * alternative to {@code compareAndSet}. 140  * 141  * @param expect the expected value 142  * @param update the new value 143  * @return {@code true} if successful 144  */ 145  public final boolean weakCompareAndSet(double expect, double update) { 146  return updater.weakCompareAndSet( 147  this, doubleToRawLongBits(expect), doubleToRawLongBits(update)); 148  } 149  150  /** 151  * Atomically adds the given value to the current value. 152  * 153  * @param delta the value to add 154  * @return the previous value 155  */ 156  @CanIgnoreReturnValue 157  public final double getAndAdd(double delta) { 158  while (true) { 159  long current = value; 160  double currentVal = longBitsToDouble(current); 161  double nextVal = currentVal + delta; 162  long next = doubleToRawLongBits(nextVal); 163  if (updater.compareAndSet(this, current, next)) { 164  return currentVal; 165  } 166  } 167  } 168  169  /** 170  * Atomically adds the given value to the current value. 171  * 172  * @param delta the value to add 173  * @return the updated value 174  */ 175  @CanIgnoreReturnValue 176  public final double addAndGet(double delta) { 177  while (true) { 178  long current = value; 179  double currentVal = longBitsToDouble(current); 180  double nextVal = currentVal + delta; 181  long next = doubleToRawLongBits(nextVal); 182  if (updater.compareAndSet(this, current, next)) { 183  return nextVal; 184  } 185  } 186  } 187  188  /** 189  * Returns the String representation of the current value. 190  * 191  * @return the String representation of the current value 192  */ 193  @Override 194  public String toString() { 195  return Double.toString(get()); 196  } 197  198  /** 199  * Returns the value of this {@code AtomicDouble} as an {@code int} after a narrowing primitive 200  * conversion. 201  */ 202  @Override 203  public int intValue() { 204  return (int) get(); 205  } 206  207  /** 208  * Returns the value of this {@code AtomicDouble} as a {@code long} after a narrowing primitive 209  * conversion. 210  */ 211  @Override 212  public long longValue() { 213  return (long) get(); 214  } 215  216  /** 217  * Returns the value of this {@code AtomicDouble} as a {@code float} after a narrowing primitive 218  * conversion. 219  */ 220  @Override 221  public float floatValue() { 222  return (float) get(); 223  } 224  225  /** Returns the value of this {@code AtomicDouble} as a {@code double}. */ 226  @Override 227  public double doubleValue() { 228  return get(); 229  } 230  231  /** 232  * Saves the state to a stream (that is, serializes it). 233  * 234  * @serialData The current value is emitted (a {@code double}). 235  */ 236  private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException { 237  s.defaultWriteObject(); 238  239  s.writeDouble(get()); 240  } 241  242  /** Reconstitutes the instance from a stream (that is, deserializes it). */ 243  private void readObject(java.io.ObjectInputStream s) 244  throws java.io.IOException, ClassNotFoundException { 245  s.defaultReadObject(); 246  247  set(s.readDouble()); 248  } 249 }