From 28446aaf2743ff55abab2b7a2dad670b5f670800 Mon Sep 17 00:00:00 2001 From: Robert Varga Date: Sat, 31 Dec 2016 19:06:20 +0100 Subject: [PATCH] BUG-7464: Cleanup Triemap Remove unused methods, make the public contract more lean and eliminate unneeded else branches. Change-Id: I79d74b2dd13b912fef493294e7afc01a1fd7c85a Signed-off-by: Robert Varga --- .../yangtools/triemap/TrieMap.java | 483 +++++++----------- .../triemap/TestInstantiationSpeed.java | 2 +- 2 files changed, 188 insertions(+), 297 deletions(-) diff --git a/third-party/triemap/src/main/java/org/opendaylight/yangtools/triemap/TrieMap.java b/third-party/triemap/src/main/java/org/opendaylight/yangtools/triemap/TrieMap.java index 66019e3f27..d64875007e 100644 --- a/third-party/triemap/src/main/java/org/opendaylight/yangtools/triemap/TrieMap.java +++ b/third-party/triemap/src/main/java/org/opendaylight/yangtools/triemap/TrieMap.java @@ -32,7 +32,8 @@ import java.util.concurrent.ConcurrentMap; import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; /*** - * This is a port of Scala's TrieMap class from the Scala Collections library. + * This is a port of Scala's TrieMap class from the Scala Collections library. This implementation does not support + * null keys nor null values. * * @author Roman Levenstein <romixlev@gmail.com> * @@ -40,11 +41,11 @@ import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; * @param */ @SuppressWarnings({"unchecked", "rawtypes", "unused"}) -public class TrieMap extends AbstractMap implements ConcurrentMap, Serializable { - private static final AtomicReferenceFieldUpdater ROOT_UPDATER = AtomicReferenceFieldUpdater.newUpdater(TrieMap.class, Object.class, "root"); +public final class TrieMap extends AbstractMap implements ConcurrentMap, Serializable { + private static final AtomicReferenceFieldUpdater ROOT_UPDATER = + AtomicReferenceFieldUpdater.newUpdater(TrieMap.class, Object.class, "root"); private static final long serialVersionUID = 1L; private static final Field READONLY_FIELD; - private static final TrieMap EMPTY = new TrieMap(); static { final Field f; @@ -64,39 +65,15 @@ public class TrieMap extends AbstractMap implements ConcurrentMap TrieMap empty () { - return EMPTY; - } - - // static class MangledHashing extends Hashing { - // int hash(K k) { - // return util.hashing.byteswap32(k); - // } - // } - - private static class RDCSS_Descriptor { - INode old; - MainNode expectedmain; - INode nv; - volatile boolean committed = false; - - public RDCSS_Descriptor (final INode old, final MainNode expectedmain, final INode nv) { - this.old = old; - this.expectedmain = expectedmain; - this.nv = nv; - } - } - private final Equivalence equiv; private transient volatile Object root; private final transient boolean readOnly; - TrieMap (final Object r, final Equivalence equiv, final boolean readOnly) { + TrieMap(final INode r, final Equivalence equiv, final boolean readOnly) { this.root = r; this.equiv = equiv; this.readOnly = readOnly; - } public TrieMap() { @@ -105,39 +82,7 @@ public class TrieMap extends AbstractMap implements ConcurrentMap INode newRootNode() { + private static INode newRootNode() { final Gen gen = new Gen(); return new INode<>(gen, new CNode<>(gen)); } @@ -150,109 +95,105 @@ public class TrieMap extends AbstractMap implements ConcurrentMap readRoot (final boolean abort) { - return RDCSS_READ_ROOT (abort); + final INode readRoot(final boolean abort) { + return RDCSS_READ_ROOT(abort); } - final INode readRoot () { - return RDCSS_READ_ROOT (false); + final INode readRoot() { + return RDCSS_READ_ROOT(false); } - final INode RDCSS_READ_ROOT () { - return RDCSS_READ_ROOT (false); + final INode RDCSS_READ_ROOT() { + return RDCSS_READ_ROOT(false); } - final INode RDCSS_READ_ROOT (final boolean abort) { - Object r = /* READ */root; + final INode RDCSS_READ_ROOT(final boolean abort) { + final Object r = /* READ */root; if (r instanceof INode) { return (INode) r; } else if (r instanceof RDCSS_Descriptor) { return RDCSS_Complete (abort); + } else { + throw new IllegalStateException("Unhandled root " + r); } - throw new RuntimeException ("Should not happen"); } - private final INode RDCSS_Complete (final boolean abort) { + private INode RDCSS_Complete(final boolean abort) { while (true) { - Object v = /* READ */root; + final Object v = /* READ */root; if (v instanceof INode) { return (INode) v; - } else if (v instanceof RDCSS_Descriptor) { - RDCSS_Descriptor desc = (RDCSS_Descriptor) v; - INode ov = desc.old; - MainNode exp = desc.expectedmain; - INode nv = desc.nv; + } + + if (v instanceof RDCSS_Descriptor) { + final RDCSS_Descriptor desc = (RDCSS_Descriptor) v; + final INode ov = desc.old; + final MainNode exp = desc.expectedmain; + final INode nv = desc.nv; if (abort) { - if (CAS_ROOT (desc, ov)) { + if (CAS_ROOT(desc, ov)) { return ov; - } else { - // return RDCSS_Complete (abort); - // tailrec - continue; } - } else { - MainNode oldmain = ov.gcasRead (this); - if (oldmain == exp) { - if (CAS_ROOT (desc, nv)) { - desc.committed = true; - return nv; - } else { - // return RDCSS_Complete (abort); - // tailrec - continue; - } - } else { - if (CAS_ROOT (desc, ov)) { - return ov; - } else { - // return RDCSS_Complete (abort); - // tailrec - continue; - - } + + // Tail recursion: return RDCSS_Complete(abort); + continue; + } + + final MainNode oldmain = ov.gcasRead(this); + if (oldmain == exp) { + if (CAS_ROOT(desc, nv)) { + desc.committed = true; + return nv; } + + // Tail recursion: return RDCSS_Complete(abort); + continue; + } + + if (CAS_ROOT(desc, ov)) { + return ov; } + + // Tail recursion: return RDCSS_Complete(abort); + continue; } - throw new RuntimeException ("Should not happen"); + throw new IllegalStateException("Unexpected root " + v); } } - private boolean RDCSS_ROOT (final INode ov, final MainNode expectedmain, final INode nv) { - RDCSS_Descriptor desc = new RDCSS_Descriptor<> (ov, expectedmain, nv); - if (CAS_ROOT (ov, desc)) { - RDCSS_Complete (false); + private boolean RDCSS_ROOT(final INode ov, final MainNode expectedmain, final INode nv) { + final RDCSS_Descriptor desc = new RDCSS_Descriptor<> (ov, expectedmain, nv); + if (CAS_ROOT(ov, desc)) { + RDCSS_Complete(false); return /* READ */desc.committed; - } else { - return false; } + + return false; } - private void inserthc (final K k, final int hc, final V v) { + private void inserthc(final K k, final int hc, final V v) { while (true) { - INode r = RDCSS_READ_ROOT (); - if (!r.rec_insert (k, v, hc, 0, null, r.gen, this)) { - // inserthc (k, hc, v); - // tailrec - continue; + final INode r = RDCSS_READ_ROOT(); + if (r.rec_insert(k, v, hc, 0, null, r.gen, this)) { + // Successful, we are done + return; } - break; + + // Tail recursion: inserthc(k, hc, v); } } - private Option insertifhc (final K k, final int hc, final V v, final Object cond) { + private Option insertifhc(final K k, final int hc, final V v, final Object cond) { while (true) { - INode r = RDCSS_READ_ROOT (); - - Option ret = r.rec_insertif (k, v, hc, cond, 0, null, r.gen, this); - if (ret == null) { - // return insertifhc (k, hc, v, cond); - // tailrec - continue; - } else { + final INode r = RDCSS_READ_ROOT(); + final Option ret = r.rec_insertif(k, v, hc, cond, 0, null, r.gen, this); + if (ret != null) { return ret; } + + // Tail recursion: return insertifhc(k, hc, v, cond); } } @@ -268,17 +209,15 @@ public class TrieMap extends AbstractMap implements ConcurrentMap removehc (final K k, final V v, final int hc) { + private Option removehc(final K k, final V v, final int hc) { while (true) { - INode r = RDCSS_READ_ROOT (); - Option res = r.rec_remove (k, v, hc, 0, null, r.gen, this); + final INode r = RDCSS_READ_ROOT(); + final Option res = r.rec_remove(k, v, hc, 0, null, r.gen, this); if (res != null) { return res; - } else { - // return removehc (k, v, hc); - // tailrec - continue; } + + // Tail recursion: return removehc(k, v, hc); } } @@ -292,31 +231,16 @@ public class TrieMap extends AbstractMap implements ConcurrentMap seq() { - // return this; - // } - - // override def par = new ParTrieMap(this) - - // static TrieMap empty() { - // return new TrieMap(); - // } - - final boolean isReadOnly () { + boolean isReadOnly() { return readOnly; } - final boolean nonReadOnly () { + boolean nonReadOnly() { return !readOnly; } + /* public methods */ + /** * Returns a snapshot of this TrieMap. This operation is lock-free and * linearizable. @@ -327,18 +251,15 @@ public class TrieMap extends AbstractMap implements ConcurrentMap snapshot () { + public TrieMap snapshot() { while (true) { - INode r = RDCSS_READ_ROOT (); - final MainNode expmain = r.gcasRead (this); - if (RDCSS_ROOT (r, expmain, r.copyToGen (new Gen (), this))) { - return new TrieMap<> (r.copyToGen (new Gen (), this), equiv, readOnly); - } else { - // return snapshot (); - // tailrec - continue; + final INode r = RDCSS_READ_ROOT(); + final MainNode expmain = r.gcasRead(this); + if (RDCSS_ROOT(r, expmain, r.copyToGen(new Gen(), this))) { + return new TrieMap<> (r.copyToGen(new Gen(), this), equiv, readOnly); } + + // Tail recursion: return snapshot(); } } @@ -355,31 +276,28 @@ public class TrieMap extends AbstractMap implements ConcurrentMap readOnlySnapshot () { + public TrieMap readOnlySnapshot() { // Is it a snapshot of a read-only snapshot? - if(!nonReadOnly ()) { + if (isReadOnly()) { return this; } while (true) { - INode r = RDCSS_READ_ROOT (); - MainNode expmain = r.gcasRead (this); - if (RDCSS_ROOT (r, expmain, r.copyToGen (new Gen (), this))) { - return new TrieMap<> (r, equiv, true); - } else { - // return readOnlySnapshot (); - continue; + final INode r = RDCSS_READ_ROOT(); + final MainNode expmain = r.gcasRead(this); + if (RDCSS_ROOT(r, expmain, r.copyToGen (new Gen(), this))) { + return new TrieMap<>(r, equiv, true); } + + // Tail recursion: return readOnlySnapshot(); } } @Override - final public void clear () { + public void clear() { while (true) { - INode r = RDCSS_READ_ROOT (); - if (!RDCSS_ROOT(r, r.gcasRead(this), newRootNode())) { - continue; - }else{ + final INode r = RDCSS_READ_ROOT(); + if (RDCSS_ROOT(r, r.gcasRead(this), newRootNode())) { return; } } @@ -393,13 +311,13 @@ public class TrieMap extends AbstractMap implements ConcurrentMap)o).get (); - } else if(o instanceof None) { + } else if (o instanceof None) { return null; } else { return (V)o; @@ -407,109 +325,80 @@ public class TrieMap extends AbstractMap implements ConcurrentMap putOpt(final Object key, final Object value) { - int hc = computeHash ((K)key); - return insertifhc ((K)key, hc, (V)value, null); - } - @Override - final public V put (final Object key, final Object value) { + public V put(final K key, final V value) { ensureReadWrite(); - int hc = computeHash ((K)key); - Option ov = insertifhc ((K)key, hc, (V)value, null); - if(ov instanceof Some) { + final int hc = computeHash(key); + final Option ov = insertifhc (key, hc, value, null); + if (ov instanceof Some) { Some sv = (Some)ov; return sv.get (); - } else { - return null; } - } - final public void update (final K k, final V v) { - int hc = computeHash (k); - inserthc (k, hc, v); + return null; } - final public TrieMap add (final K k, final V v) { - update (k, v); + TrieMap add(final K k, final V v) { + final int hc = computeHash (k); + inserthc (k, hc, v); return this; } - final Option removeOpt (final K k) { - int hc = computeHash (k); - return removehc (k, (V) null, hc); - } - @Override - final public V remove (final Object k) { + public V remove(final Object k) { ensureReadWrite(); - int hc = computeHash ((K)k); - Option ov = removehc ((K)k, (V) null, hc); - if(ov instanceof Some) { + final int hc = computeHash ((K)k); + final Option ov = removehc ((K)k, (V) null, hc); + if (ov instanceof Some) { Some sv = (Some)ov; return sv.get(); - } else { - return null; } - } - -// final public TrieMap remove (Object k) { -// removeOpt ((K)k); -// return this; -// } - final public Option putIfAbsentOpt (final K k, final V v) { - int hc = computeHash (k); - return insertifhc (k, hc, v, INode.KEY_ABSENT); + return null; } @Override - final public V putIfAbsent (final Object k, final Object v) { + public V putIfAbsent(final K k, final V v) { ensureReadWrite(); - int hc = computeHash ((K)k); - Option ov = insertifhc ((K)k, hc, (V)v, INode.KEY_ABSENT); - if(ov instanceof Some) { + final int hc = computeHash (k); + final Option ov = insertifhc (k, hc, v, INode.KEY_ABSENT); + if (ov instanceof Some) { Some sv = (Some)ov; return sv.get(); - } else { - return null; } + + return null; } @Override - public boolean remove (final Object k, final Object v) { + public boolean remove(final Object k, final Object v) { ensureReadWrite(); - int hc = computeHash ((K)k); - return removehc ((K)k, (V)v, hc).nonEmpty (); + final int hc = computeHash ((K)k); + return removehc((K)k, (V)v, hc).nonEmpty(); } @Override - public boolean replace (final K k, final V oldvalue, final V newvalue) { + public boolean replace(final K k, final V oldvalue, final V newvalue) { ensureReadWrite(); - int hc = computeHash (k); - return insertifhc (k, hc, newvalue, oldvalue).nonEmpty (); - } - - public Option replaceOpt (final K k, final V v) { - int hc = computeHash (k); - return insertifhc (k, hc, v, INode.KEY_PRESENT); + final int hc = computeHash (k); + return insertifhc (k, hc, newvalue, oldvalue).nonEmpty(); } @Override - public V replace (final Object k, final Object v) { + public V replace(final K k, final V v) { ensureReadWrite(); - int hc = computeHash ((K)k); - Option ov = insertifhc ((K)k, hc, (V)v, INode.KEY_PRESENT); - if(ov instanceof Some) { + final int hc = computeHash (k); + final Option ov = insertifhc (k, hc, v, INode.KEY_PRESENT); + if (ov instanceof Some) { Some sv = (Some)ov; return sv.get(); - } else { - return null; } + + return null; } /*** @@ -522,12 +411,12 @@ public class TrieMap extends AbstractMap implements ConcurrentMap> iterator () { - if (!nonReadOnly ()) { - return readOnlySnapshot ().readOnlyIterator (); - } else { - return new TrieMapIterator<> (0, this); + Iterator> iterator () { + if (!nonReadOnly()) { + return readOnlySnapshot().readOnlyIterator(); } + + return new TrieMapIterator<> (0, this); } /*** @@ -536,30 +425,49 @@ public class TrieMap extends AbstractMap implements ConcurrentMap> readOnlyIterator () { - if (nonReadOnly ()) { - return readOnlySnapshot ().readOnlyIterator (); - } else { - return new TrieMapReadOnlyIterator<> (0, this); + Iterator> readOnlyIterator () { + if (nonReadOnly()) { + return readOnlySnapshot().readOnlyIterator(); } + + return new TrieMapReadOnlyIterator<>(0, this); } - private int cachedSize () { + private int cachedSize() { INode r = RDCSS_READ_ROOT (); return r.cachedSize (this); } @Override - public int size () { - if (nonReadOnly ()) { - return readOnlySnapshot ().size (); - } else { - return cachedSize (); + public int size() { + if (nonReadOnly()) { + return readOnlySnapshot().size (); } + + return cachedSize(); } - String stringPrefix () { - return "TrieMap"; + @Override + public boolean containsKey(final Object key) { + return lookup((K) key) != null; + } + + @Override + public Set> entrySet() { + return entrySet; + } + + private static final class RDCSS_Descriptor { + INode old; + MainNode expectedmain; + INode nv; + volatile boolean committed = false; + + RDCSS_Descriptor (final INode old, final MainNode expectedmain, final INode nv) { + this.old = old; + this.expectedmain = expectedmain; + this.nv = nv; + } } /*** @@ -569,7 +477,7 @@ public class TrieMap extends AbstractMap implements ConcurrentMap * @param */ - private static class TrieMapReadOnlyIterator extends TrieMapIterator { + private static final class TrieMapReadOnlyIterator extends TrieMapIterator { TrieMapReadOnlyIterator (final int level, final TrieMap ct, final boolean mustInit) { super (level, ct, mustInit); } @@ -589,22 +497,22 @@ public class TrieMap extends AbstractMap implements ConcurrentMap nextEntry(final Map.Entry rr) { + Entry nextEntry(final Entry rr) { // Return non-updatable entry return rr; } } - private static class TrieMapIterator implements java.util.Iterator> { + private static class TrieMapIterator implements Iterator> { private int level; protected TrieMap ct; private final boolean mustInit; private final BasicNode[][] stack = new BasicNode[7][]; private final int[] stackpos = new int[7]; private int depth = -1; - private Iterator> subiter = null; + private Iterator> subiter = null; private KVNode current = null; - private Map.Entry lastReturned = null; + private Entry lastReturned = null; TrieMapIterator (final int level, final TrieMap ct, final boolean mustInit) { this.level = level; @@ -626,9 +534,9 @@ public class TrieMap extends AbstractMap implements ConcurrentMap next () { + public Entry next () { if (hasNext ()) { - Map.Entry r = null; + Entry r = null; if (subiter != null) { r = subiter.next (); checkSubiter (); @@ -639,7 +547,7 @@ public class TrieMap extends AbstractMap implements ConcurrentMap rr = r; + final Entry rr = r; return nextEntry(rr); } return r; @@ -649,8 +557,8 @@ public class TrieMap extends AbstractMap implements ConcurrentMap nextEntry(final Map.Entry rr) { - return new Map.Entry() { + Entry nextEntry(final Entry rr) { + return new Entry() { private V updated = null; @Override @@ -742,7 +650,7 @@ public class TrieMap extends AbstractMap implements ConcurrentMap> lst = toList (this.subiter); + List> lst = toList (this.subiter); this.subiter = lst.iterator (); it.subiter = lst.iterator (); } @@ -813,39 +721,22 @@ public class TrieMap extends AbstractMap implements ConcurrentMap> entrySet () { - return entrySet; - } - /*** * Support for EntrySet operations required by the Map interface - * */ - final class EntrySet extends AbstractSet> { + private final class EntrySet extends AbstractSet> { @Override - public Iterator> iterator () { + public Iterator> iterator () { return TrieMap.this.iterator (); } @Override public final boolean contains (final Object o) { - if (!(o instanceof Map.Entry)) { + if (!(o instanceof Entry)) { return false; } - final Map.Entry e = (Map.Entry) o; + final Entry e = (Entry) o; final K k = e.getKey (); final V v = lookup (k); return v != null; @@ -853,12 +744,12 @@ public class TrieMap extends AbstractMap implements ConcurrentMap e = (Map.Entry) o; - final K k = e.getKey (); - return null != TrieMap.this.remove (k); + final Entry e = (Entry) o; + final K k = e.getKey(); + return null != TrieMap.this.remove(k); } @Override diff --git a/third-party/triemap/src/test/java/org/opendaylight/yangtools/triemap/TestInstantiationSpeed.java b/third-party/triemap/src/test/java/org/opendaylight/yangtools/triemap/TestInstantiationSpeed.java index be6cbb1274..7eafe1e524 100644 --- a/third-party/triemap/src/test/java/org/opendaylight/yangtools/triemap/TestInstantiationSpeed.java +++ b/third-party/triemap/src/test/java/org/opendaylight/yangtools/triemap/TestInstantiationSpeed.java @@ -27,7 +27,7 @@ public class TestInstantiationSpeed { final long start = System.nanoTime(); for (int i = 0; i < COUNT; ++i) { - maps[i] = TrieMap.empty(); + maps[i] = new TrieMap<>(); } final long stop = System.nanoTime(); -- 2.36.6