BUG-7464: update INode.GCAS_Complete()
[yangtools.git] / third-party / triemap / src / main / java / org / opendaylight / yangtools / triemap / INode.java
index a619894587e0caeaeba8f453537d2c3ccaeae594..23046ed0e835f5148c6003ce2b14708ee4666ff5 100644 (file)
@@ -20,6 +20,7 @@ import static org.opendaylight.yangtools.triemap.LookupResult.RESTART;
 import static org.opendaylight.yangtools.triemap.PresencePredicate.ABSENT;
 import static org.opendaylight.yangtools.triemap.PresencePredicate.PRESENT;
 
+import com.google.common.base.VerifyException;
 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 import java.util.Optional;
 import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
@@ -52,15 +53,12 @@ final class INode<K, V> extends BasicNode {
         return GCAS_Complete(m, ct);
     }
 
-    private MainNode<K, V> GCAS_Complete(MainNode<K, V> m, final TrieMap<?, ?> ct) {
-        while (true) {
-            if (m == null) {
-                return null;
-            }
-
+    private MainNode<K, V> GCAS_Complete(final MainNode<K, V> oldmain, final TrieMap<?, ?> ct) {
+        MainNode<K, V> m = oldmain;
+        while (m != null) {
             // complete the GCAS
             final MainNode<K, V> prev = /* READ */ m.READ_PREV();
-            final Gen rdgen = ct.readRoot(true).gen;
+            final INode<?, ?> ctr = ct.readRoot(true);
             if (prev == null) {
                 return m;
             }
@@ -72,7 +70,7 @@ final class INode<K, V> extends BasicNode {
                     return fn.READ_PREV();
                 }
 
-                // Tail recursion: return GCAS_Complete (/* READ */ mainnode, ct);
+                // Tail recursion: return GCAS_Complete(/* READ */ mainnode, ct);
                 m = /* READ */ mainnode;
                 continue;
             }
@@ -85,13 +83,13 @@ final class INode<K, V> extends BasicNode {
             // ==> if `ctr.gen` = `gen` then they are both equal to G.
             // ==> otherwise, we know that either `ctr.gen` > G, `gen` < G,
             // or both
-            if (rdgen == gen && !ct.isReadOnly()) {
+            if (ctr.gen == gen && !ct.isReadOnly()) {
                 // try to commit
                 if (m.CAS_PREV(prev, null)) {
                     return m;
                 }
 
-                // Tail recursion: return GCAS_Complete (m, ct);
+                // Tail recursion: return GCAS_Complete(m, ct);
                 continue;
             }
 
@@ -101,6 +99,8 @@ final class INode<K, V> extends BasicNode {
             // Tail recursion: return GCAS_Complete(/* READ */ mainnode, ct);
             m = /* READ */ mainnode;
         }
+
+        return null;
     }
 
     private boolean GCAS(final MainNode<K, V> old, final MainNode<K, V> n, final TrieMap<?, ?> ct) {
@@ -126,9 +126,9 @@ final class INode<K, V> extends BasicNode {
      *
      * @return true if successful, false otherwise
      */
-    boolean rec_insert(final K k, final V v, final int hc, final int lev, final INode<K, V> parent,
+    boolean rec_insert(final K key, final V value, final int hc, final int lev, final INode<K, V> parent,
             final TrieMap<K, V> ct) {
-        return rec_insert(k, v, hc, lev, parent, gen, ct);
+        return rec_insert(key, value, hc, lev, parent, gen, ct);
     }
 
     private boolean rec_insert(final K k, final V v, final int hc, final int lev, final INode<K, V> parent,
@@ -154,7 +154,7 @@ final class INode<K, V> extends BasicNode {
                             return in.rec_insert(k, v, hc, lev + LEVEL_BITS, this, startgen, ct);
                         }
                         if (GCAS(cn, cn.renewed(startgen, ct), ct)) {
-                            // Tail recursion: return rec_insert (k, v, hc, lev, parent, startgen, ct);
+                            // Tail recursion: return rec_insert(k, v, hc, lev, parent, startgen, ct);
                             continue;
                         }
 
@@ -166,14 +166,17 @@ final class INode<K, V> extends BasicNode {
                         }
 
                         final CNode<K, V> rn = (cn.gen == gen) ? cn : cn.renewed(gen, ct);
-                        final MainNode<K, V> nn = rn.updatedAt(pos, inode(CNode.dual(sn, k, v, hc, lev + LEVEL_BITS, gen)), gen);
-                        return GCAS (cn, nn, ct);
+                        final MainNode<K, V> nn = rn.updatedAt(pos, inode(
+                            CNode.dual(sn, k, v, hc, lev + LEVEL_BITS, gen)), gen);
+                        return GCAS(cn, nn, ct);
+                    } else {
+                        throw CNode.invalidElement(cnAtPos);
                     }
-                } else {
-                    final CNode<K, V> rn = (cn.gen == gen) ? cn : cn.renewed(gen, ct);
-                    final MainNode<K, V> ncnode = rn.insertedAt(pos, flag, new SNode<>(k, v, hc), gen);
-                    return GCAS (cn, ncnode, ct);
                 }
+
+                final CNode<K, V> rn = (cn.gen == gen) ? cn : cn.renewed(gen, ct);
+                final MainNode<K, V> ncnode = rn.insertedAt(pos, flag, new SNode<>(k, v, hc), gen);
+                return GCAS(cn, ncnode, ct);
             } else if (m instanceof TNode) {
                 clean(parent, ct, lev - LEVEL_BITS);
                 return false;
@@ -182,13 +185,24 @@ final class INode<K, V> extends BasicNode {
                 final LNodeEntry<K, V> entry = ln.get(ct.equiv(), k);
                 return entry != null ? replaceln(ln, entry, v, ct) : insertln(ln, k, v, ct);
             } else {
-                throw new IllegalStateException("Unhandled node " + m);
+                throw invalidElement(m);
             }
-
-            throw new RuntimeException ("Should not happen");
         }
     }
 
+    private static VerifyException invalidElement(final BasicNode elem) {
+        throw new VerifyException("An INode can host only a CNode, a TNode or an LNode, not " + elem);
+    }
+
+    @SuppressFBWarnings(value = "NP_OPTIONAL_RETURN_NULL",
+            justification = "Returning null Optional indicates the need to restart.")
+    private Optional<V> insertDual(final TrieMap<K, V> ct, final CNode<K, V> cn, final int pos, final SNode<K, V> sn,
+            final K k, final V v, final int hc, final int lev) {
+        final CNode<K, V> rn = (cn.gen == gen) ? cn : cn.renewed(gen, ct);
+        final MainNode<K, V> nn = rn.updatedAt(pos, inode(CNode.dual(sn, k, v, hc, lev + LEVEL_BITS, gen)), gen);
+        return GCAS(cn, nn, ct) ? Optional.empty() : null;
+    }
+
     /**
      * Inserts a new key value pair, given that a specific condition is met.
      *
@@ -205,15 +219,6 @@ final class INode<K, V> extends BasicNode {
         return rec_insertif(k, v, hc, cond, lev, parent, gen, ct);
     }
 
-    @SuppressFBWarnings(value = "NP_OPTIONAL_RETURN_NULL",
-            justification = "Returning null Optional indicates the need to restart.")
-    private Optional<V> insertDual(final TrieMap<K, V> ct, final CNode<K, V> cn, final int pos, final SNode<K, V> sn,
-            final K k, final V v, final int hc, final int lev) {
-        final CNode<K, V> rn = (cn.gen == gen) ? cn : cn.renewed(gen, ct);
-        final MainNode<K, V> nn = rn.updatedAt(pos, inode(CNode.dual(sn, k, v, hc, lev + LEVEL_BITS, gen)), gen);
-        return GCAS(cn, nn, ct) ? Optional.empty() : null;
-    }
-
     @SuppressFBWarnings(value = "NP_OPTIONAL_RETURN_NULL",
             justification = "Returning null Optional indicates the need to restart.")
     private Optional<V> rec_insertif(final K k, final V v, final int hc, final Object cond, final int lev,
@@ -240,7 +245,7 @@ final class INode<K, V> extends BasicNode {
                         }
 
                         if (GCAS(cn, cn.renewed(startgen, ct), ct)) {
-                            // Tail recursion: return rec_insertif (k, v, hc, cond, lev, parent, startgen, ct);
+                            // Tail recursion: return rec_insertif(k, v, hc, cond, lev, parent, startgen, ct);
                             continue;
                         }
 
@@ -283,10 +288,12 @@ final class INode<K, V> extends BasicNode {
 
                             return Optional.empty();
                         }
+                    } else {
+                        throw CNode.invalidElement(cnAtPos);
                     }
                 } else if (cond == null || cond == ABSENT) {
                     final CNode<K, V> rn = (cn.gen == gen) ? cn : cn.renewed(gen, ct);
-                    final CNode<K, V> ncnode = rn.insertedAt (pos, flag, new SNode<>(k, v, hc), gen);
+                    final CNode<K, V> ncnode = rn.insertedAt(pos, flag, new SNode<>(k, v, hc), gen);
                     if (GCAS(cn, ncnode, ct)) {
                         return Optional.empty();
                     }
@@ -329,10 +336,8 @@ final class INode<K, V> extends BasicNode {
                     return replaceln(ln, entry, v, ct) ? Optional.of(entry.getValue()) : null;
                 }
             } else {
-                throw new IllegalStateException("Unhandled node " + m);
+                throw invalidElement(m);
             }
-
-            throw new RuntimeException("Should never happen");
         }
     }
 
@@ -394,6 +399,8 @@ final class INode<K, V> extends BasicNode {
                     }
 
                     return null;
+                } else {
+                    throw CNode.invalidElement(sub);
                 }
             } else if (m instanceof TNode) {
                 // 3) non-live node
@@ -403,10 +410,8 @@ final class INode<K, V> extends BasicNode {
                 final LNodeEntry<K, V> entry = ((LNode<K, V>) m).get(ct.equiv(), k);
                 return entry != null ? entry.getValue() : null;
             } else {
-                throw new IllegalStateException("Unhandled node " + m);
+                throw invalidElement(m);
             }
-
-            throw new RuntimeException ("Should not happen");
         }
     }
 
@@ -456,19 +461,18 @@ final class INode<K, V> extends BasicNode {
 
             final int pos = Integer.bitCount(bmp & (flag - 1));
             final BasicNode sub = cn.array[pos];
-            Optional<V> res = null;
+            final Optional<V> res;
             if (sub instanceof INode) {
                 final INode<K, V> in = (INode<K, V>) sub;
                 if (startgen == in.gen) {
                     res = in.rec_remove(k, cond, hc, lev + LEVEL_BITS, this, startgen, ct);
                 } else {
-                    if (GCAS(cn, cn.renewed (startgen, ct), ct)) {
+                    if (GCAS(cn, cn.renewed(startgen, ct), ct)) {
                         res = rec_remove(k, cond, hc, lev, parent, startgen, ct);
                     } else {
                         res = null;
                     }
                 }
-
             } else if (sub instanceof SNode) {
                 final SNode<K, V> sn = (SNode<K, V>) sub;
                 if (sn.hc == hc && ct.equal(sn.k, k) && (cond == null || cond.equals(sn.v))) {
@@ -481,6 +485,8 @@ final class INode<K, V> extends BasicNode {
                 } else {
                     res = Optional.empty();
                 }
+            } else {
+                throw CNode.invalidElement(sub);
             }
 
             if (res == null || !res.isPresent()) {
@@ -515,7 +521,7 @@ final class INode<K, V> extends BasicNode {
 
             return GCAS(ln, ln.removeChild(entry, hc), ct) ? Optional.of(value) : null;
         } else {
-            throw new IllegalStateException("Unhandled node " + m);
+            throw invalidElement(m);
         }
     }
 
@@ -563,8 +569,8 @@ final class INode<K, V> extends BasicNode {
         }
     }
 
-    int cachedSize(final TrieMap<?, ?> ct) {
-        return GCAS_READ(ct).cachedSize(ct);
+    int size(final ImmutableTrieMap<?, ?> ct) {
+        return GCAS_READ(ct).size(ct);
     }
 
     // /* this is a quiescent method! */
@@ -582,4 +588,4 @@ final class INode<K, V> extends BasicNode {
     String string(final int lev) {
         return "INode";
     }
-}
\ No newline at end of file
+}