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 java.io.Serializable;
39 import java.util.function.DoubleBinaryOperator;
40 
41 /**
42  * One or more variables that together maintain a running {@code double}
43  * value updated using a supplied function.  When updates (method
44  * {@link #accumulate}) are contended across threads, the set of variables
45  * may grow dynamically to reduce contention.  Method {@link #get}
46  * (or, equivalently, {@link #doubleValue}) returns the current value
47  * across the variables maintaining updates.
48  *
49  * <p>This class is usually preferable to alternatives when multiple
50  * threads update a common value that is used for purposes such as
51  * summary statistics that are frequently updated but less frequently
52  * read.
53  *
54  * <p>The supplied accumulator function should be side-effect-free,
55  * since it may be re-applied when attempted updates fail due to
56  * contention among threads. The function is applied with the current
57  * value as its first argument, and the given update as the second
58  * argument.  For example, to maintain a running maximum value, you
59  * could supply {@code Double::max} along with {@code
60  * Double.NEGATIVE_INFINITY} as the identity. The order of
61  * accumulation within or across threads is not guaranteed. Thus, this
62  * class may not be applicable if numerical stability is required,
63  * especially when combining values of substantially different orders
64  * of magnitude.
65  *
66  * <p>Class {@link DoubleAdder} provides analogs of the functionality
67  * of this class for the common special case of maintaining sums.  The
68  * call {@code new DoubleAdder()} is equivalent to {@code new
69  * DoubleAccumulator((x, y) -> x + y, 0.0)}.
70  *
71  * <p>This class extends {@link Number}, but does <em>not</em> define
72  * methods such as {@code equals}, {@code hashCode} and {@code
73  * compareTo} because instances are expected to be mutated, and so are
74  * not useful as collection keys.
75  *
76  * @since 1.8
77  * @author Doug Lea
78  */
79 public class DoubleAccumulator extends Striped64 implements Serializable {
80     private static final long serialVersionUID = 7249069246863182397L;
81 
82     private final DoubleBinaryOperator function;
83     private final long identity; // use long representation
84 
85     /**
86      * Creates a new instance using the given accumulator function
87      * and identity element.
88      * @param accumulatorFunction a side-effect-free function of two arguments
89      * @param identity identity (initial value) for the accumulator function
90      */
DoubleAccumulator(DoubleBinaryOperator accumulatorFunction, double identity)91     public DoubleAccumulator(DoubleBinaryOperator accumulatorFunction,
92                              double identity) {
93         this.function = accumulatorFunction;
94         base = this.identity = Double.doubleToRawLongBits(identity);
95     }
96 
97     /**
98      * Updates with the given value.
99      *
100      * @param x the value
101      */
accumulate(double x)102     public void accumulate(double x) {
103         Cell[] as; long b, v, r; int m; Cell a;
104         if ((as = cells) != null ||
105             (r = Double.doubleToRawLongBits
106              (function.applyAsDouble
107               (Double.longBitsToDouble(b = base), x))) != b  && !casBase(b, r)) {
108             boolean uncontended = true;
109             if (as == null || (m = as.length - 1) < 0 ||
110                 (a = as[getProbe() & m]) == null ||
111                 !(uncontended =
112                   (r = Double.doubleToRawLongBits
113                    (function.applyAsDouble
114                     (Double.longBitsToDouble(v = a.value), x))) == v ||
115                   a.cas(v, r)))
116                 doubleAccumulate(x, function, uncontended);
117         }
118     }
119 
120     /**
121      * Returns the current value.  The returned value is <em>NOT</em>
122      * an atomic snapshot; invocation in the absence of concurrent
123      * updates returns an accurate result, but concurrent updates that
124      * occur while the value is being calculated might not be
125      * incorporated.
126      *
127      * @return the current value
128      */
get()129     public double get() {
130         Cell[] as = cells;
131         double result = Double.longBitsToDouble(base);
132         if (as != null) {
133             for (Cell a : as)
134                 if (a != null)
135                     result = function.applyAsDouble
136                         (result, Double.longBitsToDouble(a.value));
137         }
138         return result;
139     }
140 
141     /**
142      * Resets variables maintaining updates to the identity value.
143      * This method may be a useful alternative to creating a new
144      * updater, but is only effective if there are no concurrent
145      * updates.  Because this method is intrinsically racy, it should
146      * only be used when it is known that no threads are concurrently
147      * updating.
148      */
reset()149     public void reset() {
150         Cell[] as = cells;
151         base = identity;
152         if (as != null) {
153             for (Cell a : as)
154                 if (a != null)
155                     a.reset(identity);
156         }
157     }
158 
159     /**
160      * Equivalent in effect to {@link #get} followed by {@link
161      * #reset}. This method may apply for example during quiescent
162      * points between multithreaded computations.  If there are
163      * updates concurrent with this method, the returned value is
164      * <em>not</em> guaranteed to be the final value occurring before
165      * the reset.
166      *
167      * @return the value before reset
168      */
getThenReset()169     public double getThenReset() {
170         Cell[] as = cells;
171         double result = Double.longBitsToDouble(base);
172         base = identity;
173         if (as != null) {
174             for (Cell a : as) {
175                 if (a != null) {
176                     double v = Double.longBitsToDouble(a.value);
177                     a.reset(identity);
178                     result = function.applyAsDouble(result, v);
179                 }
180             }
181         }
182         return result;
183     }
184 
185     /**
186      * Returns the String representation of the current value.
187      * @return the String representation of the current value
188      */
toString()189     public String toString() {
190         return Double.toString(get());
191     }
192 
193     /**
194      * Equivalent to {@link #get}.
195      *
196      * @return the current value
197      */
doubleValue()198     public double doubleValue() {
199         return get();
200     }
201 
202     /**
203      * Returns the {@linkplain #get current value} as a {@code long}
204      * after a narrowing primitive conversion.
205      */
longValue()206     public long longValue() {
207         return (long)get();
208     }
209 
210     /**
211      * Returns the {@linkplain #get current value} as an {@code int}
212      * after a narrowing primitive conversion.
213      */
intValue()214     public int intValue() {
215         return (int)get();
216     }
217 
218     /**
219      * Returns the {@linkplain #get current value} as a {@code float}
220      * after a narrowing primitive conversion.
221      */
floatValue()222     public float floatValue() {
223         return (float)get();
224     }
225 
226     /**
227      * Serialization proxy, used to avoid reference to the non-public
228      * Striped64 superclass in serialized forms.
229      * @serial include
230      */
231     private static class SerializationProxy implements Serializable {
232         private static final long serialVersionUID = 7249069246863182397L;
233 
234         /**
235          * The current value returned by get().
236          * @serial
237          */
238         private final double value;
239 
240         /**
241          * The function used for updates.
242          * @serial
243          */
244         private final DoubleBinaryOperator function;
245 
246         /**
247          * The identity value, represented as a long, as converted by
248          * {@link Double#doubleToRawLongBits}.  The original identity
249          * can be recovered using {@link Double#longBitsToDouble}.
250          * @serial
251          */
252         private final long identity;
253 
SerializationProxy(double value, DoubleBinaryOperator function, long identity)254         SerializationProxy(double value,
255                            DoubleBinaryOperator function,
256                            long identity) {
257             this.value = value;
258             this.function = function;
259             this.identity = identity;
260         }
261 
262         /**
263          * Returns a {@code DoubleAccumulator} object with initial state
264          * held by this proxy.
265          *
266          * @return a {@code DoubleAccumulator} object with initial state
267          * held by this proxy
268          */
readResolve()269         private Object readResolve() {
270             double d = Double.longBitsToDouble(identity);
271             DoubleAccumulator a = new DoubleAccumulator(function, d);
272             a.base = Double.doubleToRawLongBits(value);
273             return a;
274         }
275     }
276 
277     /**
278      * Returns a
279      * <a href="../../../../serialized-form.html#java.util.concurrent.atomic.DoubleAccumulator.SerializationProxy">
280      * SerializationProxy</a>
281      * representing the state of this instance.
282      *
283      * @return a {@link SerializationProxy}
284      * representing the state of this instance
285      */
writeReplace()286     private Object writeReplace() {
287         return new SerializationProxy(get(), function, identity);
288     }
289 
290     /**
291      * @param s the stream
292      * @throws java.io.InvalidObjectException always
293      */
readObject(java.io.ObjectInputStream s)294     private void readObject(java.io.ObjectInputStream s)
295         throws java.io.InvalidObjectException {
296         throw new java.io.InvalidObjectException("Proxy required");
297     }
298 
299 }
300