[jmm-dev] VarHandle.safepoint() methods
Sanjoy Das
sanjoy at playingwithpointers.com
Wed Jan 4 20:11:20 UTC 2017
Hi Andrew,
On Wed, Jan 4, 2017 at 10:04 AM, Andrew Haley <aph at redhat.com> wrote:
> This is a proposal for a new VarHandle method, but it also is an
> extension to the Java Memory Model, so I'm starting the discussion
> here.
>
> My intention is to provide an efficient way to handle the case where a
> field has reads which outnumber writes by several orders of magnitude.
> Once a field has been successfully modified, no thread may observe a
> stale value. Writes to a field are expected to be very rare, and can
> be expensive.
>
> It provides a secure and fast way to do something like a volatile
> access but without any memory fences (or even any restrictions on
> memory reordering) on the reader side.
>
> I propose two new VarHandle methods:
>
> Object getSafepoint()
>
> Returns the value of a variable, with memory semantics of reading as
> if the variable was declared non-volatile, except that this load
> shall not be reordered with a preceding safepoint.
I presume you'll also want to prevent CSE across safepoints? That is:
rA = t.getVolatile()
JVM::SafepointPoll()
rB = t.getVolatile()
=>
rA = t.getVolatile()
JVM::SafepointPoll()
rB = rA
needs to be prohibited also?
[snip]
> Example: A closeable MappedByteBuffer.
>
> public class CloseableMappedByteBuffer {
>
> // Actually unmaps a byte buffer.
> private native void unmap(MappedByteBuffer b);
>
> private volatile MappedByteBuffer _buf;
> private VarHandle vh;
>
> private MappedByteBuffer buf() {
> return (MappedByteBuffer) v.getSafepoint();
> }
>
> public CloseableMappedByteBuffer wrap(MappedByteBuffer buf) {
> return new CloseableMappedByteBuffer(buf);
> }
>
> public void unmap() {
> MappedByteBuffer buf = buf();
> vh.setOpaque(null);
> VarHandle.safepoint();
> // Now every thread sees the updated _buf, we can unmap it.
> unmap(buf);
> }
>
> public byte get() {
> return buf().get();
> }
You'd need to make sure that get() does not have a safepoint between
buf() and get() right?
>
> public byte get(int index) {
> return buf().get(index);
> }
>
> ...etc, for all the ByteBuffer methods.
> }
Have you considered something like this:
public void unmap() {
MappedByteBuffer buf = buf();
vh.setOpaque(null);
while (true) {
Traces = Thread.getAllStackTraces();
// If no trace in Traces contains a get() method or something
// equivalent then break; else loop.
}
unmap(buf);
}
and nothing special about the get() methods.
I'm not sure how well Thread.getAllStackTraces() works in practice
though.
-- Sanjoy
More information about the jmm-dev
mailing list