ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jsr166e/LongAdder.java
Revision: 1.6
Committed: Sun Aug 28 19:08:07 2011 UTC (12 years, 8 months ago) by dl
Branch: MAIN
Changes since 1.5: +3 -4 lines
Log Message:
Initial commit of CHM replacement

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 long sum = base;
96 Cell[] as = cells;
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 long sum = base;
131 Cell[] as = cells;
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 sum += a.value;
139 a.value = 0L;
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 Long.toString(sum());
152 }
153
154 /**
155 * Equivalent to {@link #sum}.
156 *
157 * @return the sum
158 */
159 public long longValue() {
160 return sum();
161 }
162
163 /**
164 * Returns the {@link #sum} as an {@code int} after a narrowing
165 * primitive conversion.
166 */
167 public int intValue() {
168 return (int)sum();
169 }
170
171 /**
172 * Returns the {@link #sum} as a {@code float}
173 * after a widening primitive conversion.
174 */
175 public float floatValue() {
176 return (float)sum();
177 }
178
179 /**
180 * Returns the {@link #sum} as a {@code double} after a widening
181 * primitive conversion.
182 */
183 public double doubleValue() {
184 return (double)sum();
185 }
186
187 private void writeObject(java.io.ObjectOutputStream s)
188 throws java.io.IOException {
189 s.defaultWriteObject();
190 s.writeLong(sum());
191 }
192
193 private void readObject(ObjectInputStream s)
194 throws IOException, ClassNotFoundException {
195 s.defaultReadObject();
196 busy = 0;
197 cells = null;
198 base = s.readLong();
199 }
200
201 }