On 10/03/2015 2:21 AM, Martin Buchholz wrote:
On Mon, Mar 9, 2015 at 4:13 AM, David Holmes <david.hol...@oracle.com
<mailto:david.hol...@oracle.com>> wrote:
On 9/03/2015 7:27 PM, Andrew Haley wrote:
But who is to say that is the specification for the Unsafe API?
It's for us to say!
I meant specifically the choice of the specification, not the right to
suggest one.
The public API's have a specification for what they provide to the
programmer. On what basis are we assigning that same specification
to Unsafe API? The Unsafe API has to meet the requirements of the
public APIs that use it, but that doesn't mean it necessarily
should have the same specification as those APIs.
We already have lots of code that implicitly depends on volatile
read/write visibility, especially in j.u.c.
Most obviously, how do you implement compareAndSet methods without the
same visibility guarantees on the Unsafe equivalents?
Obviously Unsafe has to be implemented in a way that satisfies the j.u.c
routines that use it.
My spec change only documents what "everyone already knows to be true".
Another way of looking at it is that the Unsafe methods are a low-level
optimization of the equivalent j.u.c.a. objects without requiring memory
allocation.
The public API methods specify memory ordering semantics so that the end
programmer can use those to reason about their use of j.u.c components.
The implementation of j.u.c has to satisfy its specified semantics.
The current implementation of j.u.c uses Unsafe operations that in turn
utilize JVM operations. The JVM operations have memory synchronization
affects that are stronger than required by j.u.c, and so satisfy them.
So the question is: should Unsafe specify the expectations of its j.u.c
client (what you propose); or should it specify what the JVM
implementations provide; or should it not actually specify anything in
this regard knowing that the implementation is required to correctly
implement the public APIs? I don't see much point in pushing down the
spec from the public APIs to the Unsafe API. To me it suffices to say
that the Unsafe methods must correctly implement the requirements of the
public API without specifying that in specific terms of volatile
read/writes (which it doesn't actually use) or full bi-directional
fences (which it does use). It's not as if Unsafe were a public API for
which we might switch in implementations from different providers and
hence we need a clear specification for those implementors to follow.
But if you think it important that these Unsafe methods say something
about memory synchronization then the wording still needs to make clear
what "volatile" is assumed to be being accessed. In particular the j.u.c
usage always passes the offset of a variable that is volatile - hence
getting volatile read/write semantics. But you can pass the Unsafe
methods the offset for a variable that is not declared volatile - so
what then? Should the specification state that the offset is
assumed/expected to that for a volatile variable and hence it provides
volatile read/write only if that variable is volatile? Or should we
state something more generic as in:
"This operation reads the Java variable at the given offset with
volatile load semantics, and writes it with volatile store semantics."
That doesn't force the variable to be volatile but does require Unsafe
to act as if it were. The wording is also similar to that used in
getObjectVolatile/putObjectVolatile. (It also doesn't attempt to the
address the debate as to whether there is any volatile write on failure
- should it?)
Or should we say something else?
Cheers,
David