[jmm-dev] jdk9 APIs

Doug Lea dl at cs.oswego.edu
Thu Aug 20 13:44:07 UTC 2015


On 08/10/2015 02:22 PM, Doug Lea wrote:
> There seems to be only a little room for discussion on the exact sets
> of methods in the VarHandle* and Fences classes:

I think these are as settled as they need to be for present purposes.
Perhaps not loved, but settled. Please let me know if you think otherwise.

Current versions are pasted below and updated at
   http://gee.cs.oswego.edu/dl/wwwtmp/Fodder.java

Bear in mind that the actual VarHandles class differs due to polymorphic
method-handle mechanics. Also it is possible that the methods in "Fences"
might end up elsewhere (maybe in the VarHandles utility class) that better
fit with Un-Unsafe-ifying (safication?) plans.

The javadocs still need some work, but the functionality
seems to meet the main goals, mainly of matching C/C++11 atomics
in all the "important" cases, providing some way to obtain
equivalent effects in remaining cases, and exposing all these
in public APIs (vs Unsafe or other weird hacks). And doing so for now
without revising the base memory model (thus relying on non-formal
specs), but with the belief that they are compatible with future
JMM updates.

As always, and other comments and suggestions are also 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.
      */
     T getRelaxed(Object owner);

     /**
      * Returns the value, with memory semantics of reading a volatile
      * variable.
      */
     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.
      */
     T getAcquire(Object owner);

     /**
      * Returns the value, accessed in program order, but with no
      * assurance of memory ordering effects with respect to other
      * threads.
      */
     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, and ensures that prior loads and stores are not
      * reordered after this access.
      *
      * @param val the new value
      */
     void setVolatile(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_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
      * getRelaxed.
      *
      * @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 jmm-dev mailing list