Node ceilingNode(double key) { for (; ; ) { Node b = skipListMap.findGrandPredecessor(key, refCntCallback); if (b == null) b = head; if (b != head && key <= b.last()) { return b; } assert b == head || b.last() < key; Node n = safeNext(b); release(b); if (n == null) { return null; } else if (key <= n.last()) { return n; } Node f = safeNext(n); release(n); if (f == null) { return null; } else { if (isInconsistentNextNode(f, key)) { release(f); continue; } return f; } } }
V putAtomic(double key, V value, boolean onlyIfAbsent) { if (value == null) throw new NullPointerException(); for (; ; ) { Node b = skipListMap.findGrandPredecessor(key, refCntCallback); if (b == null) b = head; if (b != head && b.first() <= key && key <= b.last()) { release(b); continue; } assert b == head || b.last() < key; Node n = safeNext(b); if (n == null) { if (b.appendNewAtomic(key, value, this)) { release(b); return null; } else { release(b); continue; } } else if (n.first() <= key && key <= n.last()) { Object val = n.putAtomic(key, value, b, onlyIfAbsent, this); release(b, n); if (val == Retry) continue; return (V) val; } Node f = safeNext(n); if (f == null) { Object val = n.putAtomic(key, value, b, onlyIfAbsent, this); release(b, n); if (val == Retry) continue; return (V) val; } else { if (f.first() == key) { Object val = f.putAtomic(key, value, n, onlyIfAbsent, this); release(b, n, f); if (val == Retry) continue; return (V) val; } else { if (key > f.first()) { // inconsistent read, retry release(b, n, f); continue; } Object val = n.putAtomic(key, value, b, onlyIfAbsent, this); release(b, n, f); if (val == Retry) continue; return (V) val; } } } }
int findEndIndex(Node n, double key, boolean inclusive) { boolean exclusive = !inclusive; if (key < n.first()) return -1; if (key >= n.last()) { if (key == n.last() && exclusive) return n.len() - 2; return n.len() - 1; } int pos = n.findKeyIndex(key); if (pos < 0) pos = -(pos + 1); else if (!inclusive) pos--; if (pos == n.len()) pos--; return pos; }
V doReplace(double key, V old, V value) { for (; ; ) { Node b = skipListMap.findGrandPredecessor(key, refCntCallback); if (b == null) b = head; if (b != head && b.first() <= key && key <= b.last()) { // can happen if there's inconsistency between skipListMap and orderedMap(this). // The inconsistency can happen from Node.putAtomicReally(), // where it adds to, and removes from skiplistMap. Object val = b.replace(key, old, value); release(b); if (val == Retry) continue; return (V) val; } assert b == head || b.last() < key; Node n = safeNext(b); release(b); if (n == null) { return null; } else if (n.first() <= key && key <= n.last()) { Object val = n.replace(key, old, value); release(n); if (val == Retry) continue; return (V) val; } Node f = safeNext(n); release(n); if (f == null) { return null; } else { if (isInconsistentNextNode(f, key)) { release(f); continue; } Object val = f.replace(key, old, value); release(f); if (val == Retry) continue; return (V) val; } } }