On 01/10/2013 02:23 AM, Doug Lea wrote:
On further consideration...
On 01/08/13 10:01, Peter Levart wrote:
- accumulate(long x) returns the post-modification value of the
modified cell or
base (the returned value of the function that was used to update the
state)
- the accumulator function is always called for initial allocations
of cells
(with identity value as 1st argument, like when accumulating on the
base) - the
original code optimizes this situation and just installs the
parameter x into
the cell.
... I'm no longer seeing a reason to support this kind of use,
even with "protected" methods.
The particular cells used, even for a particular thread, can
and do change over time, so returning the pre-accumulate value for the
cell used means only "this was at some moment a partial accumulation
value". The next one returned after another call might be completely
unrelated. The only possible uses I can imagine, for example a
not-at-all random progress sampling mechanism, can be done in
better ways. And as you showed, while you could make a sort of
RNG out of it, it is not competitive with ThreadLocalRandom,
and has unknowable statistical properties.
So for now anyway, I don't plan on doing this.
Another use could be a unique identifier generator. But all that is
possible with ThreadLocal also...
Thanks for the opportunity to do these thought experiments though :-)
A related question: What do you think of a variant of
[Double|Long]Adder.sumThenReset like the following:
/**
* Like {@link #sumThenReset()}, but with a guarantee that this
adder's amount
* is decreased by the same exact amount that was returned.
Invoking this method
* during frequent concurrent updates can disturb concurrent
threads slightly,
* so it is not advisable to call it very frequently...
*/
public long drain() {
Cell[] as = cells; Cell a;
long sum = gasBase(0L);
if (as != null) {
for (int i = 0; i < as.length; ++i) {
if ((a = as[i]) != null) {
sum += a.gas(0L);
}
}
}
return sum;
}
with the following additions in Striped64, using new Unsafe intrinsics:
final long gasBase(long val) {
return UNSAFE.getAndSetLong(this, BASE, val);
}
static final class Cell {
...
final long gas(long val) {
return UNSAFE.getAndSetLong(this, valueOffset, val);
}
Regards, Peter
-Doug