[jmm-dev] bitwise RMW operators, specifically testAndSetBit/BTS

Paul Sandoz paul.sandoz at oracle.com
Mon Jul 18 11:43:47 UTC 2016


> On 15 Jul 2016, at 21:17, Doug Lea <dl at cs.oswego.edu> wrote:
> 
> On 07/15/2016 12:27 PM, Doug Lea wrote:
> 
>> ... only the getAndX forms seem useful, with only Volatile
>> and Release orderings. Using the default-volatile RMW convention,
>> this would require 6 methods:
>> 
> 
> John suggests the slightly less weird (and thus better):
>  getAndBitwiseOr, getAndBitwiseAnd,  getAndBitwiseXor
>  getAndBitwiseOrRelease, getAndBitwiseAndRelease, getAndBitwiseXorRelease
> that at least separates the two "And"s.
> 
> And in the spirit of not making another premature triage proposal,
> perhaps these should also include Acquire variants:
> getAndBitwiseOrAcquire, getAndBitwiseAndAcquire, getAndBitwiseXorAcquire
> 
> The implicitly-volatile versions should be useful without implementation
> penalty in the Acquire use cases that come to mind, but perhaps there are
> others. Suggestions welcome.
> 

We can support boolean, byte, char, short, int and long, where boolean defers to byte, and char defers to short.

In terms of the Unsafe Java implementations have i got the following correct (it’s the acquire variant i am unsure of)?

@ForceInline
public final int getAndBitwiseOrInt(Object o, long offset, int mask) {
    int current;
    do {
        current = getIntVolatile(o, offset);
    } while (!weakCompareAndSwapIntVolatile(o, offset,
                                            current, current | mask));
    return current;
}

@ForceInline
public final int getAndBitwiseOrIntRelease(Object o, long offset, int mask) {
    int current;
    do {
        current = getInt(o, offset);
    } while (!weakCompareAndSwapIntRelease(o, offset,
                                           current, current | mask));
    return current;
}

@ForceInline
public final int getAndBitwiseOrIntAcquire(Object o, long offset, int mask) {
    int current;
    do {
        current = getIntAcquire(o, offset);
    } while (!weakCompareAndSwapIntAcquire(o, offset,
                                           current, current | mask));
    return current;
}


As previously indicated, with suitable intrinsics and constant power of two masks (and complement of) it should be possible to boil it down to almost single bit setting instructions on x86 (more so if the returned value, aka current/witness, is dropped).

—

Separately, i would like to propose a naming scheme:

- for the read or write method, plain is the default.

- for read-modify-write methods volatile is the default volatile
  - rename weakCompareAndSet to weakCompareAndSetPlain
  - rename weakCompareAndSetVolatile to weakCompareAndSet
  - deprecate (not for removal) Atomic*.weakCompareAndSet, add Atomic*.weakCompareAndSetPlain
    which leaves the inconsistency of Atomic*.weakCompareAndSetVolatile.

Analysis on grepcode shows very little usage of the Atomic*.weakCompareAndSet methods.

Paul.


More information about the jmm-dev mailing list