Drop a FIXME in DataContainerCodecPrototype 93/81793/3
authorRobert Varga <robert.varga@pantheon.tech>
Fri, 26 Apr 2019 19:36:30 +0000 (21:36 +0200)
committerRobert Varga <robert.varga@pantheon.tech>
Fri, 26 Apr 2019 20:38:04 +0000 (22:38 +0200)
Acquisition of the backer is in the hot path now, hence we should
consider if we can safely remove or relax the volatile read here.

Change-Id: I9efe3cd2f45ab97f6c4c9bcc8f18e4cf62542b60
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/CodecDataObject.java
binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataContainerCodecPrototype.java
binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataObjectCodecContext.java

index a9446a139455f1a9db29cfe916b41b1c11a6c731..b63e2928a731c27011fd04cd719103bc3af7acf5 100644 (file)
@@ -75,7 +75,8 @@ public abstract class CodecDataObject<T extends DataObject> implements DataObjec
                 .toString();
     }
 
-    // TODO: consider switching to VarHandles for Java 9+
+    // TODO: consider switching to VarHandles for Java 9+, as that would disconnect us from the need to use a volatile
+    //       field and use acquire/release mechanics -- see http://gee.cs.oswego.edu/dl/html/j9mm.html for details.
     protected final Object codecMember(final AtomicReferenceFieldUpdater<CodecDataObject<?>, Object> updater,
             final NodeContextSupplier supplier) {
         final Object cached = updater.get(this);
index 35b37a1e76b6ca6067f3a03216fb4b7bed62b02f..73b3c577b982bc6135e13ae8303a6cbebcf643ca 100644 (file)
@@ -46,6 +46,37 @@ final class DataContainerCodecPrototype<T extends WithStatus> implements NodeCon
     private final PathArgument yangArg;
     private final ChildAddressabilitySummary childAddressabilitySummary;
 
+    /*
+     * FIXME: This field is now utterly in the hot path of CodecDataObject's instantiation of data. It is volatile
+     *        support double-checked locking, as detailed in
+     *        https://en.wikipedia.org/wiki/Double-checked_locking#Usage_in_Java.
+     *
+     *        Removing volatile here would seem to be worthwhile, as it would mean that in the initialized case we end
+     *        up with no happens-before synchronization between threads, allowing JIT to perform better.
+     *
+     *        Since we are on Java 5+, DataContainerCodecContext and its subclasses play a role here. All of their
+     *        fields are either final or volatile, so intuition would indicate they themselves could (already?) be
+     *        acting in the same capacity as "FinalWrapper" in the above example does -- in which case we can safely
+     *        remove the volatile access altogether, after documenting this fact there (and potentially placing some
+     *        guards).
+     *
+     *        The presence of volatile fields seems to violate this, as
+     *        http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html mentions "such that all of the
+     *        fields of Helper are final".
+     *
+     *        There are only two violations, both relating to dynamic discovery of augmentations, which should be
+     *        eliminated once we have constant class loader visibility (and thus can discover all valid augmentations
+     *        and aliases). Alternatively, adding an indirection could be considered after the effects are fully
+     *        understood.
+     *
+     *        Alternatively we can consider the use of VarHandle acquire/release mechanics to remove this instance
+     *        from global synchronization order -- that would be a Java 9+ concern, though.
+     *
+     *        Finally, the benefits of addressing this are masked by CodecDataObject operating on volatiles, hence
+     *        already doing a barrier very close to us -- thus reducing the scope in which code can be reordered.
+     *        If CodecDataObject moves to VarHandles and uses acquire/release there, we will be put on the spot here,
+     *        though.
+     */
     private volatile DataContainerCodecContext<?, T> instance;
 
     @SuppressWarnings("unchecked")
index c5360d940f307181fe0281e689235adbcf86231a..cb9fa451fb7df236ab26f762e707561260f18f5b 100644 (file)
@@ -98,6 +98,8 @@ abstract class DataObjectCodecContext<D extends DataObject, T extends DataNodeCo
     private final ImmutableMap<AugmentationIdentifier, Type> possibleAugmentations;
     private final MethodHandle proxyConstructor;
 
+    // FIXME: the presence of these two volatile fields may be preventing us from being able to improve
+    //        DataContainerCodecPrototype.get() publication.
     @SuppressWarnings("rawtypes")
     private static final AtomicReferenceFieldUpdater<DataObjectCodecContext, Augmentations>
         AUGMENTATIONS_UPDATER = AtomicReferenceFieldUpdater.newUpdater(DataObjectCodecContext.class,