View Javadoc
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   /*
8    * Source:
9    * http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/src/jsr166e/LongAdder.java?revision=1.17
10   */
11  
12  package com.google.common.hash;
13  
14  import com.google.common.annotations.GwtCompatible;
15  import java.io.IOException;
16  import java.io.ObjectInputStream;
17  import java.io.ObjectOutputStream;
18  import java.io.Serializable;
19  import java.util.concurrent.atomic.AtomicLong;
20  
21  /**
22   * One or more variables that together maintain an initially zero
23   * {@code long} sum.  When updates (method {@link #add}) are contended
24   * across threads, the set of variables may grow dynamically to reduce
25   * contention. Method {@link #sum} (or, equivalently, {@link
26   * #longValue}) returns the current total combined across the
27   * variables maintaining the sum.
28   *
29   * <p>This class is usually preferable to {@link AtomicLong} when
30   * multiple threads update a common sum that is used for purposes such
31   * as collecting statistics, not for fine-grained synchronization
32   * control.  Under low update contention, the two classes have similar
33   * characteristics. But under high contention, expected throughput of
34   * this class is significantly higher, at the expense of higher space
35   * consumption.
36   *
37   * <p>This class extends {@link Number}, but does <em>not</em> define
38   * methods such as {@code equals}, {@code hashCode} and {@code
39   * compareTo} because instances are expected to be mutated, and so are
40   * not useful as collection keys.
41   *
42   * <p><em>jsr166e note: This class is targeted to be placed in
43   * java.util.concurrent.atomic.</em>
44   *
45   * @since 1.8
46   * @author Doug Lea
47   */
48  @GwtCompatible(emulated = true)
49  final class LongAdder extends Striped64 implements Serializable, LongAddable {
50      private static final long serialVersionUID = 7249069246863182397L;
51  
52      /**
53       * Version of plus for use in retryUpdate
54       */
55      final long fn(long v, long x) { return v + x; }
56  
57      /**
58       * Creates a new adder with initial sum of zero.
59       */
60      public LongAdder() {
61      }
62  
63      /**
64       * Adds the given value.
65       *
66       * @param x the value to add
67       */
68      public void add(long x) {
69          Cell[] as; long b, v; int[] hc; Cell a; int n;
70          if ((as = cells) != null || !casBase(b = base, 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, v + x)))
76                  retryUpdate(x, hc, uncontended);
77          }
78      }
79  
80      /**
81       * Equivalent to {@code add(1)}.
82       */
83      public void increment() {
84          add(1L);
85      }
86  
87      /**
88       * Equivalent to {@code add(-1)}.
89       */
90      public void decrement() {
91          add(-1L);
92      }
93  
94      /**
95       * Returns the current sum.  The returned value is <em>NOT</em> an
96       * atomic snapshot; invocation in the absence of concurrent
97       * updates returns an accurate result, but concurrent updates that
98       * occur while the sum is being calculated might not be
99       * incorporated.
100      *
101      * @return the sum
102      */
103     public long sum() {
104         long sum = base;
105         Cell[] as = cells;
106         if (as != null) {
107             int n = as.length;
108             for (int i = 0; i < n; ++i) {
109                 Cell a = as[i];
110                 if (a != null)
111                     sum += a.value;
112             }
113         }
114         return sum;
115     }
116 
117     /**
118      * Resets variables maintaining the sum to zero.  This method may
119      * be a useful alternative to creating a new adder, but is only
120      * effective if there are no concurrent updates.  Because this
121      * method is intrinsically racy, it should only be used when it is
122      * known that no threads are concurrently updating.
123      */
124     public void reset() {
125         internalReset(0L);
126     }
127 
128     /**
129      * Equivalent in effect to {@link #sum} followed by {@link
130      * #reset}. This method may apply for example during quiescent
131      * points between multithreaded computations.  If there are
132      * updates concurrent with this method, the returned value is
133      * <em>not</em> guaranteed to be the final value occurring before
134      * the reset.
135      *
136      * @return the sum
137      */
138     public long sumThenReset() {
139         long sum = base;
140         Cell[] as = cells;
141         base = 0L;
142         if (as != null) {
143             int n = as.length;
144             for (int i = 0; i < n; ++i) {
145                 Cell a = as[i];
146                 if (a != null) {
147                     sum += a.value;
148                     a.value = 0L;
149                 }
150             }
151         }
152         return sum;
153     }
154 
155     /**
156      * Returns the String representation of the {@link #sum}.
157      * @return the String representation of the {@link #sum}
158      */
159     public String toString() {
160         return Long.toString(sum());
161     }
162 
163     /**
164      * Equivalent to {@link #sum}.
165      *
166      * @return the sum
167      */
168     public long longValue() {
169         return sum();
170     }
171 
172     /**
173      * Returns the {@link #sum} as an {@code int} after a narrowing
174      * 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 widening primitive conversion.
183      */
184     public float floatValue() {
185         return (float)sum();
186     }
187 
188     /**
189      * Returns the {@link #sum} as a {@code double} after a widening
190      * primitive conversion.
191      */
192     public double doubleValue() {
193         return (double)sum();
194     }
195 
196     private void writeObject(ObjectOutputStream s) throws IOException {
197         s.defaultWriteObject();
198         s.writeLong(sum());
199     }
200 
201     private void readObject(ObjectInputStream s)
202             throws IOException, ClassNotFoundException {
203         s.defaultReadObject();
204         busy = 0;
205         cells = null;
206         base = s.readLong();
207     }
208 
209 }