Issue releaseFence() at the of ready() 94/107694/5
authorRobert Varga <robert.varga@pantheon.tech>
Mon, 4 Sep 2023 20:35:22 +0000 (22:35 +0200)
committerRobert Varga <robert.varga@pantheon.tech>
Mon, 4 Sep 2023 21:51:24 +0000 (23:51 +0200)
We seem to be observing stale state during modification validation. Make
sure we flush out any and all modifications before we complete ready().

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

index a8da8e79a0fa8d13279a8717aa694149c8193b60..6ce2d14c94e9cb1c379304e66e4ad19da44fd9c8 100644 (file)
@@ -301,14 +301,20 @@ final class InMemoryDataTreeModification extends AbstractCursorAware implements
 
     @Override
     public void ready() {
-        // We want a full CAS with setVolatile() memory semantics, as we want to force happen-before
-        // for everything, including whatever user code works.
-        final boolean wasRunning = SEALED.compareAndSet(this, 0, 1);
-        checkState(wasRunning, "Attempted to seal an already-sealed Data Tree.");
+        // We want a full CAS with setVolatile() memory semantics, as we want to force happen-before for everything,
+        // including whatever user code works.
+        if (!SEALED.compareAndSet(this, 0, 1)) {
+            throw new IllegalStateException("Attempted to seal an already-sealed Data Tree.");
+        }
 
         var current = AbstractReadyIterator.create(rootNode, getStrategy());
         do {
             current = current.process(version);
         } while (current != null);
+
+        // Make sure all affects are visible before returning, as this object may be handed off to another thread, which
+        // needs to see any HashMap.modCount mutations completed. This is needed because isSealed() is now performing
+        // only the equivalent of an acquireFence()
+        VarHandle.releaseFence();
     }
 }