Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use compareAndExchange() in obvious places #179

Merged
merged 5 commits into from
Jan 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 9 additions & 7 deletions triemap/src/main/java/tech/pantheon/triemap/INode.java
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,15 @@ private MainNode<K, V> gcasComplete(final MainNode<K, V> oldmain, final TrieMap<

if (prev instanceof FailedNode) {
// try to commit to previous value
FailedNode<K, V> fn = (FailedNode<K, V>) prev;
if (MAINNODE.compareAndSet(this, main, fn.readPrev())) {
final var fn = (FailedNode<K, V>) prev;
final var witness = (MainNode<K, V>) MAINNODE.compareAndExchange(this, main, fn.readPrev());
if (witness == main) {
// TODO: second read of FailedNode.prev. Can a FailedNode move?
return fn.readPrev();
}

// Tail recursion: return GCAS_Complete(/* READ */ mainnode, ct);
main = /* READ */ mainnode;
// Tail recursion: return GCAS_Complete(witness, ct);
main = witness;
continue;
}

Expand Down Expand Up @@ -139,7 +141,7 @@ private boolean recInsert(final K key, final V val, final int hc, final int lev,

if (m instanceof CNode) {
// 1) a multiway node
final CNode<K, V> cn = (CNode<K, V>) m;
final var cn = (CNode<K, V>) m;
final int idx = hc >>> lev & 0x1f;
final int flag = 1 << idx;
final int bmp = cn.bitmap;
Expand Down Expand Up @@ -226,7 +228,7 @@ static VerifyException invalidElement(final BasicNode elem) {

if (m instanceof CNode) {
// 1) a multiway node
final CNode<K, V> cn = (CNode<K, V>) m;
final var cn = (CNode<K, V>) m;
final int idx = hc >>> lev & 0x1f;
final int flag = 1 << idx;
final int bmp = cn.bitmap;
Expand All @@ -235,7 +237,7 @@ static VerifyException invalidElement(final BasicNode elem) {

if ((bmp & flag) != 0) {
// 1a) insert below
final BasicNode cnAtPos = cn.array[pos];
final var cnAtPos = cn.array[pos];
if (cnAtPos instanceof INode) {
@SuppressWarnings("unchecked")
final var in = (INode<K, V>) cnAtPos;
Expand Down
59 changes: 25 additions & 34 deletions triemap/src/main/java/tech/pantheon/triemap/MutableTrieMap.java
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ INode<K, V> rdcssReadRoot(final boolean abort) {
return (INode<K, V>) r;
}
if (r instanceof RDCSS_Descriptor) {
return rdcssComplete(abort);
return rdcssComplete((RDCSS_Descriptor<K, V>) r, abort);
}
throw new VerifyException("Unhandled root " + r);
}
Expand Down Expand Up @@ -203,61 +203,52 @@ private void inserthc(final K key, final int hc, final V value) {
return res;
}

private boolean casRoot(final Root ov, final Root nv) {
return ROOT.compareAndSet(this, ov, nv);
private Root casRoot(final Root ov, final Root nv) {
return (Root) ROOT.compareAndExchange(this, ov, nv);
}

private boolean rdcssRoot(final INode<K, V> ov, final MainNode<K, V> expectedmain, final INode<K, V> nv) {
final var desc = new RDCSS_Descriptor<>(ov, expectedmain, nv);
if (casRoot(ov, desc)) {
rdcssComplete(false);
return /* READ */desc.committed;
final var witness = casRoot(ov, desc);
if (witness == ov) {
rdcssComplete(desc, false);
return /* READ */ desc.committed;
}

return false;
}

@SuppressWarnings("unchecked")
private INode<K, V> rdcssComplete(final boolean abort) {
private INode<K, V> rdcssComplete(final RDCSS_Descriptor<K, V> initial, final boolean abort) {
var desc = initial;

while (true) {
final var r = /* READ */ root;
if (r instanceof INode) {
return (INode<K, V>) r;
}
if (!(r instanceof RDCSS_Descriptor)) {
throw new VerifyException("Unhandled root " + r);
}
final Root next;

final var desc = (RDCSS_Descriptor<K, V>) r;
final var ov = desc.old;
final var exp = desc.expectedmain;
final var nv = desc.nv;

if (abort) {
if (casRoot(desc, ov)) {
if (abort || ov.gcasRead(this) != desc.expectedmain) {
next = casRoot(desc, ov);
if (next == desc) {
return ov;
}

// Tail recursion: return RDCSS_Complete(abort);
continue;
}

final var oldmain = ov.gcasRead(this);
if (oldmain == exp) {
if (casRoot(desc, nv)) {
} else {
final var nv = desc.nv;
next = casRoot(desc, nv);
if (next == desc) {
desc.committed = true;
return nv;
}

// Tail recursion: return RDCSS_Complete(abort);
continue;
}

if (casRoot(desc, ov)) {
return ov;
if (next instanceof INode) {
return (INode<K, V>) next;
}
if (!(next instanceof RDCSS_Descriptor)) {
throw new VerifyException("Unhandled root " + next);
}

// Tail recursion: return RDCSS_Complete(abort);
// Tail recursion: return rdcssComplete(next, abort);
desc = (RDCSS_Descriptor<K, V>) next;
}
}

Expand Down
Loading