View Javadoc

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 }