32 * Expert Group and released to the public domain, as explained at |
32 * Expert Group and released to the public domain, as explained at |
33 * http://creativecommons.org/publicdomain/zero/1.0/ |
33 * http://creativecommons.org/publicdomain/zero/1.0/ |
34 */ |
34 */ |
35 |
35 |
36 package java.util.concurrent.atomic; |
36 package java.util.concurrent.atomic; |
|
37 |
|
38 import static java.lang.Double.doubleToRawLongBits; |
|
39 import static java.lang.Double.longBitsToDouble; |
37 |
40 |
38 import java.io.Serializable; |
41 import java.io.Serializable; |
39 import java.util.function.DoubleBinaryOperator; |
42 import java.util.function.DoubleBinaryOperator; |
40 |
43 |
41 /** |
44 /** |
89 * @param identity identity (initial value) for the accumulator function |
92 * @param identity identity (initial value) for the accumulator function |
90 */ |
93 */ |
91 public DoubleAccumulator(DoubleBinaryOperator accumulatorFunction, |
94 public DoubleAccumulator(DoubleBinaryOperator accumulatorFunction, |
92 double identity) { |
95 double identity) { |
93 this.function = accumulatorFunction; |
96 this.function = accumulatorFunction; |
94 base = this.identity = Double.doubleToRawLongBits(identity); |
97 base = this.identity = doubleToRawLongBits(identity); |
95 } |
98 } |
96 |
99 |
97 /** |
100 /** |
98 * Updates with the given value. |
101 * Updates with the given value. |
99 * |
102 * |
100 * @param x the value |
103 * @param x the value |
101 */ |
104 */ |
102 public void accumulate(double x) { |
105 public void accumulate(double x) { |
103 Cell[] as; long b, v, r; int m; Cell a; |
106 Cell[] as; long b, v, r; int m; Cell a; |
104 if ((as = cells) != null || |
107 if ((as = cells) != null |
105 (r = Double.doubleToRawLongBits |
108 || ((r = doubleToRawLongBits |
106 (function.applyAsDouble |
109 (function.applyAsDouble(longBitsToDouble(b = base), x))) != b |
107 (Double.longBitsToDouble(b = base), x))) != b && !casBase(b, r)) { |
110 && !casBase(b, r))) { |
108 boolean uncontended = true; |
111 boolean uncontended = true; |
109 if (as == null || (m = as.length - 1) < 0 || |
112 if (as == null |
110 (a = as[getProbe() & m]) == null || |
113 || (m = as.length - 1) < 0 |
111 !(uncontended = |
114 || (a = as[getProbe() & m]) == null |
112 (r = Double.doubleToRawLongBits |
115 || !(uncontended = |
113 (function.applyAsDouble |
116 ((r = doubleToRawLongBits |
114 (Double.longBitsToDouble(v = a.value), x))) == v || |
117 (function.applyAsDouble |
115 a.cas(v, r))) |
118 (longBitsToDouble(v = a.value), x))) == v) |
|
119 || a.cas(v, r))) |
116 doubleAccumulate(x, function, uncontended); |
120 doubleAccumulate(x, function, uncontended); |
117 } |
121 } |
118 } |
122 } |
119 |
123 |
120 /** |
124 /** |
126 * |
130 * |
127 * @return the current value |
131 * @return the current value |
128 */ |
132 */ |
129 public double get() { |
133 public double get() { |
130 Cell[] as = cells; |
134 Cell[] as = cells; |
131 double result = Double.longBitsToDouble(base); |
135 double result = longBitsToDouble(base); |
132 if (as != null) { |
136 if (as != null) { |
133 for (Cell a : as) |
137 for (Cell a : as) |
134 if (a != null) |
138 if (a != null) |
135 result = function.applyAsDouble |
139 result = function.applyAsDouble |
136 (result, Double.longBitsToDouble(a.value)); |
140 (result, longBitsToDouble(a.value)); |
137 } |
141 } |
138 return result; |
142 return result; |
139 } |
143 } |
140 |
144 |
141 /** |
145 /** |
166 * |
170 * |
167 * @return the value before reset |
171 * @return the value before reset |
168 */ |
172 */ |
169 public double getThenReset() { |
173 public double getThenReset() { |
170 Cell[] as = cells; |
174 Cell[] as = cells; |
171 double result = Double.longBitsToDouble(base); |
175 double result = longBitsToDouble(base); |
172 base = identity; |
176 base = identity; |
173 if (as != null) { |
177 if (as != null) { |
174 for (Cell a : as) { |
178 for (Cell a : as) { |
175 if (a != null) { |
179 if (a != null) { |
176 double v = Double.longBitsToDouble(a.value); |
180 double v = longBitsToDouble(a.value); |
177 a.reset(identity); |
181 a.reset(identity); |
178 result = function.applyAsDouble(result, v); |
182 result = function.applyAsDouble(result, v); |
179 } |
183 } |
180 } |
184 } |
181 } |
185 } |
265 * |
269 * |
266 * @return a {@code DoubleAccumulator} object with initial state |
270 * @return a {@code DoubleAccumulator} object with initial state |
267 * held by this proxy |
271 * held by this proxy |
268 */ |
272 */ |
269 private Object readResolve() { |
273 private Object readResolve() { |
270 double d = Double.longBitsToDouble(identity); |
274 double d = longBitsToDouble(identity); |
271 DoubleAccumulator a = new DoubleAccumulator(function, d); |
275 DoubleAccumulator a = new DoubleAccumulator(function, d); |
272 a.base = Double.doubleToRawLongBits(value); |
276 a.base = doubleToRawLongBits(value); |
273 return a; |
277 return a; |
274 } |
278 } |
275 } |
279 } |
276 |
280 |
277 /** |
281 /** |