1 /**
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19 /*
20 * Written by Doug Lea with assistance from members of JCP JSR-166
21 * Expert Group and released to the public domain, as explained at
22 * http://creativecommons.org/publicdomain/zero/1.0/
23 */
24
25 package org.apache.hadoop.hbase.util;
26
27 import java.io.IOException;
28 import java.io.ObjectInputStream;
29 import java.io.ObjectOutputStream;
30 import java.io.Serializable;
31 import java.util.concurrent.atomic.AtomicLong;
32
33 import org.apache.hadoop.hbase.classification.InterfaceAudience;
34 import org.apache.hadoop.hbase.classification.InterfaceStability;
35
36 /**
37 * One or more variables that together maintain an initially zero
38 * {@code long} sum. When updates (method {@link #add}) are contended
39 * across threads, the set of variables may grow dynamically to reduce
40 * contention. Method {@link #sum} (or, equivalently, {@link
41 * #longValue}) returns the current total combined across the
42 * variables maintaining the sum.
43 *
44 * <p>This class is usually preferable to {@link AtomicLong} when
45 * multiple threads update a common sum that is used for purposes such
46 * as collecting statistics, not for fine-grained synchronization
47 * control. Under low update contention, the two classes have similar
48 * characteristics. But under high contention, expected throughput of
49 * this class is significantly higher, at the expense of higher space
50 * consumption.
51 *
52 * <p>This class extends {@link Number}, but does <em>not</em> define
53 * methods such as {@code equals}, {@code hashCode} and {@code
54 * compareTo} because instances are expected to be mutated, and so are
55 * not useful as collection keys.
56 *
57 * <p><em>jsr166e note: This class is targeted to be placed in
58 * java.util.concurrent.atomic.</em>
59 *
60 * @since 1.8
61 */
62 @InterfaceAudience.Public
63 @InterfaceStability.Stable
64 public class LongAdder extends Striped64 implements Serializable {
65 private static final long serialVersionUID = 7249069246863182397L;
66
67 /**
68 * Version of plus for use in retryUpdate
69 */
70 @Override
71 final long fn(long v, long x) { return v + x; }
72
73 /**
74 * Creates a new adder with initial sum of zero.
75 */
76 public LongAdder() {
77 }
78
79 /**
80 * Adds the given value.
81 *
82 * @param x the value to add
83 */
84 public void add(long x) {
85 Cell[] as; long b, v; int[] hc; Cell a; int n;
86 if ((as = cells) != null || !casBase(b = base, b + x)) {
87 boolean uncontended = true;
88 if ((hc = threadHashCode.get()) == null ||
89 as == null || (n = as.length) < 1 ||
90 (a = as[(n - 1) & hc[0]]) == null ||
91 !(uncontended = a.cas(v = a.value, v + x)))
92 retryUpdate(x, hc, uncontended);
93 }
94 }
95
96 /**
97 * Equivalent to {@code add(1)}.
98 */
99 public void increment() {
100 add(1L);
101 }
102
103 /**
104 * Equivalent to {@code add(-1)}.
105 */
106 public void decrement() {
107 add(-1L);
108 }
109
110 /**
111 * Returns the current sum. The returned value is <em>NOT</em> an
112 * atomic snapshot; invocation in the absence of concurrent
113 * updates returns an accurate result, but concurrent updates that
114 * occur while the sum is being calculated might not be
115 * incorporated.
116 *
117 * @return the sum
118 */
119 public long sum() {
120 long sum = base;
121 Cell[] as = cells;
122 if (as != null) {
123 int n = as.length;
124 for (int i = 0; i < n; ++i) {
125 Cell a = as[i];
126 if (a != null)
127 sum += a.value;
128 }
129 }
130 return sum;
131 }
132
133 /**
134 * Resets variables maintaining the sum to zero. This method may
135 * be a useful alternative to creating a new adder, but is only
136 * effective if there are no concurrent updates. Because this
137 * method is intrinsically racy, it should only be used when it is
138 * known that no threads are concurrently updating.
139 */
140 public void reset() {
141 internalReset(0L);
142 }
143
144 /**
145 * Equivalent in effect to {@link #sum} followed by {@link
146 * #reset}. This method may apply for example during quiescent
147 * points between multithreaded computations. If there are
148 * updates concurrent with this method, the returned value is
149 * <em>not</em> guaranteed to be the final value occurring before
150 * the reset.
151 *
152 * @return the sum
153 */
154 public long sumThenReset() {
155 long sum = base;
156 Cell[] as = cells;
157 base = 0L;
158 if (as != null) {
159 int n = as.length;
160 for (int i = 0; i < n; ++i) {
161 Cell a = as[i];
162 if (a != null) {
163 sum += a.value;
164 a.value = 0L;
165 }
166 }
167 }
168 return sum;
169 }
170
171 /**
172 * Returns the String representation of the {@link #sum}.
173 * @return the String representation of the {@link #sum}
174 */
175 @Override
176 public String toString() {
177 return Long.toString(sum());
178 }
179
180 /**
181 * Equivalent to {@link #sum}.
182 *
183 * @return the sum
184 */
185 @Override
186 public long longValue() {
187 return sum();
188 }
189
190 /**
191 * Returns the {@link #sum} as an {@code int} after a narrowing
192 * primitive conversion.
193 */
194 @Override
195 public int intValue() {
196 return (int)sum();
197 }
198
199 /**
200 * Returns the {@link #sum} as a {@code float}
201 * after a widening primitive conversion.
202 */
203 @Override
204 public float floatValue() {
205 return (float)sum();
206 }
207
208 /**
209 * Returns the {@link #sum} as a {@code double} after a widening
210 * primitive conversion.
211 */
212 @Override
213 public double doubleValue() {
214 return (double)sum();
215 }
216
217 private void writeObject(ObjectOutputStream s) throws IOException {
218 s.defaultWriteObject();
219 s.writeLong(sum());
220 }
221
222 private void readObject(ObjectInputStream s)
223 throws IOException, ClassNotFoundException {
224 s.defaultReadObject();
225 busy = 0;
226 cells = null;
227 base = s.readLong();
228 }
229
230 }