Rename recursive INode methods
[yangtools.git] / third-party / triemap / src / main / java / org / opendaylight / yangtools / triemap / MutableTrieMap.java
index 95151cdbf60fb9ad4a49263a3bcf5c89263dcf0a..adbf4997f0815436a8eb6703b4e52e5ce1314f94 100644 (file)
  */
 package org.opendaylight.yangtools.triemap;
 
-import static com.google.common.base.Preconditions.checkNotNull;
 import static com.google.common.base.Preconditions.checkState;
+import static java.util.Objects.requireNonNull;
 import static org.opendaylight.yangtools.triemap.PresencePredicate.ABSENT;
 import static org.opendaylight.yangtools.triemap.PresencePredicate.PRESENT;
 
 import com.google.common.annotations.Beta;
 import com.google.common.base.Verify;
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 import java.util.Optional;
 import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
 
@@ -34,7 +35,9 @@ import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
  * @param <V> the type of mapped values
  */
 @Beta
-final class MutableTrieMap<K, V> extends TrieMap<K, V> {
+public final class MutableTrieMap<K, V> extends TrieMap<K, V> {
+    private static final long serialVersionUID = 1L;
+
     @SuppressWarnings("rawtypes")
     private static final AtomicReferenceFieldUpdater<MutableTrieMap, Object> ROOT_UPDATER =
             AtomicReferenceFieldUpdater.newUpdater(MutableTrieMap.class, Object.class, "root");
@@ -47,54 +50,55 @@ final class MutableTrieMap<K, V> extends TrieMap<K, V> {
 
     MutableTrieMap(final Equivalence<? super K> equiv, final INode<K, V> root) {
         super(equiv);
-        this.root = checkNotNull(root);
+        this.root = requireNonNull(root);
     }
 
     @Override
     public void clear() {
-        boolean success;
+        INode<K, V> r;
         do {
-            final INode<K, V> r = RDCSS_READ_ROOT();
-            success = RDCSS_ROOT(r, r.gcasRead(this), newRootNode());
-        } while (!success);
+            r = RDCSS_READ_ROOT();
+        } while (!RDCSS_ROOT(r, r.gcasRead(this), newRootNode()));
     }
 
     @Override
     public V put(final K key, final V value) {
-        final K k = checkNotNull(key);
-        return toNullable(insertifhc(k, computeHash(k), checkNotNull(value), null));
+        final K k = requireNonNull(key);
+        return toNullable(insertifhc(k, computeHash(k), requireNonNull(value), null));
     }
 
     @Override
     public V putIfAbsent(final K key, final V value) {
-        final K k = checkNotNull(key);
-        return toNullable(insertifhc(k, computeHash(k), checkNotNull(value), ABSENT));
+        final K k = requireNonNull(key);
+        return toNullable(insertifhc(k, computeHash(k), requireNonNull(value), ABSENT));
     }
 
     @Override
     public V remove(final Object key) {
         @SuppressWarnings("unchecked")
-        final K k = (K) checkNotNull(key);
+        final K k = (K) requireNonNull(key);
         return toNullable(removehc(k, null, computeHash(k)));
     }
 
+    @SuppressFBWarnings(value = "NP_PARAMETER_MUST_BE_NONNULL_BUT_MARKED_AS_NULLABLE",
+            justification = "API contract allows null value, but we do not")
     @Override
     public boolean remove(final Object key, final Object value) {
         @SuppressWarnings("unchecked")
-        final K k = (K) checkNotNull(key);
-        return removehc(k, checkNotNull(value), computeHash(k)).isPresent();
+        final K k = (K) requireNonNull(key);
+        return removehc(k, requireNonNull(value), computeHash(k)).isPresent();
     }
 
     @Override
     public boolean replace(final K key, final V oldValue, final V newValue) {
-        final K k = checkNotNull(key);
-        return insertifhc(k, computeHash(k), checkNotNull(newValue), checkNotNull(oldValue)).isPresent();
+        final K k = requireNonNull(key);
+        return insertifhc(k, computeHash(k), requireNonNull(newValue), requireNonNull(oldValue)).isPresent();
     }
 
     @Override
     public V replace(final K key, final V value) {
-        final K k = checkNotNull(key);
-        return toNullable(insertifhc(k, computeHash(k), checkNotNull(value), PRESENT));
+        final K k = requireNonNull(key);
+        return toNullable(insertifhc(k, computeHash(k), requireNonNull(value), PRESENT));
     }
 
     @Override
@@ -102,30 +106,40 @@ final class MutableTrieMap<K, V> extends TrieMap<K, V> {
         return immutableSnapshot().size();
     }
 
+    private INode<K, V> snapshot() {
+        INode<K, V> r;
+        do {
+            r = RDCSS_READ_ROOT();
+        } while (!RDCSS_ROOT(r, r.gcasRead(this), r.copyToGen(new Gen(), this)));
+
+        return r;
+    }
+
     @Override
     public ImmutableTrieMap<K, V> immutableSnapshot() {
-        while (true) {
-            final INode<K, V> r = RDCSS_READ_ROOT();
-            final MainNode<K, V> expmain = r.gcasRead(this);
-            if (RDCSS_ROOT(r, expmain, r.copyToGen (new Gen(), this))) {
-                return new ImmutableTrieMap<>(r, equiv());
-            }
-
-            // Tail recursion: return readOnlySnapshot();
-        }
+        return new ImmutableTrieMap<>(snapshot(), equiv());
     }
 
     @Override
     public MutableTrieMap<K, V> mutableSnapshot() {
-        while (true) {
-            final INode<K, V> r = RDCSS_READ_ROOT();
-            final MainNode<K, V> expmain = r.gcasRead(this);
-            if (RDCSS_ROOT(r, expmain, r.copyToGen(new Gen(), this))) {
-                return new MutableTrieMap<>(equiv(), r.copyToGen(new Gen(), this));
-            }
+        return new MutableTrieMap<>(equiv(), snapshot().copyToGen(new Gen(), this));
+    }
 
-            // Tail recursion: return snapshot();
-        }
+    @Override
+    MutableEntrySet<K, V> createEntrySet() {
+        // FIXME: it would be nice to have a ReadWriteTrieMap with read-only iterator
+        //        if (readOnlyEntrySet) return ImmutableEntrySet(this);
+        return new MutableEntrySet<>(this);
+    }
+
+    @Override
+    MutableKeySet<K> createKeySet() {
+        return new MutableKeySet<>(this);
+    }
+
+    @Override
+    MutableIterator<K, V> iterator() {
+        return new MutableIterator<>(this);
     }
 
     @Override
@@ -134,6 +148,7 @@ final class MutableTrieMap<K, V> extends TrieMap<K, V> {
     }
 
     @Override
+    @SuppressWarnings("unchecked")
     INode<K, V> RDCSS_READ_ROOT(final boolean abort) {
         final Object r = /* READ */ root;
         if (r instanceof INode) {
@@ -145,8 +160,8 @@ final class MutableTrieMap<K, V> extends TrieMap<K, V> {
     }
 
     void add(final K key, final V value) {
-        final K k = checkNotNull(key);
-        inserthc(k, computeHash(k), checkNotNull(value));
+        final K k = requireNonNull(key);
+        inserthc(k, computeHash(k), requireNonNull(value));
     }
 
     private static <K,V> INode<K, V> newRootNode() {
@@ -154,28 +169,28 @@ final class MutableTrieMap<K, V> extends TrieMap<K, V> {
         return new INode<>(gen, new CNode<>(gen));
     }
 
-    private void inserthc(final K k, final int hc, final V v) {
+    private void inserthc(final K key, final int hc, final V value) {
         // TODO: this is called from serialization only, which means we should not be observing any races,
         //       hence we should not need to pass down the entire tree, just equality (I think).
-        final boolean success = RDCSS_READ_ROOT().rec_insert(k, v, hc, 0, null, this);
+        final boolean success = RDCSS_READ_ROOT().recInsert(key, value, hc, 0, null, this);
         Verify.verify(success, "Concurrent modification during serialization of map %s", this);
     }
 
-    private Optional<V> insertifhc(final K k, final int hc, final V v, final Object cond) {
+    private Optional<V> insertifhc(final K key, final int hc, final V value, final Object cond) {
         Optional<V> res;
         do {
             // Keep looping as long as we do not get a reply
-            res = RDCSS_READ_ROOT().rec_insertif(k, v, hc, cond, 0, null, this);
+            res = RDCSS_READ_ROOT().recInsertIf(key, value, hc, cond, 0, null, this);
         } while (res == null);
 
         return res;
     }
 
-    private Optional<V> removehc(final K k, final Object cond, final int hc) {
+    private Optional<V> removehc(final K key, final Object cond, final int hc) {
         Optional<V> res;
         do {
             // Keep looping as long as we do not get a reply
-            res = RDCSS_READ_ROOT().rec_remove(k, cond, hc, 0, null, this);
+            res = RDCSS_READ_ROOT().recRemove(key, cond, hc, 0, null, this);
         } while (res == null);
 
         return res;
@@ -186,7 +201,7 @@ final class MutableTrieMap<K, V> extends TrieMap<K, V> {
     }
 
     private boolean RDCSS_ROOT(final INode<K, V> ov, final MainNode<K, V> expectedmain, final INode<K, V> nv) {
-        final RDCSS_Descriptor<K, V> desc = new RDCSS_Descriptor<> (ov, expectedmain, nv);
+        final RDCSS_Descriptor<K, V> desc = new RDCSS_Descriptor<>(ov, expectedmain, nv);
         if (CAS_ROOT(ov, desc)) {
             RDCSS_Complete(false);
             return /* READ */desc.committed;
@@ -195,6 +210,7 @@ final class MutableTrieMap<K, V> extends TrieMap<K, V> {
         return false;
     }
 
+    @SuppressWarnings("unchecked")
     private INode<K, V> RDCSS_Complete(final boolean abort) {
         while (true) {
             final Object r = /* READ */ root;
@@ -203,7 +219,6 @@ final class MutableTrieMap<K, V> extends TrieMap<K, V> {
             }
 
             checkState(r instanceof RDCSS_Descriptor, "Unhandled root %s", r);
-            @SuppressWarnings("unchecked")
             final RDCSS_Descriptor<K, V> desc = (RDCSS_Descriptor<K, V>) r;
             final INode<K, V> ov = desc.old;
             final MainNode<K, V> exp = desc.expectedmain;
@@ -244,7 +259,7 @@ final class MutableTrieMap<K, V> extends TrieMap<K, V> {
 
         volatile boolean committed = false;
 
-        RDCSS_Descriptor (final INode<K, V> old, final MainNode<K, V> expectedmain, final INode<K, V> nv) {
+        RDCSS_Descriptor(final INode<K, V> old, final MainNode<K, V> expectedmain, final INode<K, V> nv) {
             this.old = old;
             this.expectedmain = expectedmain;
             this.nv = nv;