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 36 package java.util.concurrent.atomic; 37 38 import static java.lang.Double.doubleToRawLongBits; 39 import static java.lang.Double.longBitsToDouble; 40 41 import java.io.Serializable; 42 import 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 */ 84 public class DoubleAccumulator extends Striped64 implements Serializable { 85 private static final long serialVersionUID = 7249069246863182397L; 86 87 @SuppressWarnings("serial") // Not statically typed as Serializable 88 private final DoubleBinaryOperator function; 89 private final long identity; // use long representation 90 91 /** 92 * Creates a new instance using the given accumulator function 93 * and identity element. 94 * @param accumulatorFunction a side-effect-free function of two arguments 95 * @param identity identity (initial value) for the accumulator function 96 */ 97 public DoubleAccumulator(DoubleBinaryOperator accumulatorFunction, 98 double identity) { 99 this.function = accumulatorFunction; 100 base = this.identity = doubleToRawLongBits(identity); 101 } 102 103 /** 104 * Updates with the given value. 105 * 106 * @param x the value 107 */ 108 public void accumulate(double x) { 109 Cell[] cs; long b, v, r; int m; Cell c; 110 if ((cs = cells) != null 111 || ((r = doubleToRawLongBits 112 (function.applyAsDouble(longBitsToDouble(b = base), x))) != b 113 && !casBase(b, r))) { 114 boolean uncontended = true; 115 if (cs == null 116 || (m = cs.length - 1) < 0 117 || (c = cs[getProbe() & m]) == null 118 || !(uncontended = 119 ((r = doubleToRawLongBits 120 (function.applyAsDouble 121 (longBitsToDouble(v = c.value), x))) == v) 122 || c.cas(v, r))) 123 doubleAccumulate(x, function, uncontended); 124 } 125 } 126 127 /** 128 * Returns the current value. The returned value is <em>NOT</em> 129 * an atomic snapshot; invocation in the absence of concurrent 130 * updates returns an accurate result, but concurrent updates that 131 * occur while the value is being calculated might not be 132 * incorporated. 133 * 134 * @return the current value 135 */ 136 public double get() { 137 Cell[] cs = cells; 138 double result = longBitsToDouble(base); 139 if (cs != null) { 140 for (Cell c : cs) 141 if (c != null) 142 result = function.applyAsDouble 143 (result, longBitsToDouble(c.value)); 144 } 145 return result; 146 } 147 148 /** 149 * Resets variables maintaining updates to the identity value. 150 * This method may be a useful alternative to creating a new 151 * updater, but is only effective if there are no concurrent 152 * updates. Because this method is intrinsically racy, it should 153 * only be used when it is known that no threads are concurrently 154 * updating. 155 */ 156 public void reset() { 157 Cell[] cs = cells; 158 base = identity; 159 if (cs != null) { 160 for (Cell c : cs) 161 if (c != null) 162 c.reset(identity); 163 } 164 } 165 166 /** 167 * Equivalent in effect to {@link #get} followed by {@link 168 * #reset}. This method may apply for example during quiescent 169 * points between multithreaded computations. If there are 170 * updates concurrent with this method, the returned value is 171 * <em>not</em> guaranteed to be the final value occurring before 172 * the reset. 173 * 174 * @return the value before reset 175 */ 176 public double getThenReset() { 177 Cell[] cs = cells; 178 double result = longBitsToDouble(getAndSetBase(identity)); 179 if (cs != null) { 180 for (Cell c : cs) { 181 if (c != null) { 182 double v = longBitsToDouble(c.getAndSet(identity)); 183 result = function.applyAsDouble(result, v); 184 } 185 } 186 } 187 return result; 188 } 189 190 /** 191 * Returns the String representation of the current value. 192 * @return the String representation of the current value 193 */ 194 public String toString() { 195 return Double.toString(get()); 196 } 197 198 /** 199 * Equivalent to {@link #get}. 200 * 201 * @return the current value 202 */ 203 public double doubleValue() { 204 return get(); 205 } 206 207 /** 208 * Returns the {@linkplain #get current value} as a {@code long} 209 * after a narrowing primitive conversion. 210 */ 211 public long longValue() { 212 return (long)get(); 213 } 214 215 /** 216 * Returns the {@linkplain #get current value} as an {@code int} 217 * after a narrowing primitive conversion. 218 */ 219 public int intValue() { 220 return (int)get(); 221 } 222 223 /** 224 * Returns the {@linkplain #get current value} as a {@code float} 225 * after a narrowing primitive conversion. 226 */ 227 public float floatValue() { 228 return (float)get(); 229 } 230 231 /** 232 * Serialization proxy, used to avoid reference to the non-public 233 * Striped64 superclass in serialized forms. 234 * @serial include 235 */ 236 private static class SerializationProxy implements Serializable { 237 private static final long serialVersionUID = 7249069246863182397L; 238 239 /** 240 * The current value returned by get(). 241 * @serial 242 */ 243 private final double value; 244 245 /** 246 * The function used for updates. 247 * @serial 248 */ 249 @SuppressWarnings("serial") // Not statically typed as Serializable 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="{@docRoot}/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 }