On 06/22/2013 08:06 AM, Dmitry Nadezhin wrote:
> Alexey,
> 
> Each possible radix has its cacheLine in the cache.
> 
> Cache contents looks like
> BigInteger[][] powerCache = new BigInteger[37] {
> /*0*/ null,
> /*1*/ null,
> /*2*/ new BigInteger[] { 2, 4, 16, 256, 32768, ... },
> /*3*/ new BigInteger[] { 3, 9, 81, ... },
> /*4*/ new BigInteger[] { 4, 16, 256, ... }
> /*5*/ new BigInteger[] { 5, 25, 625, ... },
> /*6*/ new BigInteger[] { 6 },
> /*7*/ new BigInteger[] { 7 },
> . . .
> /*36*/ new BigInteger[] { 36 }
> };
> 
> Is there an idiom for a list/array of volatile references ?

AtomicReferenceArray is your friend there. Although I'm not sure why you
need the list of volatile references in this case. Placing volatile to
the root reference resolves the race.

> I am not sure that such naive code works:
> volatile BigInteger[][] powerCache = ..,

Why wouldn't it work?

 volatile T[][] cache;

 T[] get(int index) {
    T[][] lc = cache;
    if (index >= lc.length) { // need resizing
       lc = generateNew(index << 1);
       cache = lc;
    }
    return lc[index];
 }

If you need to populate the 2nd level, then you have to have the final
volatile write to the $cache. The corresponding $cache volatile read
makes the update on 2nd level visible.

 T get(int index1, index2) {
    T[][] lc = cache;
    if (index1 >= lc.length) { // needs resizing
       lc = generateNewT2(index1 << 1);
       cache = lc;
    }
    T[] lt = lc[index2];
    if (index2 >= lt.length) { // needs resizing
       lt = generateNewT1(index2 << 1);
       lc[index2] = lt;
       cache = lc; // publish
    }
    return lt[index2];
 }


-Aleksey.

Reply via email to