Use VarHandles in DataNodeContainerModificationStrategy 60/103160/1
authorRobert Varga <robert.varga@pantheon.tech>
Tue, 8 Nov 2022 18:18:39 +0000 (19:18 +0100)
committerRobert Varga <robert.varga@pantheon.tech>
Tue, 8 Nov 2022 18:18:39 +0000 (19:18 +0100)
Using a VarHandle allows us to use compareAndExchange(), which
eliminates the need for a volatile read when we fail to update.

Change-Id: Ie7922c5f116801f0b442c30f3ca14d2360abc845
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
data/yang-data-tree-ri/src/main/java/org/opendaylight/yangtools/yang/data/tree/impl/DataNodeContainerModificationStrategy.java

index 4fb50de45a1dbe988c597df6bb320a9131653d25..a3bb05338e976740910d53e344fdc806b6c2156c 100644 (file)
@@ -10,7 +10,8 @@ package org.opendaylight.yangtools.yang.data.tree.impl;
 import static java.util.Objects.requireNonNull;
 
 import com.google.common.collect.ImmutableMap;
-import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 import org.eclipse.jdt.annotation.NonNull;
 import org.eclipse.jdt.annotation.Nullable;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
@@ -31,13 +32,19 @@ import org.slf4j.LoggerFactory;
  */
 class DataNodeContainerModificationStrategy<T extends DataNodeContainer & WithStatus> extends Visible<T> {
     private static final Logger LOG = LoggerFactory.getLogger(DataNodeContainerModificationStrategy.class);
+    private static final VarHandle CHILDREN;
+
+    static {
+        try {
+            CHILDREN = MethodHandles.lookup().findVarHandle(
+                DataNodeContainerModificationStrategy.class, "children", ImmutableMap.class);
+        } catch (NoSuchFieldException | IllegalAccessException e) {
+            throw new ExceptionInInitializerError(e);
+        }
+    }
 
     private final @NonNull DataTreeConfiguration treeConfig;
 
-    @SuppressWarnings("rawtypes")
-    private static final AtomicReferenceFieldUpdater<DataNodeContainerModificationStrategy, ImmutableMap> UPDATER =
-            AtomicReferenceFieldUpdater.newUpdater(DataNodeContainerModificationStrategy.class, ImmutableMap.class,
-                "children");
     private volatile ImmutableMap<PathArgument, ModificationApplyOperation> children = ImmutableMap.of();
 
     DataNodeContainerModificationStrategy(final NormalizedNodeContainerSupport<?, ?> support, final T schema,
@@ -94,12 +101,14 @@ class DataNodeContainerModificationStrategy<T extends DataNodeContainer & WithSt
                 .build();
 
             // Attempt to install the updated map
-            if (UPDATER.compareAndSet(this, previous, updated)) {
+            final var witness = (ImmutableMap<PathArgument, ModificationApplyOperation>)
+                CHILDREN.compareAndExchange(this, previous, updated);
+            if (witness == previous) {
                 return computed;
             }
 
             // We have raced, acquire a new snapshot, recheck presence and retry if needed
-            previous = children;
+            previous = witness;
             final var raced = previous.get(identifier);
             if (raced != null) {
                 return raced;