001/*
002 * Written by Doug Lea with assistance from members of JCP JSR-166
003 * Expert Group and released to the public domain, as explained at
004 * http://creativecommons.org/publicdomain/zero/1.0/
005 *
006 * Source: http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/src/jsr166e/DoubleAdder.java?revision=1.12
007 */
008
009package io.prometheus.client;
010
011import java.io.IOException;
012import java.io.ObjectInputStream;
013import java.io.ObjectOutputStream;
014import java.io.Serializable;
015
016/**
017 * One or more variables that together maintain an initially zero
018 * {@code double} sum.  When updates (method {@link #add}) are
019 * contended across threads, the set of variables may grow dynamically
020 * to reduce contention.  Method {@link #sum} (or, equivalently {@link
021 * #doubleValue}) returns the current total combined across the
022 * variables maintaining the sum.
023 *
024 * <p>This class extends {@link Number}, but does <em>not</em> define
025 * methods such as {@code equals}, {@code hashCode} and {@code
026 * compareTo} because instances are expected to be mutated, and so are
027 * not useful as collection keys.
028 *
029 * <p><em>jsr166e note: This class is targeted to be placed in
030 * java.util.concurrent.atomic.</em>
031 *
032 * @since 1.8
033 * @author Doug Lea
034 */
035public class DoubleAdder extends Striped64 implements Serializable {
036    private static final long serialVersionUID = 7249069246863182397L;
037
038    /**
039     * Update function. Note that we must use "long" for underlying
040     * representations, because there is no compareAndSet for double,
041     * due to the fact that the bitwise equals used in any CAS
042     * implementation is not the same as double-precision equals.
043     * However, we use CAS only to detect and alleviate contention,
044     * for which bitwise equals works best anyway. In principle, the
045     * long/double conversions used here should be essentially free on
046     * most platforms since they just re-interpret bits.
047     *
048     * Similar conversions are used in other methods.
049     */
050    final long fn(long v, long x) {
051        return Double.doubleToRawLongBits
052                (Double.longBitsToDouble(v) +
053                        Double.longBitsToDouble(x));
054    }
055
056    /**
057     * Creates a new adder with initial sum of zero.
058     */
059    public DoubleAdder() {
060    }
061
062    /**
063     * Adds the given value.
064     *
065     * @param x the value to add
066     */
067    public void add(double x) {
068        Cell[] as; long b, v; int[] hc; Cell a; int n;
069        if ((as = cells) != null ||
070                !casBase(b = base,
071                        Double.doubleToRawLongBits
072                                (Double.longBitsToDouble(b) + x))) {
073            boolean uncontended = true;
074            if ((hc = threadHashCode.get()) == null ||
075                    as == null || (n = as.length) < 1 ||
076                    (a = as[(n - 1) & hc[0]]) == null ||
077                    !(uncontended = a.cas(v = a.value,
078                            Double.doubleToRawLongBits
079                                    (Double.longBitsToDouble(v) + x))))
080                retryUpdate(Double.doubleToRawLongBits(x), hc, uncontended);
081        }
082    }
083
084    /**
085     * Returns the current sum.  The returned value is <em>NOT</em> an
086     * atomic snapshot; invocation in the absence of concurrent
087     * updates returns an accurate result, but concurrent updates that
088     * occur while the sum is being calculated might not be
089     * incorporated.  Also, because floating-point arithmetic is not
090     * strictly associative, the returned result need not be identical
091     * to the value that would be obtained in a sequential series of
092     * updates to a single variable.
093     *
094     * @return the sum
095     */
096    public double sum() {
097        Cell[] as = cells;
098        double sum = Double.longBitsToDouble(base);
099        if (as != null) {
100            int n = as.length;
101            for (int i = 0; i < n; ++i) {
102                Cell a = as[i];
103                if (a != null)
104                    sum += Double.longBitsToDouble(a.value);
105            }
106        }
107        return sum;
108    }
109
110    /**
111     * Resets variables maintaining the sum to zero.  This method may
112     * be a useful alternative to creating a new adder, but is only
113     * effective if there are no concurrent updates.  Because this
114     * method is intrinsically racy, it should only be used when it is
115     * known that no threads are concurrently updating.
116     */
117    public void reset() {
118        internalReset(0L);
119    }
120
121    /**
122     * Equivalent in effect to {@link #sum} followed by {@link
123     * #reset}. This method may apply for example during quiescent
124     * points between multithreaded computations.  If there are
125     * updates concurrent with this method, the returned value is
126     * <em>not</em> guaranteed to be the final value occurring before
127     * the reset.
128     *
129     * @return the sum
130     */
131    public double sumThenReset() {
132        Cell[] as = cells;
133        double sum = Double.longBitsToDouble(base);
134        base = 0L;
135        if (as != null) {
136            int n = as.length;
137            for (int i = 0; i < n; ++i) {
138                Cell a = as[i];
139                if (a != null) {
140                    long v = a.value;
141                    a.value = 0L;
142                    sum += Double.longBitsToDouble(v);
143                }
144            }
145        }
146        return sum;
147    }
148
149    /**
150     * Returns the String representation of the {@link #sum}.
151     * @return the String representation of the {@link #sum}
152     */
153    public String toString() {
154        return Double.toString(sum());
155    }
156
157    /**
158     * Equivalent to {@link #sum}.
159     *
160     * @return the sum
161     */
162    public double doubleValue() {
163        return sum();
164    }
165
166    /**
167     * Returns the {@link #sum} as a {@code long} after a
168     * narrowing primitive conversion.
169     */
170    public long longValue() {
171        return (long)sum();
172    }
173
174    /**
175     * Returns the {@link #sum} as an {@code int} after a
176     * narrowing primitive conversion.
177     */
178    public int intValue() {
179        return (int)sum();
180    }
181
182    /**
183     * Returns the {@link #sum} as a {@code float}
184     * after a narrowing primitive conversion.
185     */
186    public float floatValue() {
187        return (float)sum();
188    }
189
190    private void writeObject(ObjectOutputStream s) throws IOException {
191        s.defaultWriteObject();
192        s.writeDouble(sum());
193    }
194
195    private void readObject(ObjectInputStream s)
196            throws IOException, ClassNotFoundException {
197        s.defaultReadObject();
198        busy = 0;
199        cells = null;
200        base = Double.doubleToRawLongBits(s.readDouble());
201    }
202
203}