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     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      */
DoubleAccumulator(DoubleBinaryOperator accumulatorFunction, double identity)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      */
accumulate(double x)107     public void accumulate(double x) {
108         Cell[] cs; long b, v, r; int m; Cell c;
109         if ((cs = cells) != null
110             || ((r = doubleToRawLongBits
111                 (function.applyAsDouble(longBitsToDouble(b = base), x))) != b
112                 && !casBase(b, r))) {
113             boolean uncontended = true;
114             if (cs == null
115                 || (m = cs.length - 1) < 0
116                 || (c = cs[getProbe() & m]) == null
117                 || !(uncontended =
118                      ((r = doubleToRawLongBits
119                        (function.applyAsDouble
120                         (longBitsToDouble(v = c.value), x))) == v)
121                      || c.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      */
get()135     public double get() {
136         Cell[] cs = cells;
137         double result = longBitsToDouble(base);
138         if (cs != null) {
139             for (Cell c : cs)
140                 if (c != null)
141                     result = function.applyAsDouble
142                         (result, longBitsToDouble(c.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      */
reset()155     public void reset() {
156         Cell[] cs = cells;
157         base = identity;
158         if (cs != null) {
159             for (Cell c : cs)
160                 if (c != null)
161                     c.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      */
getThenReset()175     public double getThenReset() {
176         Cell[] cs = cells;
177         double result = longBitsToDouble(getAndSetBase(identity));
178         if (cs != null) {
179             for (Cell c : cs) {
180                 if (c != null) {
181                     double v = longBitsToDouble(c.getAndSet(identity));
182                     result = function.applyAsDouble(result, v);
183                 }
184             }
185         }
186         return result;
187     }
188 
189     /**
190      * Returns the String representation of the current value.
191      * @return the String representation of the current value
192      */
toString()193     public String toString() {
194         return Double.toString(get());
195     }
196 
197     /**
198      * Equivalent to {@link #get}.
199      *
200      * @return the current value
201      */
doubleValue()202     public double doubleValue() {
203         return get();
204     }
205 
206     /**
207      * Returns the {@linkplain #get current value} as a {@code long}
208      * after a narrowing primitive conversion.
209      */
longValue()210     public long longValue() {
211         return (long)get();
212     }
213 
214     /**
215      * Returns the {@linkplain #get current value} as an {@code int}
216      * after a narrowing primitive conversion.
217      */
intValue()218     public int intValue() {
219         return (int)get();
220     }
221 
222     /**
223      * Returns the {@linkplain #get current value} as a {@code float}
224      * after a narrowing primitive conversion.
225      */
floatValue()226     public float floatValue() {
227         return (float)get();
228     }
229 
230     /**
231      * Serialization proxy, used to avoid reference to the non-public
232      * Striped64 superclass in serialized forms.
233      * @serial include
234      */
235     private static class SerializationProxy implements Serializable {
236         private static final long serialVersionUID = 7249069246863182397L;
237 
238         /**
239          * The current value returned by get().
240          * @serial
241          */
242         private final double value;
243 
244         /**
245          * The function used for updates.
246          * @serial
247          */
248         private final DoubleBinaryOperator function;
249 
250         /**
251          * The identity value, represented as a long, as converted by
252          * {@link Double#doubleToRawLongBits}.  The original identity
253          * can be recovered using {@link Double#longBitsToDouble}.
254          * @serial
255          */
256         private final long identity;
257 
SerializationProxy(double value, DoubleBinaryOperator function, long identity)258         SerializationProxy(double value,
259                            DoubleBinaryOperator function,
260                            long identity) {
261             this.value = value;
262             this.function = function;
263             this.identity = identity;
264         }
265 
266         /**
267          * Returns a {@code DoubleAccumulator} object with initial state
268          * held by this proxy.
269          *
270          * @return a {@code DoubleAccumulator} object with initial state
271          * held by this proxy
272          */
readResolve()273         private Object readResolve() {
274             double d = longBitsToDouble(identity);
275             DoubleAccumulator a = new DoubleAccumulator(function, d);
276             a.base = doubleToRawLongBits(value);
277             return a;
278         }
279     }
280 
281     /**
282      * Returns a
283      * <a href="../../../../serialized-form.html#java.util.concurrent.atomic.DoubleAccumulator.SerializationProxy">
284      * SerializationProxy</a>
285      * representing the state of this instance.
286      *
287      * @return a {@link SerializationProxy}
288      * representing the state of this instance
289      */
writeReplace()290     private Object writeReplace() {
291         return new SerializationProxy(get(), function, identity);
292     }
293 
294     /**
295      * @param s the stream
296      * @throws java.io.InvalidObjectException always
297      */
readObject(java.io.ObjectInputStream s)298     private void readObject(java.io.ObjectInputStream s)
299         throws java.io.InvalidObjectException {
300         throw new java.io.InvalidObjectException("Proxy required");
301     }
302 
303 }
304