2104 |
|
} |
2105 |
|
|
2106 |
|
Node<K,V> find(int h, Object k) { |
2107 |
< |
Node<K,V> e; int n; |
2108 |
< |
Node<K,V>[] tab = nextTable; |
2109 |
< |
if (k != null && tab != null && (n = tab.length) > 0 && |
2110 |
< |
(e = tabAt(tab, (n - 1) & h)) != null) { |
2111 |
< |
do { |
2107 |
> |
// loop to avoid arbitrarily deep recursion on forwarding nodes |
2108 |
> |
outer: for (Node<K,V>[] tab = nextTable;;) { |
2109 |
> |
Node<K,V> e; int n; |
2110 |
> |
if (k == null || tab == null || (n = tab.length) == 0 || |
2111 |
> |
(e = tabAt(tab, (n - 1) & h)) == null) |
2112 |
> |
return null; |
2113 |
> |
for (;;) { |
2114 |
|
int eh; K ek; |
2115 |
|
if ((eh = e.hash) == h && |
2116 |
|
((ek = e.key) == k || (ek != null && k.equals(ek)))) |
2117 |
|
return e; |
2118 |
< |
if (eh < 0) |
2119 |
< |
return e.find(h, k); |
2120 |
< |
} while ((e = e.next) != null); |
2118 |
> |
if (eh < 0) { |
2119 |
> |
if (e instanceof ForwardingNode) { |
2120 |
> |
tab = ((ForwardingNode<K,V>)e).nextTable; |
2121 |
> |
continue outer; |
2122 |
> |
} |
2123 |
> |
else |
2124 |
> |
return e.find(h, k); |
2125 |
> |
} |
2126 |
> |
if ((e = e.next) == null) |
2127 |
> |
return null; |
2128 |
> |
} |
2129 |
|
} |
2120 |
– |
return null; |
2130 |
|
} |
2131 |
|
} |
2132 |
|
|
2299 |
|
int nextn = nextTab.length; |
2300 |
|
ForwardingNode<K,V> fwd = new ForwardingNode<K,V>(nextTab); |
2301 |
|
boolean advance = true; |
2302 |
+ |
boolean finishing = false; // to ensure sweep before committing nextTab |
2303 |
|
for (int i = 0, bound = 0;;) { |
2304 |
|
int nextIndex, nextBound, fh; Node<K,V> f; |
2305 |
|
while (advance) { |
2306 |
< |
if (--i >= bound) |
2306 |
> |
if (--i >= bound || finishing) |
2307 |
|
advance = false; |
2308 |
|
else if ((nextIndex = transferIndex) <= transferOrigin) { |
2309 |
|
i = -1; |
2319 |
|
} |
2320 |
|
} |
2321 |
|
if (i < 0 || i >= n || i + n >= nextn) { |
2322 |
+ |
if (finishing) { |
2323 |
+ |
nextTable = null; |
2324 |
+ |
table = nextTab; |
2325 |
+ |
sizeCtl = (n << 1) - (n >>> 1); |
2326 |
+ |
return; |
2327 |
+ |
} |
2328 |
|
for (int sc;;) { |
2329 |
|
if (U.compareAndSwapInt(this, SIZECTL, sc = sizeCtl, ++sc)) { |
2330 |
< |
if (sc == -1) { |
2331 |
< |
nextTable = null; |
2332 |
< |
table = nextTab; |
2333 |
< |
sizeCtl = (n << 1) - (n >>> 1); |
2334 |
< |
} |
2319 |
< |
return; |
2330 |
> |
if (sc != -1) |
2331 |
> |
return; |
2332 |
> |
finishing = advance = true; |
2333 |
> |
i = n; // recheck before commit |
2334 |
> |
break; |
2335 |
|
} |
2336 |
|
} |
2337 |
|
} |