ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/ConcurrentHashMap.java
(Generate patch)

Comparing jsr166/src/main/java/util/concurrent/ConcurrentHashMap.java (file contents):
Revision 1.245 by jsr166, Fri Aug 23 20:12:21 2013 UTC vs.
Revision 1.252 by dl, Sun Dec 1 13:38:58 2013 UTC

# Line 344 | Line 344 | public class ConcurrentHashMap<K,V> exte
344       * The table is resized when occupancy exceeds a percentage
345       * threshold (nominally, 0.75, but see below).  Any thread
346       * noticing an overfull bin may assist in resizing after the
347 <     * initiating thread allocates and sets up the replacement
348 <     * array. However, rather than stalling, these other threads may
349 <     * proceed with insertions etc.  The use of TreeBins shields us
350 <     * from the worst case effects of overfilling while resizes are in
347 >     * initiating thread allocates and sets up the replacement array.
348 >     * However, rather than stalling, these other threads may proceed
349 >     * with insertions etc.  The use of TreeBins shields us from the
350 >     * worst case effects of overfilling while resizes are in
351       * progress.  Resizing proceeds by transferring bins, one by one,
352 <     * from the table to the next table. To enable concurrency, the
353 <     * next table must be (incrementally) prefilled with place-holders
354 <     * serving as reverse forwarders to the old table.  Because we are
352 >     * from the table to the next table. However, threads claim small
353 >     * blocks of indices to transfer (via field transferIndex) before
354 >     * doing so, reducing contention.  A generation stamp in field
355 >     * sizeCtl ensures that resizings do not overlap. Because we are
356       * using power-of-two expansion, the elements from each bin must
357       * either stay at same index, or move with a power of two
358       * offset. We eliminate unnecessary node creation by catching
# Line 372 | Line 373 | public class ConcurrentHashMap<K,V> exte
373       * locks, average aggregate waits become shorter as resizing
374       * progresses.  The transfer operation must also ensure that all
375       * accessible bins in both the old and new table are usable by any
376 <     * traversal.  This is arranged by proceeding from the last bin
377 <     * (table.length - 1) up towards the first.  Upon seeing a
378 <     * forwarding node, traversals (see class Traverser) arrange to
379 <     * move to the new table without revisiting nodes.  However, to
380 <     * ensure that no intervening nodes are skipped, bin splitting can
381 <     * only begin after the associated reverse-forwarders are in
382 <     * place.
376 >     * traversal.  This is arranged in part by proceeding from the
377 >     * last bin (table.length - 1) up towards the first.  Upon seeing
378 >     * a forwarding node, traversals (see class Traverser) arrange to
379 >     * move to the new table without revisiting nodes.  To ensure that
380 >     * no intervening nodes are skipped even when moved out of order,
381 >     * a stack (see class TableStack) is created on first encounter of
382 >     * a forwarding node during a traversal, to maintain its place if
383 >     * later processing the current table. The need for these
384 >     * save/restore mechanics is relatively rare, but when one
385 >     * forwarding node is encountered, typically many more will be.
386 >     * So Traversers use a simple caching scheme to avoid creating so
387 >     * many new TableStack nodes. (Thanks to Peter Levart for
388 >     * suggesting use of a stack here.)
389       *
390       * The traversal scheme also applies to partial traversals of
391       * ranges of bins (via an alternate Traverser constructor)
# Line 535 | Line 542 | public class ConcurrentHashMap<K,V> exte
542       */
543      private static final int MIN_TRANSFER_STRIDE = 16;
544  
545 +    /**
546 +     * The number of bits used for generation stamp in sizeCtl.
547 +     * Must be at least 6 for 32bit arrays.
548 +     */
549 +    private static int RESIZE_STAMP_BITS = 16;
550 +
551 +    /**
552 +     * The maximum number of threads that can help resize.
553 +     * Must fit in 32 - RESIZE_STAMP_BITS bits.
554 +     */
555 +    private static final int MAX_RESIZERS = (1 << (32 - RESIZE_STAMP_BITS)) - 1;
556 +
557 +    /**
558 +     * The bit shift for recording size stamp in sizeCtl.
559 +     */
560 +    private static final int RESIZE_STAMP_SHIFT = 32 - RESIZE_STAMP_BITS;
561 +
562      /*
563       * Encodings for Node hash fields. See above for explanation.
564       */
# Line 692 | Line 716 | public class ConcurrentHashMap<K,V> exte
716       * errors by users, these checks must operate on local variables,
717       * which accounts for some odd-looking inline assignments below.
718       * Note that calls to setTabAt always occur within locked regions,
719 <     * and so in principle require only release ordering, not need
719 >     * and so in principle require only release ordering, not
720       * full volatile semantics, but are currently coded as volatile
721       * writes to be conservative.
722       */
# Line 747 | Line 771 | public class ConcurrentHashMap<K,V> exte
771      private transient volatile int transferIndex;
772  
773      /**
750     * The least available table index to split while resizing.
751     */
752    private transient volatile int transferOrigin;
753
754    /**
774       * Spinlock (locked via CAS) used when resizing and/or creating CounterCells.
775       */
776      private transient volatile int cellsBusy;
# Line 1347 | Line 1366 | public class ConcurrentHashMap<K,V> exte
1366          }
1367          int segmentShift = 32 - sshift;
1368          int segmentMask = ssize - 1;
1369 <        @SuppressWarnings("unchecked") Segment<K,V>[] segments = (Segment<K,V>[])
1369 >        @SuppressWarnings("unchecked")
1370 >        Segment<K,V>[] segments = (Segment<K,V>[])
1371              new Segment<?,?>[DEFAULT_CONCURRENCY_LEVEL];
1372          for (int i = 0; i < segments.length; ++i)
1373              segments[i] = new Segment<K,V>(LOAD_FACTOR);
# Line 1390 | Line 1410 | public class ConcurrentHashMap<K,V> exte
1410          long size = 0L;
1411          Node<K,V> p = null;
1412          for (;;) {
1413 <            @SuppressWarnings("unchecked") K k = (K) s.readObject();
1414 <            @SuppressWarnings("unchecked") V v = (V) s.readObject();
1413 >            @SuppressWarnings("unchecked")
1414 >            K k = (K) s.readObject();
1415 >            @SuppressWarnings("unchecked")
1416 >            V v = (V) s.readObject();
1417              if (k != null && v != null) {
1418                  p = new Node<K,V>(spread(k.hashCode()), k, v, p);
1419                  ++size;
# Line 1410 | Line 1432 | public class ConcurrentHashMap<K,V> exte
1432                  n = tableSizeFor(sz + (sz >>> 1) + 1);
1433              }
1434              @SuppressWarnings("unchecked")
1435 <                Node<K,V>[] tab = (Node<K,V>[])new Node<?,?>[n];
1435 >            Node<K,V>[] tab = (Node<K,V>[])new Node<?,?>[n];
1436              int mask = n - 1;
1437              long added = 0L;
1438              while (p != null) {
# Line 1999 | Line 2021 | public class ConcurrentHashMap<K,V> exte
2021  
2022      /**
2023       * Legacy method testing if some key maps into the specified value
2024 <     * in this table.  This method is identical in functionality to
2024 >     * in this table.
2025 >     *
2026 >     * @deprecated This method is identical in functionality to
2027       * {@link #containsValue(Object)}, and exists solely to ensure
2028       * full compatibility with class {@link java.util.Hashtable},
2029       * which supported this method prior to introduction of the
# Line 2012 | Line 2036 | public class ConcurrentHashMap<K,V> exte
2036       *         {@code false} otherwise
2037       * @throws NullPointerException if the specified value is null
2038       */
2039 <    @Deprecated public boolean contains(Object value) {
2039 >    @Deprecated
2040 >    public boolean contains(Object value) {
2041          return containsValue(value);
2042      }
2043  
# Line 2159 | Line 2184 | public class ConcurrentHashMap<K,V> exte
2184      /* ---------------- Table Initialization and Resizing -------------- */
2185  
2186      /**
2187 +     * Returns the stamp bits for resizing a table of size n.
2188 +     * Must be negative when shifted left by RESIZE_STAMP_SHIFT.
2189 +     */
2190 +    static final int resizeStamp(int n) {
2191 +        return Integer.numberOfLeadingZeros(n) | (1 << (RESIZE_STAMP_BITS - 1));
2192 +    }
2193 +
2194 +    /**
2195       * Initializes table, using the size recorded in sizeCtl.
2196       */
2197      private final Node<K,V>[] initTable() {
# Line 2171 | Line 2204 | public class ConcurrentHashMap<K,V> exte
2204                      if ((tab = table) == null || tab.length == 0) {
2205                          int n = (sc > 0) ? sc : DEFAULT_CAPACITY;
2206                          @SuppressWarnings("unchecked")
2207 <                            Node<K,V>[] nt = (Node<K,V>[])new Node<?,?>[n];
2207 >                        Node<K,V>[] nt = (Node<K,V>[])new Node<?,?>[n];
2208                          table = tab = nt;
2209                          sc = n - (n >>> 2);
2210                      }
# Line 2212 | Line 2245 | public class ConcurrentHashMap<K,V> exte
2245              s = sumCount();
2246          }
2247          if (check >= 0) {
2248 <            Node<K,V>[] tab, nt; int sc;
2248 >            Node<K,V>[] tab, nt; int n, sc;
2249              while (s >= (long)(sc = sizeCtl) && (tab = table) != null &&
2250 <                   tab.length < MAXIMUM_CAPACITY) {
2250 >                   (n = tab.length) < MAXIMUM_CAPACITY) {
2251 >                int rs = resizeStamp(n);
2252                  if (sc < 0) {
2253 <                    if (sc == -1 || transferIndex <= transferOrigin ||
2254 <                        (nt = nextTable) == null)
2253 >                    if ((sc >>> RESIZE_STAMP_SHIFT) != rs || sc == rs + 1 ||
2254 >                        sc == rs + MAX_RESIZERS || (nt = nextTable) == null ||
2255 >                        transferIndex <= 0)
2256                          break;
2257 <                    if (U.compareAndSwapInt(this, SIZECTL, sc, sc - 1))
2257 >                    if (U.compareAndSwapInt(this, SIZECTL, sc, sc + 1))
2258                          transfer(tab, nt);
2259                  }
2260 <                else if (U.compareAndSwapInt(this, SIZECTL, sc, -2))
2260 >                else if (U.compareAndSwapInt(this, SIZECTL, sc,
2261 >                                             (rs << RESIZE_STAMP_SHIFT) + 2))
2262                      transfer(tab, null);
2263                  s = sumCount();
2264              }
# Line 2234 | Line 2270 | public class ConcurrentHashMap<K,V> exte
2270       */
2271      final Node<K,V>[] helpTransfer(Node<K,V>[] tab, Node<K,V> f) {
2272          Node<K,V>[] nextTab; int sc;
2273 <        if ((f instanceof ForwardingNode) &&
2273 >        if (tab != null && (f instanceof ForwardingNode) &&
2274              (nextTab = ((ForwardingNode<K,V>)f).nextTable) != null) {
2275 <            if (nextTab == nextTable && tab == table &&
2276 <                transferIndex > transferOrigin && (sc = sizeCtl) < -1 &&
2277 <                U.compareAndSwapInt(this, SIZECTL, sc, sc - 1))
2278 <                transfer(tab, nextTab);
2275 >            int rs = resizeStamp(tab.length);
2276 >            while (nextTab == nextTable && table == tab &&
2277 >                   (sc = sizeCtl) < 0) {
2278 >                if ((sc >>> RESIZE_STAMP_SHIFT) != rs || sc == rs + 1 ||
2279 >                    sc == rs + MAX_RESIZERS || transferIndex <= 0)
2280 >                    break;
2281 >                if (U.compareAndSwapInt(this, SIZECTL, sc, sc + 1)) {
2282 >                    transfer(tab, nextTab);
2283 >                    break;
2284 >                }
2285 >            }
2286              return nextTab;
2287          }
2288          return table;
# Line 2262 | Line 2305 | public class ConcurrentHashMap<K,V> exte
2305                      try {
2306                          if (table == tab) {
2307                              @SuppressWarnings("unchecked")
2308 <                                Node<K,V>[] nt = (Node<K,V>[])new Node<?,?>[n];
2308 >                            Node<K,V>[] nt = (Node<K,V>[])new Node<?,?>[n];
2309                              table = nt;
2310                              sc = n - (n >>> 2);
2311                          }
# Line 2273 | Line 2316 | public class ConcurrentHashMap<K,V> exte
2316              }
2317              else if (c <= sc || n >= MAXIMUM_CAPACITY)
2318                  break;
2319 <            else if (tab == table &&
2320 <                     U.compareAndSwapInt(this, SIZECTL, sc, -2))
2321 <                transfer(tab, null);
2319 >            else if (tab == table) {
2320 >                int rs = resizeStamp(n);
2321 >                if (sc < 0) {
2322 >                    Node<K,V>[] nt;
2323 >                    if ((sc >>> RESIZE_STAMP_SHIFT) != rs || sc == rs + 1 ||
2324 >                        sc == rs + MAX_RESIZERS || (nt = nextTable) == null ||
2325 >                        transferIndex <= 0)
2326 >                        break;
2327 >                    if (U.compareAndSwapInt(this, SIZECTL, sc, sc + 1))
2328 >                        transfer(tab, nt);
2329 >                }
2330 >                else if (U.compareAndSwapInt(this, SIZECTL, sc,
2331 >                                             (rs << RESIZE_STAMP_SHIFT) + 2))
2332 >                    transfer(tab, null);
2333 >            }
2334          }
2335      }
2336  
# Line 2290 | Line 2345 | public class ConcurrentHashMap<K,V> exte
2345          if (nextTab == null) {            // initiating
2346              try {
2347                  @SuppressWarnings("unchecked")
2348 <                    Node<K,V>[] nt = (Node<K,V>[])new Node<?,?>[n << 1];
2348 >                Node<K,V>[] nt = (Node<K,V>[])new Node<?,?>[n << 1];
2349                  nextTab = nt;
2350              } catch (Throwable ex) {      // try to cope with OOME
2351                  sizeCtl = Integer.MAX_VALUE;
2352                  return;
2353              }
2354              nextTable = nextTab;
2300            transferOrigin = n;
2355              transferIndex = n;
2302            ForwardingNode<K,V> rev = new ForwardingNode<K,V>(tab);
2303            for (int k = n; k > 0;) {    // progressively reveal ready slots
2304                int nextk = (k > stride) ? k - stride : 0;
2305                for (int m = nextk; m < k; ++m)
2306                    nextTab[m] = rev;
2307                for (int m = n + nextk; m < n + k; ++m)
2308                    nextTab[m] = rev;
2309                U.putOrderedInt(this, TRANSFERORIGIN, k = nextk);
2310            }
2356          }
2357          int nextn = nextTab.length;
2358          ForwardingNode<K,V> fwd = new ForwardingNode<K,V>(nextTab);
2359          boolean advance = true;
2360          boolean finishing = false; // to ensure sweep before committing nextTab
2361          for (int i = 0, bound = 0;;) {
2362 <            int nextIndex, nextBound, fh; Node<K,V> f;
2362 >            Node<K,V> f; int fh;
2363              while (advance) {
2364 +                int nextIndex, nextBound;
2365                  if (--i >= bound || finishing)
2366                      advance = false;
2367 <                else if ((nextIndex = transferIndex) <= transferOrigin) {
2367 >                else if ((nextIndex = transferIndex) <= 0) {
2368                      i = -1;
2369                      advance = false;
2370                  }
# Line 2332 | Line 2378 | public class ConcurrentHashMap<K,V> exte
2378                  }
2379              }
2380              if (i < 0 || i >= n || i + n >= nextn) {
2381 +                int sc;
2382                  if (finishing) {
2383                      nextTable = null;
2384                      table = nextTab;
2385                      sizeCtl = (n << 1) - (n >>> 1);
2386                      return;
2387                  }
2388 <                for (int sc;;) {
2389 <                    if (U.compareAndSwapInt(this, SIZECTL, sc = sizeCtl, ++sc)) {
2390 <                        if (sc != -1)
2391 <                            return;
2392 <                        finishing = advance = true;
2346 <                        i = n; // recheck before commit
2347 <                        break;
2348 <                    }
2349 <                }
2350 <            }
2351 <            else if ((f = tabAt(tab, i)) == null) {
2352 <                if (casTabAt(tab, i, null, fwd)) {
2353 <                    setTabAt(nextTab, i, null);
2354 <                    setTabAt(nextTab, i + n, null);
2355 <                    advance = true;
2388 >                if (U.compareAndSwapInt(this, SIZECTL, sc = sizeCtl, sc - 1)) {
2389 >                    if ((sc - 2) != resizeStamp(n))
2390 >                        return;
2391 >                    finishing = advance = true;
2392 >                    i = n; // recheck before commit
2393                  }
2394              }
2395 +            else if ((f = tabAt(tab, i)) == null)
2396 +                advance = casTabAt(tab, i, null, fwd);
2397              else if ((fh = f.hash) == MOVED)
2398                  advance = true; // already processed
2399              else {
# Line 2546 | Line 2585 | public class ConcurrentHashMap<K,V> exte
2585      private final void treeifyBin(Node<K,V>[] tab, int index) {
2586          Node<K,V> b; int n, sc;
2587          if (tab != null) {
2588 <            if ((n = tab.length) < MIN_TREEIFY_CAPACITY) {
2589 <                if (tab == table && (sc = sizeCtl) >= 0 &&
2551 <                    U.compareAndSwapInt(this, SIZECTL, sc, -2))
2552 <                    transfer(tab, null);
2553 <            }
2588 >            if ((n = tab.length) < MIN_TREEIFY_CAPACITY)
2589 >                tryPresize(n << 1);
2590              else if ((b = tabAt(tab, index)) != null && b.hash >= 0) {
2591                  synchronized (b) {
2592                      if (tabAt(tab, index) == b) {
# Line 2748 | Line 2784 | public class ConcurrentHashMap<K,V> exte
2784          private final void contendedLock() {
2785              boolean waiting = false;
2786              for (int s;;) {
2787 <                if (((s = lockState) & WRITER) == 0) {
2787 >                if (((s = lockState) & ~WAITER) == 0) {
2788                      if (U.compareAndSwapInt(this, LOCKSTATE, s, WRITER)) {
2789                          if (waiting)
2790                              waiter = null;
# Line 3194 | Line 3230 | public class ConcurrentHashMap<K,V> exte
3230      /* ----------------Table Traversal -------------- */
3231  
3232      /**
3233 +     * Records the table, its length, and current traversal index for a
3234 +     * traverser that must process a region of a forwarded table before
3235 +     * proceeding with current table.
3236 +     */
3237 +    static final class TableStack<K,V> {
3238 +        int length;
3239 +        int index;
3240 +        Node<K,V>[] tab;
3241 +        TableStack<K,V> next;
3242 +    }
3243 +
3244 +    /**
3245       * Encapsulates traversal for methods such as containsValue; also
3246       * serves as a base class for other iterators and spliterators.
3247       *
# Line 3217 | Line 3265 | public class ConcurrentHashMap<K,V> exte
3265      static class Traverser<K,V> {
3266          Node<K,V>[] tab;        // current table; updated if resized
3267          Node<K,V> next;         // the next entry to use
3268 +        TableStack<K,V> stack, spare; // to save/restore on ForwardingNodes
3269          int index;              // index of bin to use next
3270          int baseIndex;          // current index of initial table
3271          int baseLimit;          // index bound for initial table
# Line 3238 | Line 3287 | public class ConcurrentHashMap<K,V> exte
3287              if ((e = next) != null)
3288                  e = e.next;
3289              for (;;) {
3290 <                Node<K,V>[] t; int i, n; K ek;  // must use locals in checks
3290 >                Node<K,V>[] t; int i, n;  // must use locals in checks
3291                  if (e != null)
3292                      return next = e;
3293                  if (baseIndex >= baseLimit || (t = tab) == null ||
3294                      (n = t.length) <= (i = index) || i < 0)
3295                      return next = null;
3296 <                if ((e = tabAt(t, index)) != null && e.hash < 0) {
3296 >                if ((e = tabAt(t, i)) != null && e.hash < 0) {
3297                      if (e instanceof ForwardingNode) {
3298                          tab = ((ForwardingNode<K,V>)e).nextTable;
3299                          e = null;
3300 +                        pushState(t, i, n);
3301                          continue;
3302                      }
3303                      else if (e instanceof TreeBin)
# Line 3255 | Line 3305 | public class ConcurrentHashMap<K,V> exte
3305                      else
3306                          e = null;
3307                  }
3308 <                if ((index += baseSize) >= n)
3309 <                    index = ++baseIndex;    // visit upper slots if present
3308 >                if (stack != null)
3309 >                    recoverState(n);
3310 >                else if ((index = i + baseSize) >= n)
3311 >                    index = ++baseIndex; // visit upper slots if present
3312              }
3313          }
3314 +
3315 +        /**
3316 +         * Saves traversal state upon encountering a forwarding node.
3317 +         */
3318 +        private void pushState(Node<K,V>[] t, int i, int n) {
3319 +            TableStack<K,V> s = spare;  // reuse if possible
3320 +            if (s != null)
3321 +                spare = s.next;
3322 +            else
3323 +                s = new TableStack<K,V>();
3324 +            s.tab = t;
3325 +            s.length = n;
3326 +            s.index = i;
3327 +            s.next = stack;
3328 +            stack = s;
3329 +        }
3330 +
3331 +        /**
3332 +         * Possibly pops traversal state.
3333 +         *
3334 +         * @param n length of current table
3335 +         */
3336 +        private void recoverState(int n) {
3337 +            TableStack<K,V> s; int len;
3338 +            while ((s = stack) != null && (index += (len = s.length)) >= n) {
3339 +                n = len;
3340 +                index = s.index;
3341 +                tab = s.tab;
3342 +                s.tab = null;
3343 +                TableStack<K,V> next = s.next;
3344 +                s.next = spare; // save for reuse
3345 +                stack = next;
3346 +                spare = s;
3347 +            }
3348 +            if (s == null && (index += baseSize) >= n)
3349 +                index = ++baseIndex;
3350 +        }
3351      }
3352  
3353      /**
# Line 4381 | Line 4470 | public class ConcurrentHashMap<K,V> exte
4470          }
4471  
4472          public final boolean removeAll(Collection<?> c) {
4473 +            if (c == null) throw new NullPointerException();
4474              boolean modified = false;
4475              for (Iterator<E> it = iterator(); it.hasNext();) {
4476                  if (c.contains(it.next())) {
# Line 4392 | Line 4482 | public class ConcurrentHashMap<K,V> exte
4482          }
4483  
4484          public final boolean retainAll(Collection<?> c) {
4485 +            if (c == null) throw new NullPointerException();
4486              boolean modified = false;
4487              for (Iterator<E> it = iterator(); it.hasNext();) {
4488                  if (!c.contains(it.next())) {
# Line 4690 | Line 4781 | public class ConcurrentHashMap<K,V> exte
4781      abstract static class BulkTask<K,V,R> extends CountedCompleter<R> {
4782          Node<K,V>[] tab;        // same as Traverser
4783          Node<K,V> next;
4784 +        TableStack<K,V> stack, spare;
4785          int index;
4786          int baseIndex;
4787          int baseLimit;
# Line 4718 | Line 4810 | public class ConcurrentHashMap<K,V> exte
4810              if ((e = next) != null)
4811                  e = e.next;
4812              for (;;) {
4813 <                Node<K,V>[] t; int i, n; K ek;  // must use locals in checks
4813 >                Node<K,V>[] t; int i, n;
4814                  if (e != null)
4815                      return next = e;
4816                  if (baseIndex >= baseLimit || (t = tab) == null ||
4817                      (n = t.length) <= (i = index) || i < 0)
4818                      return next = null;
4819 <                if ((e = tabAt(t, index)) != null && e.hash < 0) {
4819 >                if ((e = tabAt(t, i)) != null && e.hash < 0) {
4820                      if (e instanceof ForwardingNode) {
4821                          tab = ((ForwardingNode<K,V>)e).nextTable;
4822                          e = null;
4823 +                        pushState(t, i, n);
4824                          continue;
4825                      }
4826                      else if (e instanceof TreeBin)
# Line 4735 | Line 4828 | public class ConcurrentHashMap<K,V> exte
4828                      else
4829                          e = null;
4830                  }
4831 <                if ((index += baseSize) >= n)
4832 <                    index = ++baseIndex;    // visit upper slots if present
4831 >                if (stack != null)
4832 >                    recoverState(n);
4833 >                else if ((index = i + baseSize) >= n)
4834 >                    index = ++baseIndex;
4835 >            }
4836 >        }
4837 >
4838 >        private void pushState(Node<K,V>[] t, int i, int n) {
4839 >            TableStack<K,V> s = spare;
4840 >            if (s != null)
4841 >                spare = s.next;
4842 >            else
4843 >                s = new TableStack<K,V>();
4844 >            s.tab = t;
4845 >            s.length = n;
4846 >            s.index = i;
4847 >            s.next = stack;
4848 >            stack = s;
4849 >        }
4850 >
4851 >        private void recoverState(int n) {
4852 >            TableStack<K,V> s; int len;
4853 >            while ((s = stack) != null && (index += (len = s.length)) >= n) {
4854 >                n = len;
4855 >                index = s.index;
4856 >                tab = s.tab;
4857 >                s.tab = null;
4858 >                TableStack<K,V> next = s.next;
4859 >                s.next = spare; // save for reuse
4860 >                stack = next;
4861 >                spare = s;
4862              }
4863 +            if (s == null && (index += baseSize) >= n)
4864 +                index = ++baseIndex;
4865          }
4866      }
4867  
# Line 5197 | Line 5321 | public class ConcurrentHashMap<K,V> exte
5321                  result = r;
5322                  CountedCompleter<?> c;
5323                  for (c = firstComplete(); c != null; c = c.nextComplete()) {
5324 <                    @SuppressWarnings("unchecked") ReduceKeysTask<K,V>
5324 >                    @SuppressWarnings("unchecked")
5325 >                    ReduceKeysTask<K,V>
5326                          t = (ReduceKeysTask<K,V>)c,
5327                          s = t.rights;
5328                      while (s != null) {
# Line 5244 | Line 5369 | public class ConcurrentHashMap<K,V> exte
5369                  result = r;
5370                  CountedCompleter<?> c;
5371                  for (c = firstComplete(); c != null; c = c.nextComplete()) {
5372 <                    @SuppressWarnings("unchecked") ReduceValuesTask<K,V>
5372 >                    @SuppressWarnings("unchecked")
5373 >                    ReduceValuesTask<K,V>
5374                          t = (ReduceValuesTask<K,V>)c,
5375                          s = t.rights;
5376                      while (s != null) {
# Line 5289 | Line 5415 | public class ConcurrentHashMap<K,V> exte
5415                  result = r;
5416                  CountedCompleter<?> c;
5417                  for (c = firstComplete(); c != null; c = c.nextComplete()) {
5418 <                    @SuppressWarnings("unchecked") ReduceEntriesTask<K,V>
5418 >                    @SuppressWarnings("unchecked")
5419 >                    ReduceEntriesTask<K,V>
5420                          t = (ReduceEntriesTask<K,V>)c,
5421                          s = t.rights;
5422                      while (s != null) {
# Line 5342 | Line 5469 | public class ConcurrentHashMap<K,V> exte
5469                  result = r;
5470                  CountedCompleter<?> c;
5471                  for (c = firstComplete(); c != null; c = c.nextComplete()) {
5472 <                    @SuppressWarnings("unchecked") MapReduceKeysTask<K,V,U>
5472 >                    @SuppressWarnings("unchecked")
5473 >                    MapReduceKeysTask<K,V,U>
5474                          t = (MapReduceKeysTask<K,V,U>)c,
5475                          s = t.rights;
5476                      while (s != null) {
# Line 5395 | Line 5523 | public class ConcurrentHashMap<K,V> exte
5523                  result = r;
5524                  CountedCompleter<?> c;
5525                  for (c = firstComplete(); c != null; c = c.nextComplete()) {
5526 <                    @SuppressWarnings("unchecked") MapReduceValuesTask<K,V,U>
5526 >                    @SuppressWarnings("unchecked")
5527 >                    MapReduceValuesTask<K,V,U>
5528                          t = (MapReduceValuesTask<K,V,U>)c,
5529                          s = t.rights;
5530                      while (s != null) {
# Line 5448 | Line 5577 | public class ConcurrentHashMap<K,V> exte
5577                  result = r;
5578                  CountedCompleter<?> c;
5579                  for (c = firstComplete(); c != null; c = c.nextComplete()) {
5580 <                    @SuppressWarnings("unchecked") MapReduceEntriesTask<K,V,U>
5580 >                    @SuppressWarnings("unchecked")
5581 >                    MapReduceEntriesTask<K,V,U>
5582                          t = (MapReduceEntriesTask<K,V,U>)c,
5583                          s = t.rights;
5584                      while (s != null) {
# Line 5501 | Line 5631 | public class ConcurrentHashMap<K,V> exte
5631                  result = r;
5632                  CountedCompleter<?> c;
5633                  for (c = firstComplete(); c != null; c = c.nextComplete()) {
5634 <                    @SuppressWarnings("unchecked") MapReduceMappingsTask<K,V,U>
5634 >                    @SuppressWarnings("unchecked")
5635 >                    MapReduceMappingsTask<K,V,U>
5636                          t = (MapReduceMappingsTask<K,V,U>)c,
5637                          s = t.rights;
5638                      while (s != null) {
# Line 5553 | Line 5684 | public class ConcurrentHashMap<K,V> exte
5684                  result = r;
5685                  CountedCompleter<?> c;
5686                  for (c = firstComplete(); c != null; c = c.nextComplete()) {
5687 <                    @SuppressWarnings("unchecked") MapReduceKeysToDoubleTask<K,V>
5687 >                    @SuppressWarnings("unchecked")
5688 >                    MapReduceKeysToDoubleTask<K,V>
5689                          t = (MapReduceKeysToDoubleTask<K,V>)c,
5690                          s = t.rights;
5691                      while (s != null) {
# Line 5602 | Line 5734 | public class ConcurrentHashMap<K,V> exte
5734                  result = r;
5735                  CountedCompleter<?> c;
5736                  for (c = firstComplete(); c != null; c = c.nextComplete()) {
5737 <                    @SuppressWarnings("unchecked") MapReduceValuesToDoubleTask<K,V>
5737 >                    @SuppressWarnings("unchecked")
5738 >                    MapReduceValuesToDoubleTask<K,V>
5739                          t = (MapReduceValuesToDoubleTask<K,V>)c,
5740                          s = t.rights;
5741                      while (s != null) {
# Line 5651 | Line 5784 | public class ConcurrentHashMap<K,V> exte
5784                  result = r;
5785                  CountedCompleter<?> c;
5786                  for (c = firstComplete(); c != null; c = c.nextComplete()) {
5787 <                    @SuppressWarnings("unchecked") MapReduceEntriesToDoubleTask<K,V>
5787 >                    @SuppressWarnings("unchecked")
5788 >                    MapReduceEntriesToDoubleTask<K,V>
5789                          t = (MapReduceEntriesToDoubleTask<K,V>)c,
5790                          s = t.rights;
5791                      while (s != null) {
# Line 5700 | Line 5834 | public class ConcurrentHashMap<K,V> exte
5834                  result = r;
5835                  CountedCompleter<?> c;
5836                  for (c = firstComplete(); c != null; c = c.nextComplete()) {
5837 <                    @SuppressWarnings("unchecked") MapReduceMappingsToDoubleTask<K,V>
5837 >                    @SuppressWarnings("unchecked")
5838 >                    MapReduceMappingsToDoubleTask<K,V>
5839                          t = (MapReduceMappingsToDoubleTask<K,V>)c,
5840                          s = t.rights;
5841                      while (s != null) {
# Line 5749 | Line 5884 | public class ConcurrentHashMap<K,V> exte
5884                  result = r;
5885                  CountedCompleter<?> c;
5886                  for (c = firstComplete(); c != null; c = c.nextComplete()) {
5887 <                    @SuppressWarnings("unchecked") MapReduceKeysToLongTask<K,V>
5887 >                    @SuppressWarnings("unchecked")
5888 >                    MapReduceKeysToLongTask<K,V>
5889                          t = (MapReduceKeysToLongTask<K,V>)c,
5890                          s = t.rights;
5891                      while (s != null) {
# Line 5798 | Line 5934 | public class ConcurrentHashMap<K,V> exte
5934                  result = r;
5935                  CountedCompleter<?> c;
5936                  for (c = firstComplete(); c != null; c = c.nextComplete()) {
5937 <                    @SuppressWarnings("unchecked") MapReduceValuesToLongTask<K,V>
5937 >                    @SuppressWarnings("unchecked")
5938 >                    MapReduceValuesToLongTask<K,V>
5939                          t = (MapReduceValuesToLongTask<K,V>)c,
5940                          s = t.rights;
5941                      while (s != null) {
# Line 5847 | Line 5984 | public class ConcurrentHashMap<K,V> exte
5984                  result = r;
5985                  CountedCompleter<?> c;
5986                  for (c = firstComplete(); c != null; c = c.nextComplete()) {
5987 <                    @SuppressWarnings("unchecked") MapReduceEntriesToLongTask<K,V>
5987 >                    @SuppressWarnings("unchecked")
5988 >                    MapReduceEntriesToLongTask<K,V>
5989                          t = (MapReduceEntriesToLongTask<K,V>)c,
5990                          s = t.rights;
5991                      while (s != null) {
# Line 5896 | Line 6034 | public class ConcurrentHashMap<K,V> exte
6034                  result = r;
6035                  CountedCompleter<?> c;
6036                  for (c = firstComplete(); c != null; c = c.nextComplete()) {
6037 <                    @SuppressWarnings("unchecked") MapReduceMappingsToLongTask<K,V>
6037 >                    @SuppressWarnings("unchecked")
6038 >                    MapReduceMappingsToLongTask<K,V>
6039                          t = (MapReduceMappingsToLongTask<K,V>)c,
6040                          s = t.rights;
6041                      while (s != null) {
# Line 5945 | Line 6084 | public class ConcurrentHashMap<K,V> exte
6084                  result = r;
6085                  CountedCompleter<?> c;
6086                  for (c = firstComplete(); c != null; c = c.nextComplete()) {
6087 <                    @SuppressWarnings("unchecked") MapReduceKeysToIntTask<K,V>
6087 >                    @SuppressWarnings("unchecked")
6088 >                    MapReduceKeysToIntTask<K,V>
6089                          t = (MapReduceKeysToIntTask<K,V>)c,
6090                          s = t.rights;
6091                      while (s != null) {
# Line 5994 | Line 6134 | public class ConcurrentHashMap<K,V> exte
6134                  result = r;
6135                  CountedCompleter<?> c;
6136                  for (c = firstComplete(); c != null; c = c.nextComplete()) {
6137 <                    @SuppressWarnings("unchecked") MapReduceValuesToIntTask<K,V>
6137 >                    @SuppressWarnings("unchecked")
6138 >                    MapReduceValuesToIntTask<K,V>
6139                          t = (MapReduceValuesToIntTask<K,V>)c,
6140                          s = t.rights;
6141                      while (s != null) {
# Line 6043 | Line 6184 | public class ConcurrentHashMap<K,V> exte
6184                  result = r;
6185                  CountedCompleter<?> c;
6186                  for (c = firstComplete(); c != null; c = c.nextComplete()) {
6187 <                    @SuppressWarnings("unchecked") MapReduceEntriesToIntTask<K,V>
6187 >                    @SuppressWarnings("unchecked")
6188 >                    MapReduceEntriesToIntTask<K,V>
6189                          t = (MapReduceEntriesToIntTask<K,V>)c,
6190                          s = t.rights;
6191                      while (s != null) {
# Line 6092 | Line 6234 | public class ConcurrentHashMap<K,V> exte
6234                  result = r;
6235                  CountedCompleter<?> c;
6236                  for (c = firstComplete(); c != null; c = c.nextComplete()) {
6237 <                    @SuppressWarnings("unchecked") MapReduceMappingsToIntTask<K,V>
6237 >                    @SuppressWarnings("unchecked")
6238 >                    MapReduceMappingsToIntTask<K,V>
6239                          t = (MapReduceMappingsToIntTask<K,V>)c,
6240                          s = t.rights;
6241                      while (s != null) {
# Line 6108 | Line 6251 | public class ConcurrentHashMap<K,V> exte
6251      private static final sun.misc.Unsafe U;
6252      private static final long SIZECTL;
6253      private static final long TRANSFERINDEX;
6111    private static final long TRANSFERORIGIN;
6254      private static final long BASECOUNT;
6255      private static final long CELLSBUSY;
6256      private static final long CELLVALUE;
# Line 6123 | Line 6265 | public class ConcurrentHashMap<K,V> exte
6265                  (k.getDeclaredField("sizeCtl"));
6266              TRANSFERINDEX = U.objectFieldOffset
6267                  (k.getDeclaredField("transferIndex"));
6126            TRANSFERORIGIN = U.objectFieldOffset
6127                (k.getDeclaredField("transferOrigin"));
6268              BASECOUNT = U.objectFieldOffset
6269                  (k.getDeclaredField("baseCount"));
6270              CELLSBUSY = U.objectFieldOffset

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines