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