ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jsr166e/LongAdder.java
Revision: 1.5
Committed: Tue Aug 2 18:04:12 2011 UTC (12 years, 9 months ago) by dl
Branch: MAIN
Changes since 1.4: +72 -299 lines
Log Message:
Refactor and introduce new forms of update

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.util.concurrent.atomic.AtomicLong;
9 import java.io.IOException;
10 import java.io.Serializable;
11 import java.io.ObjectInputStream;
12 import java.io.ObjectOutputStream;
13
14 /**
15 * One or more variables that together maintain an initially zero
16 * {@code long} sum. When updates (method {@link #add}) are contended
17 * across threads, the set of variables may grow dynamically to reduce
18 * contention. Method {@link #sum} (or, equivalently, {@link
19 * #longValue}) returns the current total combined across the
20 * variables maintaining the sum.
21 *
22 * <p> This class is usually preferable to {@link AtomicLong} when
23 * multiple threads update a common sum that is used for purposes such
24 * as collecting statistics, not for fine-grained synchronization
25 * control. Under low update contention, the two classes have similar
26 * characteristics. But under high contention, expected throughput of
27 * this class is significantly higher, at the expense of higher space
28 * consumption.
29 *
30 * <p>This class extends {@link Number}, but does <em>not</em> define
31 * methods such as {@code hashCode} and {@code compareTo} because
32 * instances are expected to be mutated, and so are not useful as
33 * collection keys.
34 *
35 * <p><em>jsr166e note: This class is targeted to be placed in
36 * java.util.concurrent.atomic<em>
37 *
38 * @author Doug Lea
39 */
40 public class LongAdder extends Striped64 implements Serializable {
41 private static final long serialVersionUID = 7249069246863182397L;
42
43 /**
44 * Version of plus for use in retryUpdate
45 */
46 final long fn(long v, long x) { return v + x; }
47
48 /**
49 * Creates a new adder with initial sum of zero.
50 */
51 public LongAdder() {
52 }
53
54 /**
55 * Adds the given value.
56 *
57 * @param x the value to add
58 */
59 public void add(long x) {
60 Cell[] as; long b, v; HashCode hc; Cell a; int n;
61 if ((as = cells) != null || !casBase(b = base, b + x)) {
62 boolean uncontended = true;
63 int h = (hc = threadHashCode.get()).code;
64 if (as == null || (n = as.length) < 1 ||
65 (a = as[(n - 1) & h]) == null ||
66 !(uncontended = a.cas(v = a.value, v + x)))
67 retryUpdate(x, hc, uncontended);
68 }
69 }
70
71 /**
72 * Equivalent to {@code add(1)}.
73 */
74 public void increment() {
75 add(1L);
76 }
77
78 /**
79 * Equivalent to {@code add(-1)}.
80 */
81 public void decrement() {
82 add(-1L);
83 }
84
85 /**
86 * Returns the current sum. The returned value is <em>NOT</em> an
87 * atomic snapshot: Invocation in the absence of concurrent
88 * updates returns an accurate result, but concurrent updates that
89 * occur while the sum is being calculated might not be
90 * incorporated.
91 *
92 * @return the sum
93 */
94 public long sum() {
95 Cell[] as = cells;
96 long sum = 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 += 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 long sumThenReset() {
130 Cell[] as = cells;
131 long sum = 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 += 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 Long.toString(sum());
153 }
154
155 /**
156 * Equivalent to {@link #sum}.
157 *
158 * @return the sum
159 */
160 public long longValue() {
161 return sum();
162 }
163
164 /**
165 * Returns the {@link #sum} as an {@code int} after a narrowing
166 * primitive conversion.
167 */
168 public int intValue() {
169 return (int)sum();
170 }
171
172 /**
173 * Returns the {@link #sum} as a {@code float}
174 * after a widening primitive conversion.
175 */
176 public float floatValue() {
177 return (float)sum();
178 }
179
180 /**
181 * Returns the {@link #sum} as a {@code double} after a widening
182 * primitive conversion.
183 */
184 public double doubleValue() {
185 return (double)sum();
186 }
187
188 private void writeObject(java.io.ObjectOutputStream s)
189 throws java.io.IOException {
190 s.defaultWriteObject();
191 s.writeLong(sum());
192 }
193
194 private void readObject(ObjectInputStream s)
195 throws IOException, ClassNotFoundException {
196 s.defaultReadObject();
197 busy = 0;
198 cells = null;
199 base = s.readLong();
200 }
201
202 }