jdk9 VarHandle and Fence methods
Doug Lea
dl at cs.oswego.edu
Fri Aug 21 14:24:06 UTC 2015
For those of you who haven't been following this on the jmm-dev list
or follow-ups on concurrency-interest:
We are NOT planning a full JMM memory model update for jdk9 -- there
are still unresolved issues in revising the formal core model.
However, jdk9 will include APIs for VarHandles (a scaled-down version of
the "enhanced volatiles" JEP), that together with some other
support replaces the need to use of Unsafe to obtain these
effects and does so compatibly with C/C++11 atomics. To do this, we
must, until the next full JMM update, provide specs that are
clear to readers (at least those familiar with the underlying
concepts) but not formally tied to a base model, (Which limits
how much we can say in them.)
The tentative methods are pasted below and also at
http://gee.cs.oswego.edu/dl/wwwtmp/Fodder.java
The javadocs currently do not include any examples helping to
explain why you would ever want to use any of these methods.
The actual VarHandle class will look a bit different because
it will rely on specializations of polymorphic signatures.
(Current versions can be found in the openjdk mercurial
"jdk9/sandbox" repo.) And the "Fences" method may end up
in a different java.lang.* utility class. We'd also retrofit
j.u.c.atomic.Atomic* classes to use compatible methods/names.
Comments welcome.
...
/**
* Stand-in for spec purposes of jdk9 java.lang.invoke.VarHandle
*/
abstract class NotReallyVarHandle<T> {
// Load
/**
* Returns the value, with memory semantics of reading a
* non-volatile variable.
*
* @return the value
*/
T getRelaxed(Object owner);
/**
* Returns the value, with memory semantics of reading a volatile
* variable.
*
* @return the value
*/
T getVolatile(Object owner);
/**
* Returns the value, and ensures that subsequent loads and stores
* are not reordered before this access.
*
* @apiNote Ignoring the many semantic differences from C and
* C++, this method has memory ordering effects compatible with
* memory_order_acquire ordering.
*
* @return the value
*/
T getAcquire(Object owner);
/**
* Returns the value, accessed in program order, but with no
* assurance of memory ordering effects with respect to other
* threads.
*
* @return the value
*/
T getOpaque(Object owner);
// Store
/**
* Sets the value, with memory semantics of setting a non-volatile
* variable.
*
* @param val the new value
*/
void setRelaxed(Object owner, T val);
/**
* Sets the value, with memory semantics of setting a volatile
* variable.
*
* @apiNote Ignoring the many semantic differences from C and
* C++, this method has memory ordering effects compatible with
* memory_order_seq_cst.
*
* @param val the new value
*/
void setVolatile(Object owner, T val);
/**
* Sets the value, and ensures that prior loads and stores are not
* reordered after this access.
*
* @apiNote Ignoring the many semantic differences from C and
* C++, this method has memory ordering effects compatible with
* memory_order_release ordering.
*
* @param val the new value
*/
void setRelease(Object owner, T val);
/**
* Sets the value, in program order, but with no assurance of
* memory ordering effects with respect to other threads.
*
* @param val the new value
*/
void setOpaque(Object owner, T val);
// CAS
/**
* Atomically sets the value to the given updated value with the
* memory semantics of setVolatile if the current value {@code ==}
* the expected value, as accessed with the memory semantics of
* getVolatile.
*
* @param expected the expected value
* @param val the new value
* @return {@code true} if successful. False return indicates that
* the actual value was not equal to the expected value.
*/
boolean compareAndSet(Object owner, T expected, T val);
// Value-returning compare and exchange
/**
* Atomically sets the value to the given updated value with the
* memory semantics of setVolatile if the current value {@code ==}
* the expected value, as accessed with the memory semantics of
* getVolatile.
*
* @param expected the expected value
* @param val the new value
* @return the current value, which will be the same as {@code val} if
* successful.
*/
T compareAndExchangeVolatile(Object owner, T expected, T val);
/**
* Atomically sets the value to the given updated value with the
* memory semantics of setRelaxed if the current value {@code ==}
* the expected value, as accessed with the memory semantics of
* getAcquire.
*
* @param expected the expected value
* @param val the new value
* @return the current value, which will be the same as {@code val} if
* successful.
*/
T compareAndExchangeAcquire(Object owner, T expected, T val);
/**
* Atomically sets the value to the given updated value with the
* memory semantics of setRelease if the current value {@code ==}
* the expected value, as accessed with the memory samantics of
* getRelease.
*
* @param expected the expected value
* @param val the new value
* @return the current value, which will be the same as {@code val} if
* successful.
*/
T compareAndExchangeRelease(Object owner, T expected, T val);
// Weak (spurious failures allowed)
/**
* Possibly atomically sets the value to the given updated value
* with the semantics of setRelaxed if the current value {@code
* ==} the expected value, as as accessed with the memory
* semantics of getRelaxed. This operation may fail spuriously
* (typically, due to memory contention) even if the current value
* does match the expected value.
*
* @param expected the expected value
* @param val the new value
* @return {@code true} if successful
*/
boolean weakCompareAndSetRelaxed(Object owner, T expected, T val);
/**
* Possibly atomically sets the value to the given updated value
* with the memory semantics of setRelaxed if the current value
* {@code ==} the expected value, as as accessed with the memory
* semantics of getAcquire. This operation may fail spuriously
* (typically, due to memory contention) even if the current value
* does match the expected value.
*
* @param expected the expected value
* @param val the new value
* @return {@code true} if successful
*/
boolean weakCompareAndSetAcquire(Object owner, T expected, T val);
/**
* Possibly atomically sets the value to the given updated value
* with the memory semantics of setRelease if the current value
* {@code ==} the expected value, as as accessed with the memory
* semantics of getRelaxed. This operation may fail spuriously
* (typically, due to memory contention) even if the current value
* does match the expected value.
*
* @param expected the expected value
* @param val the new value
* @return {@code true} if successful
*/
boolean weakCompareAndSetRelease(Object owner, T expected, T val);
// special RMW
/**
* Atomically sets to the given value with the memory semantics of
* setVolatile and returns the old value.
*
* @param newValue the new value
* @return the previous value
*/
T getAndSet(Object owner, T val);
/**
* Atomically adds the given value to the current value with the
* memory semantics of setVolatile.
*
* @param delta the value to add
* @return the previous value
*/
T getAndAdd(Object owner, T delta);
/**
* Atomically adds the given value to the current value with the
* memory semantics of setVolatile.
*
* @param delta the value to add
* @return the current value
*/
T addAndGet(Object owner, T delta);
}
/**
* A set of methods providing fine-grained control of memory ordering.
*
* <p>The Java Language Specification permits operations to be
* executed in orders different than are apparent in program source
* code, subject to constraints mainly arising from the use of locks
* and volatile fields. The methods of this class can also be used to
* impose constraints. Their specifications are phrased in terms of
* the lack of "reorderings" -- observable ordering effects that might
* otherwise occur if the fence were not present.
*
* @apiNote More precise phrasing of these specifications may
* accompany future updates of the Java Language Specification.
*/
public class Fences {
/**
* Ensures that loads and stores before the fence will not be
* reordered with loads and stores after the fence.
*
* @apiNote Ignoring the many semantic differences from C and
* C++, this method has memory ordering effects compatible with
* atomic_thread_fence(memory_order_seq_cst)
*/
public static void fullFence() {}
/**
* Ensures that loads before the fence will not be reordered with
* loads and stores after the fence.
*
* @apiNote Ignoring the many semantic differences from C and
* C++, this method has memory ordering effects compatible with
* atomic_thread_fence(memory_order_acquire)
*/
public static void acquireFence() {}
/**
* Ensures that loads and stores before the fence will not be
* reordered with stores after the fence.
*
* @apiNote Ignoring the many semantic differences from C and
* C++, this method has memory ordering effects compatible with
* atomic_thread_fence(memory_order_release)
*/
public static void releaseFence() {}
/**
* Ensures that loads before the fence will not be reordered with
* loads after the fence.
*/
public static void loadLoadFence() {}
/**
* Ensures that stores before the fence will not be reordered with
* stores after the fence.
*/
public static void storeStoreFence() {}
}
class java.lang.ref.Reference {
// add:
/**
* Ensures that the object referenced by the given reference
* remains <em>strongly reachable</em> (as defined in the {@link
* java.lang.ref} package documentation), regardless of any prior
* actions of the program that might otherwise cause the object to
* become unreachable; thus, the referenced object is not
* reclaimable by garbage collection at least until after the
* invocation of this method. Invocation of this method does not
* itself initiate garbage collection or finalization.
*
* @param ref the reference. If null, this method has no effect.
*/
public static void reachabilityFence(Object ref) {}
}
More information about the valhalla-dev
mailing list