RFR 8005311: Add Scalable Updatable Variables, DoubleAccumulator, DoubleAdder, LongAccumulator, LongAdder

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