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 * Source: http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/src/jsr166e/DoubleAdder.java?revision=1.12 007 */ 008 009package io.prometheus.client; 010 011import java.io.IOException; 012import java.io.ObjectInputStream; 013import java.io.ObjectOutputStream; 014import java.io.Serializable; 015 016/** 017 * One or more variables that together maintain an initially zero 018 * {@code double} sum. When updates (method {@link #add}) are 019 * contended across threads, the set of variables may grow dynamically 020 * to reduce contention. Method {@link #sum} (or, equivalently {@link 021 * #doubleValue}) returns the current total combined across the 022 * variables maintaining the sum. 023 * 024 * <p>This class extends {@link Number}, but does <em>not</em> define 025 * methods such as {@code equals}, {@code hashCode} and {@code 026 * compareTo} because instances are expected to be mutated, and so are 027 * not useful as collection keys. 028 * 029 * <p><em>jsr166e note: This class is targeted to be placed in 030 * java.util.concurrent.atomic.</em> 031 * 032 * @since 1.8 033 * @author Doug Lea 034 */ 035public class DoubleAdder extends Striped64 implements Serializable { 036 private static final long serialVersionUID = 7249069246863182397L; 037 038 /** 039 * Update function. Note that we must use "long" for underlying 040 * representations, because there is no compareAndSet for double, 041 * due to the fact that the bitwise equals used in any CAS 042 * implementation is not the same as double-precision equals. 043 * However, we use CAS only to detect and alleviate contention, 044 * for which bitwise equals works best anyway. In principle, the 045 * long/double conversions used here should be essentially free on 046 * most platforms since they just re-interpret bits. 047 * 048 * Similar conversions are used in other methods. 049 */ 050 final long fn(long v, long x) { 051 return Double.doubleToRawLongBits 052 (Double.longBitsToDouble(v) + 053 Double.longBitsToDouble(x)); 054 } 055 056 /** 057 * Creates a new adder with initial sum of zero. 058 */ 059 public DoubleAdder() { 060 } 061 062 /** 063 * Adds the given value. 064 * 065 * @param x the value to add 066 */ 067 public void add(double x) { 068 Cell[] as; long b, v; int[] hc; Cell a; int n; 069 if ((as = cells) != null || 070 !casBase(b = base, 071 Double.doubleToRawLongBits 072 (Double.longBitsToDouble(b) + x))) { 073 boolean uncontended = true; 074 if ((hc = threadHashCode.get()) == null || 075 as == null || (n = as.length) < 1 || 076 (a = as[(n - 1) & hc[0]]) == null || 077 !(uncontended = a.cas(v = a.value, 078 Double.doubleToRawLongBits 079 (Double.longBitsToDouble(v) + x)))) 080 retryUpdate(Double.doubleToRawLongBits(x), hc, uncontended); 081 } 082 } 083 084 /** 085 * Returns the current sum. The returned value is <em>NOT</em> an 086 * atomic snapshot; invocation in the absence of concurrent 087 * updates returns an accurate result, but concurrent updates that 088 * occur while the sum is being calculated might not be 089 * incorporated. Also, because floating-point arithmetic is not 090 * strictly associative, the returned result need not be identical 091 * to the value that would be obtained in a sequential series of 092 * updates to a single variable. 093 * 094 * @return the sum 095 */ 096 public double sum() { 097 // On concurrent `sum` and `set`, it is acceptable to `get` an outdated `value`. 098 // On concurrent `sum` and `add`, it is acceptable to `get` an outdated `value`. 099 // On concurrent `sum` and `set` and `add`, it is possible to `get` an outdated `value`. 100 101 // Correctness is guaranteed by `volatile` memory access ordering and visibility semantics. 102 // Program order: 103 // - writes in `set` - `busy` (CAS), `cells` (Wc), `base` (Wb), `busy` 104 // - reads in `sum` - `cells` (Rc), `base` (Rb), `busy`, `cells` (Cc), `base` (Cb) 105 // Note that: 106 // - `busy` is written after `cells` and `base` 107 // - `busy` is read after `cells` and `base`, then `cells` and `base` is re-read after `busy` 108 // In other words: 109 // - if we see the write to `busy`, then we must see the write to `cells` and `busy` on re-read 110 // - if we don't see the write to `busy`, then we must retry as we have no guarantees 111 // Execution order (in the former case): 112 // - serial 113 // - old result - Rc, Rb, Cc, Cb, Wc, Wb 114 // - new result - Wc, Wb, Rc, Rb, Cc, Cb 115 // - concurrent 116 // - old result - Rc, Wc, Rb, Wb, Cc, Cb - retry (superfluous) 117 // - new result - Wc, Rc, Wb, Rb, Cc, Cb 118 // - invalid result - Rc, Wc, Wb, Rb, Cc, Cb - retry 119 // - invalid result - Wc, Rc, Rb, Wb, Cc, Cb - retry 120 Cell[] as = cells; long b = base; 121 while (as != null && !(busy == 0 && cells == as && base == b)) { 122 // busy waiting, retry loop 123 Thread.yield(); 124 as = cells; b = base; 125 } 126 127 double sum = Double.longBitsToDouble(b); 128 if (as != null) { 129 int n = as.length; 130 for (int i = 0; i < n; ++i) { 131 Cell a = as[i]; 132 if (a != null) 133 sum += Double.longBitsToDouble(a.value); 134 } 135 } 136 return sum; 137 } 138 139 /** 140 * Resets variables maintaining the sum to zero. This method may 141 * be a useful alternative to creating a new adder, but is only 142 * effective if there are no concurrent updates. Because this 143 * method is intrinsically racy, it should only be used when it is 144 * known that no threads are concurrently updating. 145 */ 146 public void reset() { 147 internalReset(0L); 148 } 149 150 public void set(double x) { 151 // On concurrent `set` and `set`, it should be acceptable to lose one `set` measurement. 152 // On concurrent `set` and `add`, it should be acceptable to lose the `add` measurement. 153 154 // Correctness is ensured by different techniques: 155 // - `set` waits on contention (blocking) 156 // - `add` avoids contention (non-blocking) 157 // - `sum` retries on conflicts (non-blocking) 158 // Performance characteristics by use cases: 159 // - only `set` - `cells` is always `null` - no allocations 160 // - only `add` - `cells` allocated on contention 161 // - mixed `set` and `add` - `cells` allocated on contention, `cells` deallocated on `set` 162 for (;;) { 163 Cell[] as; 164 if ((as = cells) != null) { // have cells 165 if (busy == 0 && casBusy()) { 166 try { 167 if (cells == as) { // recheck under lock 168 // update cells and base (not atomic) 169 cells = null; 170 base = Double.doubleToLongBits(x); 171 break; 172 } 173 } finally { 174 busy = 0; 175 } 176 } 177 } else { // no cells 178 // update base (atomic) 179 base = Double.doubleToLongBits(x); 180 break; 181 } 182 } 183 } 184 185 /** 186 * Equivalent in effect to {@link #sum} followed by {@link 187 * #reset}. This method may apply for example during quiescent 188 * points between multithreaded computations. If there are 189 * updates concurrent with this method, the returned value is 190 * <em>not</em> guaranteed to be the final value occurring before 191 * the reset. 192 * 193 * @return the sum 194 */ 195 public double sumThenReset() { 196 Cell[] as = cells; 197 double sum = Double.longBitsToDouble(base); 198 base = 0L; 199 if (as != null) { 200 int n = as.length; 201 for (int i = 0; i < n; ++i) { 202 Cell a = as[i]; 203 if (a != null) { 204 long v = a.value; 205 a.value = 0L; 206 sum += Double.longBitsToDouble(v); 207 } 208 } 209 } 210 return sum; 211 } 212 213 /** 214 * Returns the String representation of the {@link #sum}. 215 * @return the String representation of the {@link #sum} 216 */ 217 public String toString() { 218 return Double.toString(sum()); 219 } 220 221 /** 222 * Equivalent to {@link #sum}. 223 * 224 * @return the sum 225 */ 226 public double doubleValue() { 227 return sum(); 228 } 229 230 /** 231 * Returns the {@link #sum} as a {@code long} after a 232 * narrowing primitive conversion. 233 */ 234 public long longValue() { 235 return (long)sum(); 236 } 237 238 /** 239 * Returns the {@link #sum} as an {@code int} after a 240 * narrowing primitive conversion. 241 */ 242 public int intValue() { 243 return (int)sum(); 244 } 245 246 /** 247 * Returns the {@link #sum} as a {@code float} 248 * after a narrowing primitive conversion. 249 */ 250 public float floatValue() { 251 return (float)sum(); 252 } 253 254 private void writeObject(ObjectOutputStream s) throws IOException { 255 s.defaultWriteObject(); 256 s.writeDouble(sum()); 257 } 258 259 private void readObject(ObjectInputStream s) 260 throws IOException, ClassNotFoundException { 261 s.defaultReadObject(); 262 busy = 0; 263 cells = null; 264 base = Double.doubleToRawLongBits(s.readDouble()); 265 } 266 267}