ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jsr166e/DoubleAdder.java
Revision: 1.1
Committed: Tue Aug 2 18:04:12 2011 UTC (12 years, 8 months ago) by dl
Branch: MAIN
Log Message:
Refactor and introduce new forms of update

File Contents

# User Rev Content
1 dl 1.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    
7     package jsr166e;
8     import java.io.IOException;
9     import java.io.Serializable;
10     import java.io.ObjectInputStream;
11     import java.io.ObjectOutputStream;
12    
13     /**
14     * One or more variables that together maintain an initially zero
15     * {@code double} sum. When updates (method {@link #add}) are
16     * contended across threads, the set of variables may grow dynamically
17     * to reduce contention. Method {@link #sum} (or, equivalently {@link
18     * #doubleValue}) returns the current total combined across the
19     * variables maintaining the sum.
20     *
21     * <p>This class extends {@link Number}, but does <em>not</em> define
22     * methods such as {@code hashCode} and {@code compareTo} because
23     * instances are expected to be mutated, and so are not useful as
24     * collection keys.
25     *
26     * <p><em>jsr166e note: This class is targeted to be placed in
27     * java.util.concurrent.atomic<em>
28     *
29     * @author Doug Lea
30     */
31     public class DoubleAdder extends Striped64 implements Serializable {
32     private static final long serialVersionUID = 7249069246863182397L;
33    
34     /**
35     * Update function. Note that we must use "long" for underlying
36     * representations, because there is no compareAndSet for double,
37     * due to the fact that the bitwise equals used in any CAS
38     * implementation is not the same as double-precision equals.
39     * However, we use CAS only to detect and alleviate contention,
40     * for which bitwise equals works best anyway. In principle, the
41     * long/double conversions used here should be essentially free on
42     * most platforms since they just re-interpret bits.
43     *
44     * Similar conversions are used in other methods.
45     */
46     final long fn(long v, long x) {
47     return Double.doubleToRawLongBits
48     (Double.longBitsToDouble(v) +
49     Double.longBitsToDouble(x));
50     }
51    
52     /**
53     * Creates a new adder with initial sum of zero.
54     */
55     public DoubleAdder() {
56     }
57    
58     /**
59     * Adds the given value.
60     *
61     * @param x the value to add
62     */
63     public void add(double x) {
64     Cell[] as; long b, v; HashCode hc; Cell a; int n;
65     if ((as = cells) != null ||
66     !casBase(b = base,
67     Double.doubleToRawLongBits
68     (Double.longBitsToDouble(b) + x))) {
69     boolean uncontended = true;
70     int h = (hc = threadHashCode.get()).code;
71     if (as == null || (n = as.length) < 1 ||
72     (a = as[(n - 1) & h]) == null ||
73     !(uncontended = a.cas(v = a.value,
74     Double.doubleToRawLongBits
75     (Double.longBitsToDouble(v) + x))))
76     retryUpdate(Double.doubleToRawLongBits(x), hc, uncontended);
77     }
78     }
79    
80     /**
81     * Returns the current sum. The returned value is <em>NOT</em> an
82     * atomic snapshot: Invocation in the absence of concurrent
83     * updates returns an accurate result, but concurrent updates that
84     * occur while the sum is being calculated might not be
85     * incorporated. Also, because double-precision arithmetic is not
86     * strictly associative, the returned result need not be identical
87     * to the value that would be obtained in a sequential series of
88     * updates to a single variable.
89     *
90     * @return the sum
91     */
92     public double sum() {
93     Cell[] as = cells;
94     double sum = Double.longBitsToDouble(base);
95     if (as != null) {
96     int n = as.length;
97     for (int i = 0; i < n; ++i) {
98     Cell a = as[i];
99     if (a != null)
100     sum += Double.longBitsToDouble(a.value);
101     }
102     }
103     return sum;
104     }
105    
106     /**
107     * Resets variables maintaining the sum to zero. This method may
108     * be a useful alternative to creating a new adder, but is only
109     * effective if there are no concurrent updates. Because this
110     * method is intrinsically racy, it should only be used when it is
111     * known that no threads are concurrently updating.
112     */
113     public void reset() {
114     internalReset(0L);
115     }
116    
117     /**
118     * Equivalent in effect to {@link #sum} followed by {@link
119     * #reset}. This method may apply for example during quiescent
120     * points between multithreaded computations. If there are
121     * updates concurrent with this method, the returned value is
122     * <em>not</em> guaranteed to be the final value occurring before
123     * the reset.
124     *
125     * @return the sum
126     */
127     public double sumThenReset() {
128     Cell[] as = cells;
129     double sum = Double.longBitsToDouble(base);
130     base = 0L;
131     if (as != null) {
132     int n = as.length;
133     for (int i = 0; i < n; ++i) {
134     Cell a = as[i];
135     if (a != null) {
136     long v = a.value;
137     a.value = 0L;
138     sum += Double.longBitsToDouble(v);
139     }
140     }
141     }
142     return sum;
143     }
144    
145     /**
146     * Returns the String representation of the {@link #sum}.
147     * @return the String representation of the {@link #sum}.
148     */
149     public String toString() {
150     return Double.toString(sum());
151     }
152    
153     /**
154     * Equivalent to {@link #sum}.
155     *
156     * @return the sum
157     */
158     public double doubleValue() {
159     return sum();
160     }
161    
162     /**
163     * Returns the {@link #sum} as a {@code long} after a
164     * primitive conversion.
165     */
166     public long longValue() {
167     return (long)sum();
168     }
169    
170     /**
171     * Returns the {@link #sum} as an {@code int} after a
172     * primitive conversion.
173     */
174     public int intValue() {
175     return (int)sum();
176     }
177    
178     /**
179     * Returns the {@link #sum} as a {@code float}
180     * after a primitive conversion.
181     */
182     public float floatValue() {
183     return (float)sum();
184     }
185    
186     private void writeObject(java.io.ObjectOutputStream s)
187     throws java.io.IOException {
188     s.defaultWriteObject();
189     s.writeDouble(sum());
190     }
191    
192     private void readObject(ObjectInputStream s)
193     throws IOException, ClassNotFoundException {
194     s.defaultReadObject();
195     busy = 0;
196     cells = null;
197     base = Double.doubleToRawLongBits(s.readDouble());
198     }
199    
200     }