--- jsr166/src/jsr166e/ConcurrentHashMapV8.java 2013/07/03 18:16:31 1.109 +++ jsr166/src/jsr166e/ConcurrentHashMapV8.java 2013/07/04 18:34:49 1.110 @@ -2141,20 +2141,29 @@ public class ConcurrentHashMapV8 } Node find(int h, Object k) { - Node e; int n; - Node[] tab = nextTable; - if (k != null && tab != null && (n = tab.length) > 0 && - (e = tabAt(tab, (n - 1) & h)) != null) { - do { + // loop to avoid arbitrarily deep recursion on forwarding nodes + outer: for (Node[] tab = nextTable;;) { + Node e; int n; + if (k == null || tab == null || (n = tab.length) == 0 || + (e = tabAt(tab, (n - 1) & h)) == null) + return null; + for (;;) { int eh; K ek; if ((eh = e.hash) == h && ((ek = e.key) == k || (ek != null && k.equals(ek)))) return e; - if (eh < 0) - return e.find(h, k); - } while ((e = e.next) != null); + if (eh < 0) { + if (e instanceof ForwardingNode) { + tab = ((ForwardingNode)e).nextTable; + continue outer; + } + else + return e.find(h, k); + } + if ((e = e.next) == null) + return null; + } } - return null; } } @@ -2328,10 +2337,11 @@ public class ConcurrentHashMapV8 int nextn = nextTab.length; ForwardingNode fwd = new ForwardingNode(nextTab); boolean advance = true; + boolean finishing = false; // to ensure sweep before committing nextTab for (int i = 0, bound = 0;;) { int nextIndex, nextBound, fh; Node f; while (advance) { - if (--i >= bound) + if (--i >= bound || finishing) advance = false; else if ((nextIndex = transferIndex) <= transferOrigin) { i = -1; @@ -2347,14 +2357,19 @@ public class ConcurrentHashMapV8 } } if (i < 0 || i >= n || i + n >= nextn) { + if (finishing) { + nextTable = null; + table = nextTab; + sizeCtl = (n << 1) - (n >>> 1); + return; + } for (int sc;;) { if (U.compareAndSwapInt(this, SIZECTL, sc = sizeCtl, ++sc)) { - if (sc == -1) { - nextTable = null; - table = nextTab; - sizeCtl = (n << 1) - (n >>> 1); - } - return; + if (sc != -1) + return; + finishing = advance = true; + i = n; // recheck before commit + break; } } }