ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jsr166e/DoubleAdder.java
Revision: 1.10
Committed: Mon Jan 14 20:30:22 2013 UTC (11 years, 3 months ago) by jsr166
Branch: MAIN
Changes since 1.9: +1 -1 lines
Log Message:
javadoc wordsmithing

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