88 private final long identity; // use long representation
89
90 /**
91 * Creates a new instance using the given accumulator function
92 * and identity element.
93 * @param accumulatorFunction a side-effect-free function of two arguments
94 * @param identity identity (initial value) for the accumulator function
95 */
96 public DoubleAccumulator(DoubleBinaryOperator accumulatorFunction,
97 double identity) {
98 this.function = accumulatorFunction;
99 base = this.identity = doubleToRawLongBits(identity);
100 }
101
102 /**
103 * Updates with the given value.
104 *
105 * @param x the value
106 */
107 public void accumulate(double x) {
108 Cell[] as; long b, v, r; int m; Cell a;
109 if ((as = cells) != null
110 || ((r = doubleToRawLongBits
111 (function.applyAsDouble(longBitsToDouble(b = base), x))) != b
112 && !casBase(b, r))) {
113 boolean uncontended = true;
114 if (as == null
115 || (m = as.length - 1) < 0
116 || (a = as[getProbe() & m]) == null
117 || !(uncontended =
118 ((r = doubleToRawLongBits
119 (function.applyAsDouble
120 (longBitsToDouble(v = a.value), x))) == v)
121 || a.cas(v, r)))
122 doubleAccumulate(x, function, uncontended);
123 }
124 }
125
126 /**
127 * Returns the current value. The returned value is <em>NOT</em>
128 * an atomic snapshot; invocation in the absence of concurrent
129 * updates returns an accurate result, but concurrent updates that
130 * occur while the value is being calculated might not be
131 * incorporated.
132 *
133 * @return the current value
134 */
135 public double get() {
136 Cell[] as = cells;
137 double result = longBitsToDouble(base);
138 if (as != null) {
139 for (Cell a : as)
140 if (a != null)
141 result = function.applyAsDouble
142 (result, longBitsToDouble(a.value));
143 }
144 return result;
145 }
146
147 /**
148 * Resets variables maintaining updates to the identity value.
149 * This method may be a useful alternative to creating a new
150 * updater, but is only effective if there are no concurrent
151 * updates. Because this method is intrinsically racy, it should
152 * only be used when it is known that no threads are concurrently
153 * updating.
154 */
155 public void reset() {
156 Cell[] as = cells;
157 base = identity;
158 if (as != null) {
159 for (Cell a : as)
160 if (a != null)
161 a.reset(identity);
162 }
163 }
164
165 /**
166 * Equivalent in effect to {@link #get} followed by {@link
167 * #reset}. This method may apply for example during quiescent
168 * points between multithreaded computations. If there are
169 * updates concurrent with this method, the returned value is
170 * <em>not</em> guaranteed to be the final value occurring before
171 * the reset.
172 *
173 * @return the value before reset
174 */
175 public double getThenReset() {
176 Cell[] as = cells;
177 double result = longBitsToDouble(base);
178 base = identity;
179 if (as != null) {
180 for (Cell a : as) {
181 if (a != null) {
182 double v = longBitsToDouble(a.value);
183 a.reset(identity);
184 result = function.applyAsDouble(result, v);
185 }
186 }
187 }
188 return result;
189 }
190
191 /**
192 * Returns the String representation of the current value.
193 * @return the String representation of the current value
194 */
195 public String toString() {
196 return Double.toString(get());
197 }
198
199 /**
200 * Equivalent to {@link #get}.
201 *
202 * @return the current value
203 */
|
88 private final long identity; // use long representation
89
90 /**
91 * Creates a new instance using the given accumulator function
92 * and identity element.
93 * @param accumulatorFunction a side-effect-free function of two arguments
94 * @param identity identity (initial value) for the accumulator function
95 */
96 public DoubleAccumulator(DoubleBinaryOperator accumulatorFunction,
97 double identity) {
98 this.function = accumulatorFunction;
99 base = this.identity = doubleToRawLongBits(identity);
100 }
101
102 /**
103 * Updates with the given value.
104 *
105 * @param x the value
106 */
107 public void accumulate(double x) {
108 Cell[] cs; long b, v, r; int m; Cell c;
109 if ((cs = cells) != null
110 || ((r = doubleToRawLongBits
111 (function.applyAsDouble(longBitsToDouble(b = base), x))) != b
112 && !casBase(b, r))) {
113 boolean uncontended = true;
114 if (cs == null
115 || (m = cs.length - 1) < 0
116 || (c = cs[getProbe() & m]) == null
117 || !(uncontended =
118 ((r = doubleToRawLongBits
119 (function.applyAsDouble
120 (longBitsToDouble(v = c.value), x))) == v)
121 || c.cas(v, r)))
122 doubleAccumulate(x, function, uncontended);
123 }
124 }
125
126 /**
127 * Returns the current value. The returned value is <em>NOT</em>
128 * an atomic snapshot; invocation in the absence of concurrent
129 * updates returns an accurate result, but concurrent updates that
130 * occur while the value is being calculated might not be
131 * incorporated.
132 *
133 * @return the current value
134 */
135 public double get() {
136 Cell[] cs = cells;
137 double result = longBitsToDouble(base);
138 if (cs != null) {
139 for (Cell c : cs)
140 if (c != null)
141 result = function.applyAsDouble
142 (result, longBitsToDouble(c.value));
143 }
144 return result;
145 }
146
147 /**
148 * Resets variables maintaining updates to the identity value.
149 * This method may be a useful alternative to creating a new
150 * updater, but is only effective if there are no concurrent
151 * updates. Because this method is intrinsically racy, it should
152 * only be used when it is known that no threads are concurrently
153 * updating.
154 */
155 public void reset() {
156 Cell[] cs = cells;
157 base = identity;
158 if (cs != null) {
159 for (Cell c : cs)
160 if (c != null)
161 c.reset(identity);
162 }
163 }
164
165 /**
166 * Equivalent in effect to {@link #get} followed by {@link
167 * #reset}. This method may apply for example during quiescent
168 * points between multithreaded computations. If there are
169 * updates concurrent with this method, the returned value is
170 * <em>not</em> guaranteed to be the final value occurring before
171 * the reset.
172 *
173 * @return the value before reset
174 */
175 public double getThenReset() {
176 Cell[] cs = cells;
177 double result = longBitsToDouble(getAndSetBase(identity));
178 if (cs != null) {
179 for (Cell c : cs) {
180 if (c != null) {
181 double v = longBitsToDouble(c.getAndSet(identity));
182 result = function.applyAsDouble(result, v);
183 }
184 }
185 }
186 return result;
187 }
188
189 /**
190 * Returns the String representation of the current value.
191 * @return the String representation of the current value
192 */
193 public String toString() {
194 return Double.toString(get());
195 }
196
197 /**
198 * Equivalent to {@link #get}.
199 *
200 * @return the current value
201 */
|