1/* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * 4 * This code is free software; you can redistribute it and/or modify it 5 * under the terms of the GNU General Public License version 2 only, as 6 * published by the Free Software Foundation. Oracle designates this 7 * particular file as subject to the "Classpath" exception as provided 8 * by Oracle in the LICENSE file that accompanied this code. 9 * 10 * This code is distributed in the hope that it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 * version 2 for more details (a copy is included in the LICENSE file that 14 * accompanied this code). 15 * 16 * You should have received a copy of the GNU General Public License version 17 * 2 along with this work; if not, write to the Free Software Foundation, 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 * 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 * or visit www.oracle.com if you need additional information or have any 22 * questions. 23 */ 24 25/* 26 * This file is available under and governed by the GNU General Public 27 * License version 2 only, as published by the Free Software Foundation. 28 * However, the following notice accompanied the original version of this 29 * file: 30 * 31 * Written by Doug Lea with assistance from members of JCP JSR-166 32 * Expert Group and released to the public domain, as explained at 33 * http://creativecommons.org/publicdomain/zero/1.0/ 34 */ 35 36package java.util.concurrent.atomic; 37 38import static java.lang.Double.doubleToRawLongBits; 39import static java.lang.Double.longBitsToDouble; 40 41import java.io.Serializable; 42import java.util.function.DoubleBinaryOperator; 43 44/** 45 * One or more variables that together maintain a running {@code double} 46 * value updated using a supplied function. When updates (method 47 * {@link #accumulate}) are contended across threads, the set of variables 48 * may grow dynamically to reduce contention. Method {@link #get} 49 * (or, equivalently, {@link #doubleValue}) returns the current value 50 * across the variables maintaining updates. 51 * 52 * <p>This class is usually preferable to alternatives when multiple 53 * threads update a common value that is used for purposes such as 54 * summary statistics that are frequently updated but less frequently 55 * read. 56 * 57 * <p>The supplied accumulator function should be side-effect-free, 58 * since it may be re-applied when attempted updates fail due to 59 * contention among threads. For predictable results, the accumulator 60 * function should be commutative and associative within the floating 61 * point tolerance required in usage contexts. The function is applied 62 * with an existing value (or identity) as one argument, and a given 63 * update as the other argument. For example, to maintain a running 64 * maximum value, you could supply {@code Double::max} along with 65 * {@code Double.NEGATIVE_INFINITY} as the identity. The order of 66 * accumulation within or across threads is not guaranteed. Thus, this 67 * class may not be applicable if numerical stability is required, 68 * especially when combining values of substantially different orders 69 * of magnitude. 70 * 71 * <p>Class {@link DoubleAdder} provides analogs of the functionality 72 * of this class for the common special case of maintaining sums. The 73 * call {@code new DoubleAdder()} is equivalent to {@code new 74 * DoubleAccumulator((x, y) -> x + y, 0.0)}. 75 * 76 * <p>This class extends {@link Number}, but does <em>not</em> define 77 * methods such as {@code equals}, {@code hashCode} and {@code 78 * compareTo} because instances are expected to be mutated, and so are 79 * not useful as collection keys. 80 * 81 * @since 1.8 82 * @author Doug Lea 83 */ 84public class DoubleAccumulator extends Striped64 implements Serializable { 85 private static final long serialVersionUID = 7249069246863182397L; 86 87 private final DoubleBinaryOperator function; 88 private final long identity; // use long representation 89 90 /** 91 * Creates a new instance using the given accumulator function 92 * and identity element. 93 * @param accumulatorFunction a side-effect-free function of two arguments 94 * @param identity identity (initial value) for the accumulator function 95 */ 96 public DoubleAccumulator(DoubleBinaryOperator accumulatorFunction, 97 double identity) { 98 this.function = accumulatorFunction; 99 base = this.identity = doubleToRawLongBits(identity); 100 } 101 102 /** 103 * Updates with the given value. 104 * 105 * @param x the value 106 */ 107 public void accumulate(double x) { 108 Cell[] as; long b, v, r; int m; Cell a; 109 if ((as = cells) != null 110 || ((r = doubleToRawLongBits 111 (function.applyAsDouble(longBitsToDouble(b = base), x))) != b 112 && !casBase(b, r))) { 113 boolean uncontended = true; 114 if (as == null 115 || (m = as.length - 1) < 0 116 || (a = as[getProbe() & m]) == null 117 || !(uncontended = 118 ((r = doubleToRawLongBits 119 (function.applyAsDouble 120 (longBitsToDouble(v = a.value), x))) == v) 121 || a.cas(v, r))) 122 doubleAccumulate(x, function, uncontended); 123 } 124 } 125 126 /** 127 * Returns the current value. The returned value is <em>NOT</em> 128 * an atomic snapshot; invocation in the absence of concurrent 129 * updates returns an accurate result, but concurrent updates that 130 * occur while the value is being calculated might not be 131 * incorporated. 132 * 133 * @return the current value 134 */ 135 public double get() { 136 Cell[] as = cells; 137 double result = longBitsToDouble(base); 138 if (as != null) { 139 for (Cell a : as) 140 if (a != null) 141 result = function.applyAsDouble 142 (result, longBitsToDouble(a.value)); 143 } 144 return result; 145 } 146 147 /** 148 * Resets variables maintaining updates to the identity value. 149 * This method may be a useful alternative to creating a new 150 * updater, but is only effective if there are no concurrent 151 * updates. Because this method is intrinsically racy, it should 152 * only be used when it is known that no threads are concurrently 153 * updating. 154 */ 155 public void reset() { 156 Cell[] as = cells; 157 base = identity; 158 if (as != null) { 159 for (Cell a : as) 160 if (a != null) 161 a.reset(identity); 162 } 163 } 164 165 /** 166 * Equivalent in effect to {@link #get} followed by {@link 167 * #reset}. This method may apply for example during quiescent 168 * points between multithreaded computations. If there are 169 * updates concurrent with this method, the returned value is 170 * <em>not</em> guaranteed to be the final value occurring before 171 * the reset. 172 * 173 * @return the value before reset 174 */ 175 public double getThenReset() { 176 Cell[] as = cells; 177 double result = longBitsToDouble(base); 178 base = identity; 179 if (as != null) { 180 for (Cell a : as) { 181 if (a != null) { 182 double v = longBitsToDouble(a.value); 183 a.reset(identity); 184 result = function.applyAsDouble(result, v); 185 } 186 } 187 } 188 return result; 189 } 190 191 /** 192 * Returns the String representation of the current value. 193 * @return the String representation of the current value 194 */ 195 public String toString() { 196 return Double.toString(get()); 197 } 198 199 /** 200 * Equivalent to {@link #get}. 201 * 202 * @return the current value 203 */ 204 public double doubleValue() { 205 return get(); 206 } 207 208 /** 209 * Returns the {@linkplain #get current value} as a {@code long} 210 * after a narrowing primitive conversion. 211 */ 212 public long longValue() { 213 return (long)get(); 214 } 215 216 /** 217 * Returns the {@linkplain #get current value} as an {@code int} 218 * after a narrowing primitive conversion. 219 */ 220 public int intValue() { 221 return (int)get(); 222 } 223 224 /** 225 * Returns the {@linkplain #get current value} as a {@code float} 226 * after a narrowing primitive conversion. 227 */ 228 public float floatValue() { 229 return (float)get(); 230 } 231 232 /** 233 * Serialization proxy, used to avoid reference to the non-public 234 * Striped64 superclass in serialized forms. 235 * @serial include 236 */ 237 private static class SerializationProxy implements Serializable { 238 private static final long serialVersionUID = 7249069246863182397L; 239 240 /** 241 * The current value returned by get(). 242 * @serial 243 */ 244 private final double value; 245 246 /** 247 * The function used for updates. 248 * @serial 249 */ 250 private final DoubleBinaryOperator function; 251 252 /** 253 * The identity value, represented as a long, as converted by 254 * {@link Double#doubleToRawLongBits}. The original identity 255 * can be recovered using {@link Double#longBitsToDouble}. 256 * @serial 257 */ 258 private final long identity; 259 260 SerializationProxy(double value, 261 DoubleBinaryOperator function, 262 long identity) { 263 this.value = value; 264 this.function = function; 265 this.identity = identity; 266 } 267 268 /** 269 * Returns a {@code DoubleAccumulator} object with initial state 270 * held by this proxy. 271 * 272 * @return a {@code DoubleAccumulator} object with initial state 273 * held by this proxy 274 */ 275 private Object readResolve() { 276 double d = longBitsToDouble(identity); 277 DoubleAccumulator a = new DoubleAccumulator(function, d); 278 a.base = doubleToRawLongBits(value); 279 return a; 280 } 281 } 282 283 /** 284 * Returns a 285 * <a href="../../../../serialized-form.html#java.util.concurrent.atomic.DoubleAccumulator.SerializationProxy"> 286 * SerializationProxy</a> 287 * representing the state of this instance. 288 * 289 * @return a {@link SerializationProxy} 290 * representing the state of this instance 291 */ 292 private Object writeReplace() { 293 return new SerializationProxy(get(), function, identity); 294 } 295 296 /** 297 * @param s the stream 298 * @throws java.io.InvalidObjectException always 299 */ 300 private void readObject(java.io.ObjectInputStream s) 301 throws java.io.InvalidObjectException { 302 throw new java.io.InvalidObjectException("Proxy required"); 303 } 304 305} 306