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