ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jsr166e/DoubleAdder.java
Revision: 1.12
Committed: Mon May 5 20:20:15 2014 UTC (9 years, 11 months ago) by jsr166
Branch: MAIN
CVS Tags: HEAD
Changes since 1.11: +7 -4 lines
Log Message:
import everything to reduce diffs with guava fork

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