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      */
DoubleAccumulator(DoubleBinaryOperator accumulatorFunction, double identity)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      */
accumulate(double x)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             int index = getProbe();
115             boolean uncontended = true;
116             if (cs == null
117                 || (m = cs.length - 1) < 0
118                 || (c = cs[index & m]) == null
119                 || !(uncontended =
120                      ((r = doubleToRawLongBits
121                        (function.applyAsDouble
122                         (longBitsToDouble(v = c.value), x))) == v)
123                      || c.cas(v, r)))
124                 doubleAccumulate(x, function, uncontended, index);
125         }
126     }
127 
128     /**
129      * Returns the current value.  The returned value is <em>NOT</em>
130      * an atomic snapshot; invocation in the absence of concurrent
131      * updates returns an accurate result, but concurrent updates that
132      * occur while the value is being calculated might not be
133      * incorporated.
134      *
135      * @return the current value
136      */
get()137     public double get() {
138         Cell[] cs = cells;
139         double result = longBitsToDouble(base);
140         if (cs != null) {
141             for (Cell c : cs)
142                 if (c != null)
143                     result = function.applyAsDouble
144                         (result, longBitsToDouble(c.value));
145         }
146         return result;
147     }
148 
149     /**
150      * Resets variables maintaining updates to the identity value.
151      * This method may be a useful alternative to creating a new
152      * updater, but is only effective if there are no concurrent
153      * updates.  Because this method is intrinsically racy, it should
154      * only be used when it is known that no threads are concurrently
155      * updating.
156      */
reset()157     public void reset() {
158         Cell[] cs = cells;
159         base = identity;
160         if (cs != null) {
161             for (Cell c : cs)
162                 if (c != null)
163                     c.reset(identity);
164         }
165     }
166 
167     /**
168      * Equivalent in effect to {@link #get} followed by {@link
169      * #reset}. This method may apply for example during quiescent
170      * points between multithreaded computations.  If there are
171      * updates concurrent with this method, the returned value is
172      * <em>not</em> guaranteed to be the final value occurring before
173      * the reset.
174      *
175      * @return the value before reset
176      */
getThenReset()177     public double getThenReset() {
178         Cell[] cs = cells;
179         double result = longBitsToDouble(getAndSetBase(identity));
180         if (cs != null) {
181             for (Cell c : cs) {
182                 if (c != null) {
183                     double v = longBitsToDouble(c.getAndSet(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      */
toString()195     public String toString() {
196         return Double.toString(get());
197     }
198 
199     /**
200      * Equivalent to {@link #get}.
201      *
202      * @return the current value
203      */
doubleValue()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      */
longValue()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      */
intValue()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      */
floatValue()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         @SuppressWarnings("serial") // Not statically typed as Serializable
251         private final DoubleBinaryOperator function;
252 
253         /**
254          * The identity value, represented as a long, as converted by
255          * {@link Double#doubleToRawLongBits}.  The original identity
256          * can be recovered using {@link Double#longBitsToDouble}.
257          * @serial
258          */
259         private final long identity;
260 
SerializationProxy(double value, DoubleBinaryOperator function, long identity)261         SerializationProxy(double value,
262                            DoubleBinaryOperator function,
263                            long identity) {
264             this.value = value;
265             this.function = function;
266             this.identity = identity;
267         }
268 
269         /**
270          * Returns a {@code DoubleAccumulator} object with initial state
271          * held by this proxy.
272          *
273          * @return a {@code DoubleAccumulator} object with initial state
274          * held by this proxy
275          */
readResolve()276         private Object readResolve() {
277             double d = longBitsToDouble(identity);
278             DoubleAccumulator a = new DoubleAccumulator(function, d);
279             a.base = doubleToRawLongBits(value);
280             return a;
281         }
282     }
283 
284     /**
285      * Returns a
286      * <a href="{@docRoot}/serialized-form.html#java.util.concurrent.atomic.DoubleAccumulator.SerializationProxy">
287      * SerializationProxy</a>
288      * representing the state of this instance.
289      *
290      * @return a {@link SerializationProxy}
291      * representing the state of this instance
292      */
writeReplace()293     private Object writeReplace() {
294         return new SerializationProxy(get(), function, identity);
295     }
296 
297     /**
298      * @param s the stream
299      * @throws java.io.InvalidObjectException always
300      */
readObject(java.io.ObjectInputStream s)301     private void readObject(java.io.ObjectInputStream s)
302         throws java.io.InvalidObjectException {
303         throw new java.io.InvalidObjectException("Proxy required");
304     }
305 
306 }
307