RFR 8005311: Add Scalable Updatable Variables, DoubleAccumulator, DoubleAdder, LongAccumulator, LongAdder (original) (raw)

Peter Levart peter.levart at gmail.com
Thu Jan 10 11:40:57 UTC 2013


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



More information about the core-libs-dev mailing list