DoubleAdder.java revision 29957558cf0db700bfaae360a80c42dc3871d0e5
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 java.io.Serializable;
39
40/**
41 * One or more variables that together maintain an initially zero
42 * {@code double} sum.  When updates (method {@link #add}) are
43 * contended across threads, the set of variables may grow dynamically
44 * to reduce contention.  Method {@link #sum} (or, equivalently {@link
45 * #doubleValue}) returns the current total combined across the
46 * variables maintaining the sum. The order of accumulation within or
47 * across threads is not guaranteed. Thus, this class may not be
48 * applicable if numerical stability is required, especially when
49 * combining values of substantially different orders of magnitude.
50 *
51 * <p>This class is usually preferable to alternatives when multiple
52 * threads update a common value that is used for purposes such as
53 * summary statistics that are frequently updated but less frequently
54 * read.
55 *
56 * <p>This class extends {@link Number}, but does <em>not</em> define
57 * methods such as {@code equals}, {@code hashCode} and {@code
58 * compareTo} because instances are expected to be mutated, and so are
59 * not useful as collection keys.
60 *
61 * @since 1.8
62 * @author Doug Lea
63 */
64public class DoubleAdder extends Striped64 implements Serializable {
65    private static final long serialVersionUID = 7249069246863182397L;
66
67    /*
68     * Note that we must use "long" for underlying representations,
69     * because there is no compareAndSet for double, due to the fact
70     * that the bitwise equals used in any CAS implementation is not
71     * the same as double-precision equals.  However, we use CAS only
72     * to detect and alleviate contention, for which bitwise equals
73     * works best anyway. In principle, the long/double conversions
74     * used here should be essentially free on most platforms since
75     * they just re-interpret bits.
76     */
77
78    /**
79     * Creates a new adder with initial sum of zero.
80     */
81    public DoubleAdder() {
82    }
83
84    /**
85     * Adds the given value.
86     *
87     * @param x the value to add
88     */
89    public void add(double x) {
90        Cell[] as; long b, v; int m; Cell a;
91        if ((as = cells) != null ||
92            !casBase(b = base,
93                     Double.doubleToRawLongBits
94                     (Double.longBitsToDouble(b) + x))) {
95            boolean uncontended = true;
96            if (as == null || (m = as.length - 1) < 0 ||
97                (a = as[getProbe() & m]) == null ||
98                !(uncontended = a.cas(v = a.value,
99                                      Double.doubleToRawLongBits
100                                      (Double.longBitsToDouble(v) + x))))
101                doubleAccumulate(x, null, uncontended);
102        }
103    }
104
105    /**
106     * Returns the current sum.  The returned value is <em>NOT</em> an
107     * atomic snapshot; invocation in the absence of concurrent
108     * updates returns an accurate result, but concurrent updates that
109     * occur while the sum is being calculated might not be
110     * incorporated.  Also, because floating-point arithmetic is not
111     * strictly associative, the returned result need not be identical
112     * to the value that would be obtained in a sequential series of
113     * updates to a single variable.
114     *
115     * @return the sum
116     */
117    public double sum() {
118        Cell[] as = cells;
119        double sum = Double.longBitsToDouble(base);
120        if (as != null) {
121            for (Cell a : as)
122                if (a != null)
123                    sum += Double.longBitsToDouble(a.value);
124        }
125        return sum;
126    }
127
128    /**
129     * Resets variables maintaining the sum to zero.  This method may
130     * be a useful alternative to creating a new adder, but is only
131     * effective if there are no concurrent updates.  Because this
132     * method is intrinsically racy, it should only be used when it is
133     * known that no threads are concurrently updating.
134     */
135    public void reset() {
136        Cell[] as = cells;
137        base = 0L; // relies on fact that double 0 must have same rep as long
138        if (as != null) {
139            for (Cell a : as)
140                if (a != null)
141                    a.reset();
142        }
143    }
144
145    /**
146     * Equivalent in effect to {@link #sum} followed by {@link
147     * #reset}. This method may apply for example during quiescent
148     * points between multithreaded computations.  If there are
149     * updates concurrent with this method, the returned value is
150     * <em>not</em> guaranteed to be the final value occurring before
151     * the reset.
152     *
153     * @return the sum
154     */
155    public double sumThenReset() {
156        Cell[] as = cells;
157        double sum = Double.longBitsToDouble(base);
158        base = 0L;
159        if (as != null) {
160            for (Cell a : as) {
161                if (a != null) {
162                    long v = a.value;
163                    a.reset();
164                    sum += Double.longBitsToDouble(v);
165                }
166            }
167        }
168        return sum;
169    }
170
171    /**
172     * Returns the String representation of the {@link #sum}.
173     * @return the String representation of the {@link #sum}
174     */
175    public String toString() {
176        return Double.toString(sum());
177    }
178
179    /**
180     * Equivalent to {@link #sum}.
181     *
182     * @return the sum
183     */
184    public double doubleValue() {
185        return sum();
186    }
187
188    /**
189     * Returns the {@link #sum} as a {@code long} after a
190     * narrowing primitive conversion.
191     */
192    public long longValue() {
193        return (long)sum();
194    }
195
196    /**
197     * Returns the {@link #sum} as an {@code int} after a
198     * narrowing primitive conversion.
199     */
200    public int intValue() {
201        return (int)sum();
202    }
203
204    /**
205     * Returns the {@link #sum} as a {@code float}
206     * after a narrowing primitive conversion.
207     */
208    public float floatValue() {
209        return (float)sum();
210    }
211
212    /**
213     * Serialization proxy, used to avoid reference to the non-public
214     * Striped64 superclass in serialized forms.
215     * @serial include
216     */
217    private static class SerializationProxy implements Serializable {
218        private static final long serialVersionUID = 7249069246863182397L;
219
220        /**
221         * The current value returned by sum().
222         * @serial
223         */
224        private final double value;
225
226        SerializationProxy(DoubleAdder a) {
227            value = a.sum();
228        }
229
230        /**
231         * Returns a {@code DoubleAdder} object with initial state
232         * held by this proxy.
233         *
234         * @return a {@code DoubleAdder} object with initial state
235         * held by this proxy
236         */
237        private Object readResolve() {
238            DoubleAdder a = new DoubleAdder();
239            a.base = Double.doubleToRawLongBits(value);
240            return a;
241        }
242    }
243
244    /**
245     * Returns a
246     * <a href="../../../../serialized-form.html#java.util.concurrent.atomic.DoubleAdder.SerializationProxy">
247     * SerializationProxy</a>
248     * representing the state of this instance.
249     *
250     * @return a {@link SerializationProxy}
251     * representing the state of this instance
252     */
253    private Object writeReplace() {
254        return new SerializationProxy(this);
255    }
256
257    /**
258     * @param s the stream
259     * @throws java.io.InvalidObjectException always
260     */
261    private void readObject(java.io.ObjectInputStream s)
262        throws java.io.InvalidObjectException {
263        throw new java.io.InvalidObjectException("Proxy required");
264    }
265
266}
267