Home | History | Annotate | Download | only in atomic
      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 
     38 import java.io.Serializable;
     39 import java.util.function.DoubleBinaryOperator;
     40 
     41 /**
     42  * One or more variables that together maintain a running {@code double}
     43  * value updated using a supplied function.  When updates (method
     44  * {@link #accumulate}) are contended across threads, the set of variables
     45  * may grow dynamically to reduce contention.  Method {@link #get}
     46  * (or, equivalently, {@link #doubleValue}) returns the current value
     47  * across the variables maintaining updates.
     48  *
     49  * <p>This class is usually preferable to alternatives when multiple
     50  * threads update a common value that is used for purposes such as
     51  * summary statistics that are frequently updated but less frequently
     52  * read.
     53  *
     54  * <p>The supplied accumulator function should be side-effect-free,
     55  * since it may be re-applied when attempted updates fail due to
     56  * contention among threads. The function is applied with the current
     57  * value as its first argument, and the given update as the second
     58  * argument.  For example, to maintain a running maximum value, you
     59  * could supply {@code Double::max} along with {@code
     60  * Double.NEGATIVE_INFINITY} as the identity. The order of
     61  * accumulation within or across threads is not guaranteed. Thus, this
     62  * class may not be applicable if numerical stability is required,
     63  * especially when combining values of substantially different orders
     64  * of magnitude.
     65  *
     66  * <p>Class {@link DoubleAdder} provides analogs of the functionality
     67  * of this class for the common special case of maintaining sums.  The
     68  * call {@code new DoubleAdder()} is equivalent to {@code new
     69  * DoubleAccumulator((x, y) -> x + y, 0.0)}.
     70  *
     71  * <p>This class extends {@link Number}, but does <em>not</em> define
     72  * methods such as {@code equals}, {@code hashCode} and {@code
     73  * compareTo} because instances are expected to be mutated, and so are
     74  * not useful as collection keys.
     75  *
     76  * @since 1.8
     77  * @author Doug Lea
     78  */
     79 public class DoubleAccumulator extends Striped64 implements Serializable {
     80     private static final long serialVersionUID = 7249069246863182397L;
     81 
     82     private final DoubleBinaryOperator function;
     83     private final long identity; // use long representation
     84 
     85     /**
     86      * Creates a new instance using the given accumulator function
     87      * and identity element.
     88      * @param accumulatorFunction a side-effect-free function of two arguments
     89      * @param identity identity (initial value) for the accumulator function
     90      */
     91     public DoubleAccumulator(DoubleBinaryOperator accumulatorFunction,
     92                              double identity) {
     93         this.function = accumulatorFunction;
     94         base = this.identity = Double.doubleToRawLongBits(identity);
     95     }
     96 
     97     /**
     98      * Updates with the given value.
     99      *
    100      * @param x the value
    101      */
    102     public void accumulate(double x) {
    103         Cell[] as; long b, v, r; int m; Cell a;
    104         if ((as = cells) != null ||
    105             (r = Double.doubleToRawLongBits
    106              (function.applyAsDouble
    107               (Double.longBitsToDouble(b = base), x))) != b  && !casBase(b, r)) {
    108             boolean uncontended = true;
    109             if (as == null || (m = as.length - 1) < 0 ||
    110                 (a = as[getProbe() & m]) == null ||
    111                 !(uncontended =
    112                   (r = Double.doubleToRawLongBits
    113                    (function.applyAsDouble
    114                     (Double.longBitsToDouble(v = a.value), x))) == v ||
    115                   a.cas(v, r)))
    116                 doubleAccumulate(x, function, uncontended);
    117         }
    118     }
    119 
    120     /**
    121      * Returns the current value.  The returned value is <em>NOT</em>
    122      * an atomic snapshot; invocation in the absence of concurrent
    123      * updates returns an accurate result, but concurrent updates that
    124      * occur while the value is being calculated might not be
    125      * incorporated.
    126      *
    127      * @return the current value
    128      */
    129     public double get() {
    130         Cell[] as = cells;
    131         double result = Double.longBitsToDouble(base);
    132         if (as != null) {
    133             for (Cell a : as)
    134                 if (a != null)
    135                     result = function.applyAsDouble
    136                         (result, Double.longBitsToDouble(a.value));
    137         }
    138         return result;
    139     }
    140 
    141     /**
    142      * Resets variables maintaining updates to the identity value.
    143      * This method may be a useful alternative to creating a new
    144      * updater, but is only effective if there are no concurrent
    145      * updates.  Because this method is intrinsically racy, it should
    146      * only be used when it is known that no threads are concurrently
    147      * updating.
    148      */
    149     public void reset() {
    150         Cell[] as = cells;
    151         base = identity;
    152         if (as != null) {
    153             for (Cell a : as)
    154                 if (a != null)
    155                     a.reset(identity);
    156         }
    157     }
    158 
    159     /**
    160      * Equivalent in effect to {@link #get} followed by {@link
    161      * #reset}. This method may apply for example during quiescent
    162      * points between multithreaded computations.  If there are
    163      * updates concurrent with this method, the returned value is
    164      * <em>not</em> guaranteed to be the final value occurring before
    165      * the reset.
    166      *
    167      * @return the value before reset
    168      */
    169     public double getThenReset() {
    170         Cell[] as = cells;
    171         double result = Double.longBitsToDouble(base);
    172         base = identity;
    173         if (as != null) {
    174             for (Cell a : as) {
    175                 if (a != null) {
    176                     double v = Double.longBitsToDouble(a.value);
    177                     a.reset(identity);
    178                     result = function.applyAsDouble(result, v);
    179                 }
    180             }
    181         }
    182         return result;
    183     }
    184 
    185     /**
    186      * Returns the String representation of the current value.
    187      * @return the String representation of the current value
    188      */
    189     public String toString() {
    190         return Double.toString(get());
    191     }
    192 
    193     /**
    194      * Equivalent to {@link #get}.
    195      *
    196      * @return the current value
    197      */
    198     public double doubleValue() {
    199         return get();
    200     }
    201 
    202     /**
    203      * Returns the {@linkplain #get current value} as a {@code long}
    204      * after a narrowing primitive conversion.
    205      */
    206     public long longValue() {
    207         return (long)get();
    208     }
    209 
    210     /**
    211      * Returns the {@linkplain #get current value} as an {@code int}
    212      * after a narrowing primitive conversion.
    213      */
    214     public int intValue() {
    215         return (int)get();
    216     }
    217 
    218     /**
    219      * Returns the {@linkplain #get current value} as a {@code float}
    220      * after a narrowing primitive conversion.
    221      */
    222     public float floatValue() {
    223         return (float)get();
    224     }
    225 
    226     /**
    227      * Serialization proxy, used to avoid reference to the non-public
    228      * Striped64 superclass in serialized forms.
    229      * @serial include
    230      */
    231     private static class SerializationProxy implements Serializable {
    232         private static final long serialVersionUID = 7249069246863182397L;
    233 
    234         /**
    235          * The current value returned by get().
    236          * @serial
    237          */
    238         private final double value;
    239 
    240         /**
    241          * The function used for updates.
    242          * @serial
    243          */
    244         private final DoubleBinaryOperator function;
    245 
    246         /**
    247          * The identity value, represented as a long, as converted by
    248          * {@link Double#doubleToRawLongBits}.  The original identity
    249          * can be recovered using {@link Double#longBitsToDouble}.
    250          * @serial
    251          */
    252         private final long identity;
    253 
    254         SerializationProxy(double value,
    255                            DoubleBinaryOperator function,
    256                            long identity) {
    257             this.value = value;
    258             this.function = function;
    259             this.identity = identity;
    260         }
    261 
    262         /**
    263          * Returns a {@code DoubleAccumulator} object with initial state
    264          * held by this proxy.
    265          *
    266          * @return a {@code DoubleAccumulator} object with initial state
    267          * held by this proxy
    268          */
    269         private Object readResolve() {
    270             double d = Double.longBitsToDouble(identity);
    271             DoubleAccumulator a = new DoubleAccumulator(function, d);
    272             a.base = Double.doubleToRawLongBits(value);
    273             return a;
    274         }
    275     }
    276 
    277     /**
    278      * Returns a
    279      * <a href="../../../../serialized-form.html#java.util.concurrent.atomic.DoubleAccumulator.SerializationProxy">
    280      * SerializationProxy</a>
    281      * representing the state of this instance.
    282      *
    283      * @return a {@link SerializationProxy}
    284      * representing the state of this instance
    285      */
    286     private Object writeReplace() {
    287         return new SerializationProxy(get(), function, identity);
    288     }
    289 
    290     /**
    291      * @param s the stream
    292      * @throws java.io.InvalidObjectException always
    293      */
    294     private void readObject(java.io.ObjectInputStream s)
    295         throws java.io.InvalidObjectException {
    296         throw new java.io.InvalidObjectException("Proxy required");
    297     }
    298 
    299 }
    300