We have a couple of while(true) loops, which can we written
concisely using a 'do { ... } while (retry);' pattern.
Also check if the from-serialization codepath does not encounter
a does not observe a concurrent modification.
Change-Id: I7970a3d11fcd6715fb86a3c669d4eb195d10fa26
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
final class INode<K, V> extends BasicNode {
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
final class INode<K, V> extends BasicNode {
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 ();
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
+import com.google.common.base.Verify;
import com.google.common.collect.Iterators;
import java.io.ObjectStreamException;
import java.io.Serializable;
import com.google.common.collect.Iterators;
import java.io.ObjectStreamException;
import java.io.Serializable;
}
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) {
- final INode<K, V> r = RDCSS_READ_ROOT();
- if (r.rec_insert(k, v, hc, 0, null, this)) {
- // Successful, we are done
- return;
- }
-
- // Tail recursion: inserthc(k, hc, v);
- }
+ // 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 INode<K, V> r = RDCSS_READ_ROOT();
+ final boolean success = r.rec_insert(k, v, 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 k, final int hc, final V v, final Object cond) {
- while (true) {
- final INode<K, V> r = RDCSS_READ_ROOT();
- final Optional<V> ret = r.rec_insertif(k, v, hc, cond, 0, null, this);
- if (ret != null) {
- return ret;
- }
+ 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);
+ } while (res == null);
- // Tail recursion: return insertifhc(k, hc, v, cond);
- }
- private Object lookuphc(final K k, final int hc) {
- while (true) {
- final INode<K, V> r = RDCSS_READ_ROOT();
- final Object res = r.rec_lookup(k, hc, 0, null, this);
- if (!INode.RESTART.equals(res)) {
- return res;
- }
+ private V lookuphc(final K k, final int hc) {
+ Object res;
+ do {
+ // Keep looping as long as RESTART is being indicated
+ res = RDCSS_READ_ROOT().rec_lookup(k, hc, 0, null, this);
+ } while (INode.RESTART.equals(res));
- // Tail recursion: lookuphc(k, hc)
- }
}
private Optional<V> removehc(final K k, final V v, final int hc) {
}
private Optional<V> removehc(final K k, final V v, final int hc) {
- while (true) {
- final INode<K, V> r = RDCSS_READ_ROOT();
- final Optional<V> res = r.rec_remove(k, v, hc, 0, null, this);
- if (res != null) {
- return res;
- }
+ Optional<V> res;
+ do {
+ // Keep looping as long as we do not get a reply
+ res = RDCSS_READ_ROOT().rec_remove(k, v, hc, 0, null, this);
+ } while (res == null);
- // Tail recursion: return removehc(k, v, hc);
- }
@Override
public void clear() {
@Override
public void clear() {
+ boolean success;
+ do {
final INode<K, V> r = RDCSS_READ_ROOT();
final INode<K, V> r = RDCSS_READ_ROOT();
- if (RDCSS_ROOT(r, r.gcasRead(this), newRootNode())) {
- return;
- }
- }
+ success = RDCSS_ROOT(r, r.gcasRead(this), newRootNode());
+ } while (!success);
}
int computeHash(final K k) {
}
int computeHash(final K k) {
@Override
public V get(final Object key) {
final K k = (K) checkNotNull(key);
@Override
public V get(final Object key) {
final K k = (K) checkNotNull(key);
- return (V) lookuphc(k, computeHash(k));
+ return lookuphc(k, computeHash(k));