ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jsr166e/DoubleMaxUpdater.java
Revision: 1.1
Committed: Tue Aug 2 18:04:12 2011 UTC (12 years, 9 months ago) by dl
Branch: MAIN
Log Message:
Refactor and introduce new forms of update

File Contents

# User Rev Content
1 dl 1.1 /*
2     * Written by Doug Lea with assistance from members of JCP JSR-166
3     * Expert Group and released to the public domain, as explained at
4     * http://creativecommons.org/publicdomain/zero/1.0/
5     */
6    
7     package jsr166e;
8     import java.io.IOException;
9     import java.io.Serializable;
10     import java.io.ObjectInputStream;
11     import java.io.ObjectOutputStream;
12    
13     /**
14     * One or more variables that together maintain a running {@code double}
15     * maximum with initial value {@code Double.NEGATIVE_INFINITY}. When
16     * updates (method {@link #update}) are contended across threads, the
17     * set of variables may grow dynamically to reduce contention. Method
18     * {@link #max} (or, equivalently, {@link #doubleValue}) returns the
19     * current maximum across the variables maintaining updates.
20     *
21     * <p>This class extends {@link Number}, but does <em>not</em> define
22     * methods such as {@code hashCode} and {@code compareTo} because
23     * instances are expected to be mutated, and so are not useful as
24     * collection keys.
25     *
26     * <p><em>jsr166e note: This class is targeted to be placed in
27     * java.util.concurrent.atomic<em>
28     *
29     * @author Doug Lea
30     */
31     public class DoubleMaxUpdater extends Striped64 implements Serializable {
32     private static final long serialVersionUID = 7249069246863182397L;
33     /**
34     * Long representation of negative infinity. See class Double
35     * internal documentation for explanation.
36     */
37     private static final long MIN_AS_LONG = 0xfff0000000000000L;
38    
39     /**
40     * Update function. See class DoubleAdder for rationale
41     * for using conversions from/to long.
42     */
43     final long fn(long v, long x) {
44     return Double.longBitsToDouble(v) > Double.longBitsToDouble(x) ? v : x;
45     }
46    
47     /**
48     * Creates a new instance with initial value of {@code
49     * Double.NEGATIVE_INFINITY}.
50     */
51     public DoubleMaxUpdater() {
52     base = MIN_AS_LONG;
53     }
54    
55     /**
56     * Updates the maximum to be at least the given value.
57     *
58     * @param x the value to update
59     */
60     public void update(double x) {
61     long lx = Double.doubleToRawLongBits(x);
62     Cell[] as; long b, v; HashCode hc; Cell a; int n;
63     if ((as = cells) != null ||
64     (Double.longBitsToDouble(b = base) < x && !casBase(b, lx))) {
65     boolean uncontended = true;
66     int h = (hc = threadHashCode.get()).code;
67     if (as == null || (n = as.length) < 1 ||
68     (a = as[(n - 1) & h]) == null ||
69     (Double.longBitsToDouble(v = a.value) < x &&
70     !(uncontended = a.cas(v, lx))))
71     retryUpdate(lx, hc, uncontended);
72     }
73     }
74    
75     /**
76     * Returns the current maximum. The returned value is
77     * <em>NOT</em> an atomic snapshot: Invocation in the absence of
78     * concurrent updates returns an accurate result, but concurrent
79     * updates that occur while the value is being calculated might
80     * not be incorporated.
81     *
82     * @return the maximum
83     */
84     public double max() {
85     Cell[] as = cells;
86     double max = Double.longBitsToDouble(base);
87     if (as != null) {
88     int n = as.length;
89     double v;
90     for (int i = 0; i < n; ++i) {
91     Cell a = as[i];
92     if (a != null && (v = Double.longBitsToDouble(a.value)) > max)
93     max = v;
94     }
95     }
96     return max;
97     }
98    
99     /**
100     * Resets variables maintaining updates to {@code
101     * Double.NEGATIVE_INFINITY}. This method may be a useful
102     * alternative to creating a new updater, but is only effective if
103     * there are no concurrent updates. Because this method is
104     * intrinsically racy, it should only be used when it is known
105     * that no threads are concurrently updating.
106     */
107     public void reset() {
108     internalReset(MIN_AS_LONG);
109     }
110    
111     /**
112     * Equivalent in effect to {@link #max} followed by {@link
113     * #reset}. This method may apply for example during quiescent
114     * points between multithreaded computations. If there are
115     * updates concurrent with this method, the returned value is
116     * <em>not</em> guaranteed to be the final value occurring before
117     * the reset.
118     *
119     * @return the maximum
120     */
121     public double maxThenReset() {
122     Cell[] as = cells;
123     double max = Double.longBitsToDouble(base);
124     base = MIN_AS_LONG;
125     if (as != null) {
126     int n = as.length;
127     for (int i = 0; i < n; ++i) {
128     Cell a = as[i];
129     if (a != null) {
130     double v = Double.longBitsToDouble(a.value);
131     a.value = MIN_AS_LONG;
132     if (v > max)
133     max = v;
134     }
135     }
136     }
137     return max;
138     }
139    
140     /**
141     * Returns the String representation of the {@link #max}.
142     * @return the String representation of the {@link #max}.
143     */
144     public String toString() {
145     return Double.toString(max());
146     }
147    
148     /**
149     * Equivalent to {@link #max}.
150     *
151     * @return the max
152     */
153     public double doubleValue() {
154     return max();
155     }
156    
157     /**
158     * Returns the {@link #max} as a {@code long} after a
159     * primitive conversion.
160     */
161     public long longValue() {
162     return (long)max();
163     }
164    
165     /**
166     * Returns the {@link #max} as an {@code int} after a
167     * primitive conversion.
168     */
169     public int intValue() {
170     return (int)max();
171     }
172    
173     /**
174     * Returns the {@link #max} as a {@code float}
175     * after a primitive conversion.
176     */
177     public float floatValue() {
178     return (float)max();
179     }
180    
181     private void writeObject(java.io.ObjectOutputStream s)
182     throws java.io.IOException {
183     s.defaultWriteObject();
184     s.writeDouble(max());
185     }
186    
187     private void readObject(ObjectInputStream s)
188     throws IOException, ClassNotFoundException {
189     s.defaultReadObject();
190     busy = 0;
191     cells = null;
192     base = Double.doubleToRawLongBits(s.readDouble());
193     }
194    
195     }