This field is accessed either as CAS or READ, with writes being
a falso positiive, in that they are performed only at initialization
time.
Refactor access patterns to hide the updater and the field, passing
down explicit initializer from the subclass.
Also remove INodeBase.prev(), as it is not called from anywhere.
Change-Id: I3bfcc7e7a606b3a0622ed04b99abbc67e41eb407
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
int bmp = (1 << xidx) | (1 << yidx);
if (xidx == yidx) {
int bmp = (1 << xidx) | (1 << yidx);
if (xidx == yidx) {
- INode<K, V> subinode = new INode<>(gen);// (TrieMap.inodeupdater)
- subinode.mainnode = dual (x, xhc, y, yhc, lev + 5, gen);
+ INode<K, V> subinode = new INode<>(gen, dual(x, xhc, y, yhc, lev + 5, gen));
return new CNode<>(bmp, new BasicNode[] { subinode }, gen);
} else {
if (xidx < yidx) {
return new CNode<>(bmp, new BasicNode[] { subinode }, gen);
} else {
if (xidx < yidx) {
static final Object KEY_PRESENT = new Object ();
static final Object KEY_ABSENT = new Object ();
static final Object KEY_PRESENT = new Object ();
static final Object KEY_ABSENT = new Object ();
+ /**
+ * Virtual result for lookup methods indicating that the lookup needs to be restarted. This is a faster version
+ * of throwing a checked exception to control the restart.
+ */
+ static final Object RESTART = new Object();
+
static <K,V> INode<K,V> newRootNode() {
Gen gen = new Gen ();
CNode<K, V> cn = new CNode<> (0, new BasicNode[] {}, gen);
static <K,V> INode<K,V> newRootNode() {
Gen gen = new Gen ();
CNode<K, V> cn = new CNode<> (0, new BasicNode[] {}, gen);
- return new INode<>(cn, gen);
- }
-
- private INode(final MainNode<K, V> bn, final Gen g) {
- super(g);
- WRITE(bn);
- }
-
- INode(final Gen g) {
- this(null, g);
- }
-
- void WRITE(final MainNode<K, V> nval) {
- INodeBase.updater.set(this, nval);
+ return new INode<>(gen, cn);
- boolean CAS(final MainNode<K, V> old, final MainNode<K, V> n) {
- return INodeBase.updater.compareAndSet(this, old, n);
+ INode(final Gen gen, final MainNode<K, V> bn) {
+ super(gen, bn);
}
MainNode<K, V> gcasRead(final TrieMap<K, V> ct) {
}
MainNode<K, V> gcasRead(final TrieMap<K, V> ct) {
}
MainNode<K, V> GCAS_READ(final TrieMap<K, V> ct) {
}
MainNode<K, V> GCAS_READ(final TrieMap<K, V> ct) {
- MainNode<K, V> m = /* READ */mainnode;
+ MainNode<K, V> m = /* READ */ READ();
MainNode<K, V> prevval = /* READ */ m.READ_PREV();
if (prevval == null) {
return m;
MainNode<K, V> prevval = /* READ */ m.READ_PREV();
if (prevval == null) {
return m;
} else {
// Tailrec
// return GCAS_Complete (/* READ */mainnode, ct);
} else {
// Tailrec
// return GCAS_Complete (/* READ */mainnode, ct);
- m = /* READ */mainnode;
continue;
}
} else if (prev instanceof MainNode) {
continue;
}
} else if (prev instanceof MainNode) {
} else {
// try to abort
m.CAS_PREV(prev, new FailedNode<>(prev));
} else {
// try to abort
m.CAS_PREV(prev, new FailedNode<>(prev));
- return GCAS_Complete(/* READ */mainnode, ct);
+ return GCAS_Complete(/* READ */ READ(), ct);
}
private INode<K, V> inode(final MainNode<K, V> cn) {
}
private INode<K, V> inode(final MainNode<K, V> cn) {
- INode<K, V> nin = new INode<>(gen);
- nin.WRITE(cn);
- return nin;
+ return new INode<>(gen, cn);
}
INode<K, V> copyToGen(final Gen ngen, final TrieMap<K, V> ct) {
}
INode<K, V> copyToGen(final Gen ngen, final TrieMap<K, V> ct) {
- INode<K, V> nin = new INode<>(ngen);
- MainNode<K, V> main = GCAS_READ(ct);
- nin.WRITE(main);
- return nin;
+ return new INode<>(ngen, GCAS_READ(ct));
// Tailrec
continue;
} else {
// Tailrec
continue;
} else {
- return RESTART; // used to be throw
- // RestartException
+ return RESTART; // used to be throw RestartException
}
}
} else if (sub instanceof SNode) {
}
}
} else if (sub instanceof SNode) {
abstract class INodeBase<K, V> extends BasicNode {
abstract class INodeBase<K, V> extends BasicNode {
- public static final AtomicReferenceFieldUpdater<INodeBase, MainNode> updater = AtomicReferenceFieldUpdater.newUpdater(INodeBase.class, MainNode.class, "mainnode");
-
- public static final Object RESTART = new Object();
-
- public volatile MainNode<K, V> mainnode = null;
+ @SuppressWarnings("rawtypes")
+ private static final AtomicReferenceFieldUpdater<INodeBase, MainNode> MAINNODE_UPDATER =
+ AtomicReferenceFieldUpdater.newUpdater(INodeBase.class, MainNode.class, "mainnode");
- public INodeBase(final Gen generation) {
- gen = generation;
+ private volatile MainNode<K, V> mainnode;
+
+ INodeBase(final Gen generation, final MainNode<K, V> mainnode) {
+ gen = generation;
+ this.mainnode = mainnode;
- public BasicNode prev() {
- return null;
+ final boolean CAS(final MainNode<K, V> old, final MainNode<K, V> n) {
+ return MAINNODE_UPDATER.compareAndSet(this, old, n);
-}
\ No newline at end of file
+ final MainNode<K, V> READ() {
+ return mainnode;
+ }
+}
- private Object lookuphc (final K k, final int hc) {
+ private Object lookuphc(final K k, final int hc) {
- INode<K, V> r = RDCSS_READ_ROOT ();
- Object res = r.rec_lookup (k, hc, 0, null, r.gen, this);
- if (res == INodeBase.RESTART) {
- // return lookuphc (k, hc);
- // tailrec
- continue;
- } else {
+ final INode<K, V> r = RDCSS_READ_ROOT ();
+ final Object res = r.rec_lookup(k, hc, 0, null, r.gen, this);
+ if (!INode.RESTART.equals(res)) {
+
+ // Tail recursion: lookuphc(k, hc)