ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jsr166e/DoubleAdder.java
Revision: 1.7
Committed: Sun Jan 6 18:50:00 2013 UTC (11 years, 3 months ago) by jsr166
Branch: MAIN
Changes since 1.6: +1 -1 lines
Log Message:
javadoc style

File Contents

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