1 /*
   2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   3  *
   4  * This code is free software; you can redistribute it and/or modify it
   5  * under the terms of the GNU General Public License version 2 only, as
   6  * published by the Free Software Foundation.  Oracle designates this
   7  * particular file as subject to the "Classpath" exception as provided
   8  * by Oracle in the LICENSE file that accompanied this code.
   9  *
  10  * This code is distributed in the hope that it will be useful, but WITHOUT
  11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  13  * version 2 for more details (a copy is included in the LICENSE file that
  14  * accompanied this code).
  15  *
  16  * You should have received a copy of the GNU General Public License version
  17  * 2 along with this work; if not, write to the Free Software Foundation,
  18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  19  *
  20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  21  * or visit www.oracle.com if you need additional information or have any
  22  * questions.
  23  */
  24 
  25 /*
  26  * This file is available under and governed by the GNU General Public
  27  * License version 2 only, as published by the Free Software Foundation.
  28  * However, the following notice accompanied the original version of this
  29  * file:
  30  *
  31  * Written by Doug Lea with assistance from members of JCP JSR-166
  32  * Expert Group and released to the public domain, as explained at
  33  * http://creativecommons.org/publicdomain/zero/1.0/
  34  */
  35 
  36 package java.util.concurrent.atomic;
  37 import java.io.IOException;
  38 import java.io.Serializable;
  39 import java.io.ObjectInputStream;
  40 import java.io.ObjectOutputStream;
  41 import java.util.function.LongBinaryOperator;
  42 
  43 /**
  44  * One or more variables that together maintain a running {@code long}
  45  * value updated using a supplied function.  When updates (method
  46  * {@link #accumulate}) are contended across threads, the set of variables
  47  * may grow dynamically to reduce contention.  Method {@link #get}
  48  * (or, equivalently, {@link #longValue}) returns the current value
  49  * across the variables maintaining updates.
  50  *
  51  * <p>The supplied accumulator function must be side-effect-free.  It
  52  * may be re-applied when attempted updates fail due to contention
  53  * among threads. The function is applied with the current value as
  54  * its first argument, and the given update as the second argument.
  55  * For example, to maintain a running maximum value, you could supply
  56  * {@code (x, y) -> (y > x) ? y : x} along with {@code
  57  * Long.MINIMUM_VALUE} as the identity.  (Class {@link LongAdder}
  58  * provides analogs of the functionality of this class for the common
  59  * special case of maintaining counts and sums.)
  60  *
  61  * <p>This class extends {@link Number}, but does <em>not</em> define
  62  * methods such as {@code hashCode} and {@code compareTo} because
  63  * instances are expected to be mutated, and so are not useful as
  64  * collection keys.
  65  *
  66  * @since 1.8
  67  * @author Doug Lea
  68  */
  69 public class LongAccumulator extends Striped64 implements Serializable {
  70     private static final long serialVersionUID = 7249069246863182397L;
  71 
  72     private final LongBinaryOperator function;
  73     private final long identity;
  74 
  75     /**
  76      * Creates a new instance using the given accumulator function
  77      * and identity element.
  78      */
  79     public LongAccumulator(LongBinaryOperator accumulatorFunction,
  80                            long identity) {
  81         this.function = accumulatorFunction;
  82         base = this.identity = identity;
  83     }
  84 
  85     /**
  86      * Updates with the given value.
  87      *
  88      * @param x the value
  89      */
  90     public void accumulate(long x) {
  91         Cell[] as; long b, v, r; CellHashCode hc; Cell a; int m;
  92         if ((as = cells) != null ||
  93             (r = function.operateAsLong(b = base, x)) != b && !casBase(b, r)) { // ## rename when JDK8 syncs with lambda, applyAsLong
  94             boolean uncontended = true;
  95             if ((hc = threadCellHashCode.get()) == null ||
  96                 as == null || (m = as.length - 1) < 0 ||
  97                 (a = as[m & hc.code]) == null ||
  98                 !(uncontended =
  99                   (r = function.operateAsLong(v = a.value, x)) == v || // ## rename when JDK8 syncs with lambda, applyAsLong
 100                   a.cas(v, r)))
 101                 longAccumulate(x, hc, function, uncontended);
 102         }
 103     }
 104 
 105     /**
 106      * Returns the current value.  The returned value is
 107      * <em>NOT</em> an atomic snapshot: Invocation in the absence of
 108      * concurrent updates returns an accurate result, but concurrent
 109      * updates that occur while the value is being calculated might
 110      * not be incorporated.
 111      *
 112      * @return the current value
 113      */
 114     public long get() {
 115         Cell[] as = cells; Cell a;
 116         long result = base;
 117         if (as != null) {
 118             for (int i = 0; i < as.length; ++i) {
 119                 if ((a = as[i]) != null)
 120                     result = function.operateAsLong(result, a.value); // ## rename when JDK8 syncs with lambda, applyAsLong
 121             }
 122         }
 123         return result;
 124     }
 125 
 126     /**
 127      * Resets variables maintaining updates the given value.  This
 128      * method may be a useful alternative to creating a new updater,
 129      * but is only effective if there are no concurrent updates.
 130      * Because this method is intrinsically racy, it should only be
 131      * used when it is known that no threads are concurrently
 132      * updating.
 133      */
 134     public void reset() {
 135         Cell[] as = cells; Cell a;
 136         base = identity;
 137         if (as != null) {
 138             for (int i = 0; i < as.length; ++i) {
 139                 if ((a = as[i]) != null)
 140                     a.value = identity;
 141             }
 142         }
 143     }
 144 
 145     /**
 146      * Equivalent in effect to {@link #get} followed by {@link
 147      * #reset}. This method may apply for example during quiescent
 148      * points between multithreaded computations.  If there are
 149      * updates concurrent with this method, the returned value is
 150      * <em>not</em> guaranteed to be the final value occurring before
 151      * the reset.
 152      *
 153      * @return the value before reset
 154      */
 155     public long getThenReset() {
 156         Cell[] as = cells; Cell a;
 157         long result = base;
 158         base = identity;
 159         if (as != null) {
 160             for (int i = 0; i < as.length; ++i) {
 161                 if ((a = as[i]) != null) {
 162                     long v = a.value;
 163                     a.value = identity;
 164                     result = function.operateAsLong(result, v); // ## rename when JDK8 syncs with lambda, applyAsLong
 165                 }
 166             }
 167         }
 168         return result;
 169     }
 170 
 171     /**
 172      * Returns the String representation of the current value.
 173      * @return the String representation of the current value
 174      */
 175     public String toString() {
 176         return Long.toString(get());
 177     }
 178 
 179     /**
 180      * Equivalent to {@link #get}.
 181      *
 182      * @return the maximum
 183      */
 184     public long longValue() {
 185         return get();
 186     }
 187 
 188     /**
 189      * Returns the {@link #get} as an {@code int} after a narrowing
 190      * primitive conversion.
 191      */
 192     public int intValue() {
 193         return (int)get();
 194     }
 195 
 196     /**
 197      * Returns the {@link #get} as a {@code float}
 198      * after a widening primitive conversion.
 199      */
 200     public float floatValue() {
 201         return (float)get();
 202     }
 203 
 204     /**
 205      * Returns the {@link #get} as a {@code double} after a widening
 206      * primitive conversion.
 207      */
 208     public double doubleValue() {
 209         return (double)get();
 210     }
 211 
 212     private void writeObject(java.io.ObjectOutputStream s)
 213         throws java.io.IOException {
 214         s.defaultWriteObject();
 215         s.writeLong(get());
 216     }
 217 
 218     private void readObject(ObjectInputStream s)
 219         throws IOException, ClassNotFoundException {
 220         s.defaultReadObject();
 221         cellsBusy = 0;
 222         cells = null;
 223         base = s.readLong();
 224     }
 225 
 226 }