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

# User Rev Content
1 dl 1.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 dl 1.5 * 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 dl 1.1 *
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 dl 1.5 * <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 dl 1.1 *
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 dl 1.5 public class LongAdder extends Striped64 implements Serializable {
41 dl 1.1 private static final long serialVersionUID = 7249069246863182397L;
42    
43     /**
44 dl 1.5 * Version of plus for use in retryUpdate
45 dl 1.1 */
46 dl 1.5 final long fn(long v, long x) { return v + x; }
47 dl 1.1
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 dl 1.5 Cell[] as; long b, v; HashCode hc; Cell a; int n;
61     if ((as = cells) != null || !casBase(b = base, b + x)) {
62 dl 1.1 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 dl 1.5 !(uncontended = a.cas(v = a.value, v + x)))
67     retryUpdate(x, hc, uncontended);
68 dl 1.1 }
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 dl 1.5 * 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 dl 1.1 *
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 dl 1.5 * 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 dl 1.1 */
115     public void reset() {
116 dl 1.5 internalReset(0L);
117 dl 1.1 }
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 dl 1.5 * <em>not</em> guaranteed to be the final value occurring before
125 dl 1.1 * 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 dl 1.5 long v = a.value;
139 dl 1.1 a.value = 0L;
140 dl 1.5 sum += v;
141 dl 1.1 }
142     }
143     }
144     return sum;
145     }
146    
147 dl 1.5 /**
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 dl 1.1 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     }