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.294 by dl, Wed Jun 8 19:44:32 2016 UTC vs.
Revision 1.324 by dl, Fri Mar 18 16:01:41 2022 UTC

# Line 130 | Line 130 | import jdk.internal.misc.Unsafe;
130   * ordering, or on any other objects or values that may transiently
131   * change while computation is in progress; and except for forEach
132   * actions, should ideally be side-effect-free. Bulk operations on
133 < * {@link java.util.Map.Entry} objects do not support method {@code
134 < * setValue}.
133 > * {@link Map.Entry} objects do not support method {@code setValue}.
134   *
135   * <ul>
136   * <li>forEach: Performs a given action on each element.
# Line 225 | Line 224 | import jdk.internal.misc.Unsafe;
224   * <p>All arguments to all task methods must be non-null.
225   *
226   * <p>This class is a member of the
227 < * <a href="{@docRoot}/../technotes/guides/collections/index.html">
227 > * <a href="{@docRoot}/java.base/java/util/package-summary.html#CollectionsFramework">
228   * Java Collections Framework</a>.
229   *
230   * @since 1.5
# Line 357 | Line 356 | public class ConcurrentHashMap<K,V> exte
356       * cases where old nodes can be reused because their next fields
357       * won't change.  On average, only about one-sixth of them need
358       * cloning when a table doubles. The nodes they replace will be
359 <     * garbage collectable as soon as they are no longer referenced by
359 >     * garbage collectible as soon as they are no longer referenced by
360       * any reader thread that may be in the midst of concurrently
361       * traversing table.  Upon transfer, the old table bin contains
362       * only a special forwarding node (with hash field "MOVED") that
# Line 674 | Line 673 | public class ConcurrentHashMap<K,V> exte
673       * See Hackers Delight, sec 3.2
674       */
675      private static final int tableSizeFor(int c) {
676 <        int n = c - 1;
678 <        n |= n >>> 1;
679 <        n |= n >>> 2;
680 <        n |= n >>> 4;
681 <        n |= n >>> 8;
682 <        n |= n >>> 16;
676 >        int n = -1 >>> Integer.numberOfLeadingZeros(c - 1);
677          return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
678      }
679  
# Line 689 | Line 683 | public class ConcurrentHashMap<K,V> exte
683       */
684      static Class<?> comparableClassFor(Object x) {
685          if (x instanceof Comparable) {
686 <            Class<?> c; Type[] ts, as; Type t; ParameterizedType p;
686 >            Class<?> c; Type[] ts, as; ParameterizedType p;
687              if ((c = x.getClass()) == String.class) // bypass checks
688                  return c;
689              if ((ts = c.getGenericInterfaces()) != null) {
690 <                for (int i = 0; i < ts.length; ++i) {
691 <                    if (((t = ts[i]) instanceof ParameterizedType) &&
690 >                for (Type t : ts) {
691 >                    if ((t instanceof ParameterizedType) &&
692                          ((p = (ParameterizedType)t).getRawType() ==
693                           Comparable.class) &&
694                          (as = p.getActualTypeArguments()) != null &&
# Line 734 | Line 728 | public class ConcurrentHashMap<K,V> exte
728  
729      @SuppressWarnings("unchecked")
730      static final <K,V> Node<K,V> tabAt(Node<K,V>[] tab, int i) {
731 <        return (Node<K,V>)U.getObjectAcquire(tab, ((long)i << ASHIFT) + ABASE);
731 >        return (Node<K,V>)U.getReferenceAcquire(tab, ((long)i << ASHIFT) + ABASE);
732      }
733  
734      static final <K,V> boolean casTabAt(Node<K,V>[] tab, int i,
735                                          Node<K,V> c, Node<K,V> v) {
736 <        return U.compareAndSwapObject(tab, ((long)i << ASHIFT) + ABASE, c, v);
736 >        return U.compareAndSetReference(tab, ((long)i << ASHIFT) + ABASE, c, v);
737      }
738  
739      static final <K,V> void setTabAt(Node<K,V>[] tab, int i, Node<K,V> v) {
740 <        U.putObjectRelease(tab, ((long)i << ASHIFT) + ABASE, v);
740 >        U.putReferenceRelease(tab, ((long)i << ASHIFT) + ABASE, v);
741      }
742  
743      /* ---------------- Fields -------------- */
# Line 816 | Line 810 | public class ConcurrentHashMap<K,V> exte
810       * elements is negative
811       */
812      public ConcurrentHashMap(int initialCapacity) {
813 <        if (initialCapacity < 0)
820 <            throw new IllegalArgumentException();
821 <        int cap = ((initialCapacity >= (MAXIMUM_CAPACITY >>> 1)) ?
822 <                   MAXIMUM_CAPACITY :
823 <                   tableSizeFor(initialCapacity + (initialCapacity >>> 1) + 1));
824 <        this.sizeCtl = cap;
813 >        this(initialCapacity, LOAD_FACTOR, 1);
814      }
815  
816      /**
# Line 855 | Line 844 | public class ConcurrentHashMap<K,V> exte
844  
845      /**
846       * Creates a new, empty map with an initial table size based on
847 <     * the given number of elements ({@code initialCapacity}), table
848 <     * density ({@code loadFactor}), and number of concurrently
847 >     * the given number of elements ({@code initialCapacity}), initial
848 >     * table density ({@code loadFactor}), and number of concurrently
849       * updating threads ({@code concurrencyLevel}).
850       *
851       * @param initialCapacity the initial capacity. The implementation
# Line 994 | Line 983 | public class ConcurrentHashMap<K,V> exte
983          int hash = spread(key.hashCode());
984          int binCount = 0;
985          for (Node<K,V>[] tab = table;;) {
986 <            Node<K,V> f; int n, i, fh;
986 >            Node<K,V> f; int n, i, fh; K fk; V fv;
987              if (tab == null || (n = tab.length) == 0)
988                  tab = initTable();
989              else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) {
# Line 1003 | Line 992 | public class ConcurrentHashMap<K,V> exte
992              }
993              else if ((fh = f.hash) == MOVED)
994                  tab = helpTransfer(tab, f);
995 +            else if (onlyIfAbsent // check first node without acquiring lock
996 +                     && fh == hash
997 +                     && ((fk = f.key) == key || (fk != null && key.equals(fk)))
998 +                     && (fv = f.val) != null)
999 +                return fv;
1000              else {
1001                  V oldVal = null;
1002                  synchronized (f) {
# Line 1361 | Line 1355 | public class ConcurrentHashMap<K,V> exte
1355      }
1356  
1357      /**
1358 <     * Saves the state of the {@code ConcurrentHashMap} instance to a
1359 <     * stream (i.e., serializes it).
1358 >     * Saves this map to a stream (that is, serializes it).
1359 >     *
1360       * @param s the stream
1361       * @throws java.io.IOException if an I/O error occurs
1362       * @serialData
# Line 1406 | Line 1400 | public class ConcurrentHashMap<K,V> exte
1400      }
1401  
1402      /**
1403 <     * Reconstitutes the instance from a stream (that is, deserializes it).
1403 >     * Reconstitutes this map from a stream (that is, deserializes it).
1404       * @param s the stream
1405       * @throws ClassNotFoundException if the class of a serialized object
1406       *         could not be found
# Line 1440 | Line 1434 | public class ConcurrentHashMap<K,V> exte
1434          if (size == 0L)
1435              sizeCtl = 0;
1436          else {
1437 <            int n;
1438 <            if (size >= (long)(MAXIMUM_CAPACITY >>> 1))
1439 <                n = MAXIMUM_CAPACITY;
1446 <            else {
1447 <                int sz = (int)size;
1448 <                n = tableSizeFor(sz + (sz >>> 1) + 1);
1449 <            }
1437 >            long ts = (long)(1.0 + size / LOAD_FACTOR);
1438 >            int n = (ts >= (long)MAXIMUM_CAPACITY) ?
1439 >                MAXIMUM_CAPACITY : tableSizeFor((int)ts);
1440              @SuppressWarnings("unchecked")
1441              Node<K,V>[] tab = (Node<K,V>[])new Node<?,?>[n];
1442              int mask = n - 1;
# Line 1648 | Line 1638 | public class ConcurrentHashMap<K,V> exte
1638       * If the specified key is not already associated with a value,
1639       * attempts to compute its value using the given mapping function
1640       * and enters it into this map unless {@code null}.  The entire
1641 <     * method invocation is performed atomically, so the function is
1642 <     * applied at most once per key.  Some attempted update operations
1643 <     * on this map by other threads may be blocked while computation
1644 <     * is in progress, so the computation should be short and simple,
1645 <     * and must not attempt to update any other mappings of this map.
1641 >     * method invocation is performed atomically.  The supplied
1642 >     * function is invoked exactly once per invocation of this method
1643 >     * if the key is absent, else not at all.  Some attempted update
1644 >     * operations on this map by other threads may be blocked while
1645 >     * computation is in progress, so the computation should be short
1646 >     * and simple.
1647 >     *
1648 >     * <p>The mapping function must not modify this map during computation.
1649       *
1650       * @param key key with which the specified value is to be associated
1651       * @param mappingFunction the function to compute a value
# Line 1673 | Line 1666 | public class ConcurrentHashMap<K,V> exte
1666          V val = null;
1667          int binCount = 0;
1668          for (Node<K,V>[] tab = table;;) {
1669 <            Node<K,V> f; int n, i, fh;
1669 >            Node<K,V> f; int n, i, fh; K fk; V fv;
1670              if (tab == null || (n = tab.length) == 0)
1671                  tab = initTable();
1672              else if ((f = tabAt(tab, i = (n - 1) & h)) == null) {
# Line 1695 | Line 1688 | public class ConcurrentHashMap<K,V> exte
1688              }
1689              else if ((fh = f.hash) == MOVED)
1690                  tab = helpTransfer(tab, f);
1691 +            else if (fh == h    // check first node without acquiring lock
1692 +                     && ((fk = f.key) == key || (fk != null && key.equals(fk)))
1693 +                     && (fv = f.val) != null)
1694 +                return fv;
1695              else {
1696                  boolean added = false;
1697                  synchronized (f) {
# Line 1755 | Line 1752 | public class ConcurrentHashMap<K,V> exte
1752       * If the value for the specified key is present, attempts to
1753       * compute a new mapping given the key and its current mapped
1754       * value.  The entire method invocation is performed atomically.
1755 <     * Some attempted update operations on this map by other threads
1756 <     * may be blocked while computation is in progress, so the
1757 <     * computation should be short and simple, and must not attempt to
1758 <     * update any other mappings of this map.
1755 >     * The supplied function is invoked exactly once per invocation of
1756 >     * this method if the key is present, else not at all.  Some
1757 >     * attempted update operations on this map by other threads may be
1758 >     * blocked while computation is in progress, so the computation
1759 >     * should be short and simple.
1760 >     *
1761 >     * <p>The remapping function must not modify this map during computation.
1762       *
1763       * @param key key with which a value may be associated
1764       * @param remappingFunction the function to compute a value
# Line 1847 | Line 1847 | public class ConcurrentHashMap<K,V> exte
1847       * Attempts to compute a mapping for the specified key and its
1848       * current mapped value (or {@code null} if there is no current
1849       * mapping). The entire method invocation is performed atomically.
1850 <     * Some attempted update operations on this map by other threads
1851 <     * may be blocked while computation is in progress, so the
1852 <     * computation should be short and simple, and must not attempt to
1853 <     * update any other mappings of this Map.
1850 >     * The supplied function is invoked exactly once per invocation of
1851 >     * this method.  Some attempted update operations on this map by
1852 >     * other threads may be blocked while computation is in progress,
1853 >     * so the computation should be short and simple.
1854 >     *
1855 >     * <p>The remapping function must not modify this map during computation.
1856       *
1857       * @param key key with which the specified value is to be associated
1858       * @param remappingFunction the function to compute a value
# Line 2262 | Line 2264 | public class ConcurrentHashMap<K,V> exte
2264          while ((tab = table) == null || tab.length == 0) {
2265              if ((sc = sizeCtl) < 0)
2266                  Thread.yield(); // lost initialization race; just spin
2267 <            else if (U.compareAndSwapInt(this, SIZECTL, sc, -1)) {
2267 >            else if (U.compareAndSetInt(this, SIZECTL, sc, -1)) {
2268                  try {
2269                      if ((tab = table) == null || tab.length == 0) {
2270                          int n = (sc > 0) ? sc : DEFAULT_CAPACITY;
# Line 2291 | Line 2293 | public class ConcurrentHashMap<K,V> exte
2293       * @param check if <0, don't check resize, if <= 1 only check if uncontended
2294       */
2295      private final void addCount(long x, int check) {
2296 <        CounterCell[] as; long b, s;
2297 <        if ((as = counterCells) != null ||
2298 <            !U.compareAndSwapLong(this, BASECOUNT, b = baseCount, s = b + x)) {
2299 <            CounterCell a; long v; int m;
2296 >        CounterCell[] cs; long b, s;
2297 >        if ((cs = counterCells) != null ||
2298 >            !U.compareAndSetLong(this, BASECOUNT, b = baseCount, s = b + x)) {
2299 >            CounterCell c; long v; int m;
2300              boolean uncontended = true;
2301 <            if (as == null || (m = as.length - 1) < 0 ||
2302 <                (a = as[ThreadLocalRandom.getProbe() & m]) == null ||
2301 >            if (cs == null || (m = cs.length - 1) < 0 ||
2302 >                (c = cs[ThreadLocalRandom.getProbe() & m]) == null ||
2303                  !(uncontended =
2304 <                  U.compareAndSwapLong(a, CELLVALUE, v = a.value, v + x))) {
2304 >                  U.compareAndSetLong(c, CELLVALUE, v = c.value, v + x))) {
2305                  fullAddCount(x, uncontended);
2306                  return;
2307              }
# Line 2311 | Line 2313 | public class ConcurrentHashMap<K,V> exte
2313              Node<K,V>[] tab, nt; int n, sc;
2314              while (s >= (long)(sc = sizeCtl) && (tab = table) != null &&
2315                     (n = tab.length) < MAXIMUM_CAPACITY) {
2316 <                int rs = resizeStamp(n);
2316 >                int rs = resizeStamp(n) << RESIZE_STAMP_SHIFT;
2317                  if (sc < 0) {
2318 <                    if ((sc >>> RESIZE_STAMP_SHIFT) != rs || sc == rs + 1 ||
2319 <                        sc == rs + MAX_RESIZERS || (nt = nextTable) == null ||
2318 <                        transferIndex <= 0)
2318 >                    if (sc == rs + MAX_RESIZERS || sc == rs + 1 ||
2319 >                        (nt = nextTable) == null || transferIndex <= 0)
2320                          break;
2321 <                    if (U.compareAndSwapInt(this, SIZECTL, sc, sc + 1))
2321 >                    if (U.compareAndSetInt(this, SIZECTL, sc, sc + 1))
2322                          transfer(tab, nt);
2323                  }
2324 <                else if (U.compareAndSwapInt(this, SIZECTL, sc,
2324 <                                             (rs << RESIZE_STAMP_SHIFT) + 2))
2324 >                else if (U.compareAndSetInt(this, SIZECTL, sc, rs + 2))
2325                      transfer(tab, null);
2326                  s = sumCount();
2327              }
# Line 2335 | Line 2335 | public class ConcurrentHashMap<K,V> exte
2335          Node<K,V>[] nextTab; int sc;
2336          if (tab != null && (f instanceof ForwardingNode) &&
2337              (nextTab = ((ForwardingNode<K,V>)f).nextTable) != null) {
2338 <            int rs = resizeStamp(tab.length);
2338 >            int rs = resizeStamp(tab.length) << RESIZE_STAMP_SHIFT;
2339              while (nextTab == nextTable && table == tab &&
2340                     (sc = sizeCtl) < 0) {
2341 <                if ((sc >>> RESIZE_STAMP_SHIFT) != rs || sc == rs + 1 ||
2342 <                    sc == rs + MAX_RESIZERS || transferIndex <= 0)
2341 >                if (sc == rs + MAX_RESIZERS || sc == rs + 1 ||
2342 >                    transferIndex <= 0)
2343                      break;
2344 <                if (U.compareAndSwapInt(this, SIZECTL, sc, sc + 1)) {
2344 >                if (U.compareAndSetInt(this, SIZECTL, sc, sc + 1)) {
2345                      transfer(tab, nextTab);
2346                      break;
2347                  }
# Line 2364 | Line 2364 | public class ConcurrentHashMap<K,V> exte
2364              Node<K,V>[] tab = table; int n;
2365              if (tab == null || (n = tab.length) == 0) {
2366                  n = (sc > c) ? sc : c;
2367 <                if (U.compareAndSwapInt(this, SIZECTL, sc, -1)) {
2367 >                if (U.compareAndSetInt(this, SIZECTL, sc, -1)) {
2368                      try {
2369                          if (table == tab) {
2370                              @SuppressWarnings("unchecked")
# Line 2381 | Line 2381 | public class ConcurrentHashMap<K,V> exte
2381                  break;
2382              else if (tab == table) {
2383                  int rs = resizeStamp(n);
2384 <                if (U.compareAndSwapInt(this, SIZECTL, sc,
2384 >                if (U.compareAndSetInt(this, SIZECTL, sc,
2385                                          (rs << RESIZE_STAMP_SHIFT) + 2))
2386                      transfer(tab, null);
2387              }
# Line 2422 | Line 2422 | public class ConcurrentHashMap<K,V> exte
2422                      i = -1;
2423                      advance = false;
2424                  }
2425 <                else if (U.compareAndSwapInt
2425 >                else if (U.compareAndSetInt
2426                           (this, TRANSFERINDEX, nextIndex,
2427                            nextBound = (nextIndex > stride ?
2428                                         nextIndex - stride : 0))) {
# Line 2439 | Line 2439 | public class ConcurrentHashMap<K,V> exte
2439                      sizeCtl = (n << 1) - (n >>> 1);
2440                      return;
2441                  }
2442 <                if (U.compareAndSwapInt(this, SIZECTL, sc = sizeCtl, sc - 1)) {
2442 >                if (U.compareAndSetInt(this, SIZECTL, sc = sizeCtl, sc - 1)) {
2443                      if ((sc - 2) != resizeStamp(n) << RESIZE_STAMP_SHIFT)
2444                          return;
2445                      finishing = advance = true;
# Line 2519 | Line 2519 | public class ConcurrentHashMap<K,V> exte
2519                              setTabAt(tab, i, fwd);
2520                              advance = true;
2521                          }
2522 +                        else if (f instanceof ReservationNode)
2523 +                            throw new IllegalStateException("Recursive update");
2524                      }
2525                  }
2526              }
# Line 2537 | Line 2539 | public class ConcurrentHashMap<K,V> exte
2539      }
2540  
2541      final long sumCount() {
2542 <        CounterCell[] as = counterCells; CounterCell a;
2542 >        CounterCell[] cs = counterCells;
2543          long sum = baseCount;
2544 <        if (as != null) {
2545 <            for (int i = 0; i < as.length; ++i) {
2546 <                if ((a = as[i]) != null)
2547 <                    sum += a.value;
2546 <            }
2544 >        if (cs != null) {
2545 >            for (CounterCell c : cs)
2546 >                if (c != null)
2547 >                    sum += c.value;
2548          }
2549          return sum;
2550      }
# Line 2558 | Line 2559 | public class ConcurrentHashMap<K,V> exte
2559          }
2560          boolean collide = false;                // True if last slot nonempty
2561          for (;;) {
2562 <            CounterCell[] as; CounterCell a; int n; long v;
2563 <            if ((as = counterCells) != null && (n = as.length) > 0) {
2564 <                if ((a = as[(n - 1) & h]) == null) {
2562 >            CounterCell[] cs; CounterCell c; int n; long v;
2563 >            if ((cs = counterCells) != null && (n = cs.length) > 0) {
2564 >                if ((c = cs[(n - 1) & h]) == null) {
2565                      if (cellsBusy == 0) {            // Try to attach new Cell
2566                          CounterCell r = new CounterCell(x); // Optimistic create
2567                          if (cellsBusy == 0 &&
2568 <                            U.compareAndSwapInt(this, CELLSBUSY, 0, 1)) {
2568 >                            U.compareAndSetInt(this, CELLSBUSY, 0, 1)) {
2569                              boolean created = false;
2570                              try {               // Recheck under lock
2571                                  CounterCell[] rs; int m, j;
# Line 2586 | Line 2587 | public class ConcurrentHashMap<K,V> exte
2587                  }
2588                  else if (!wasUncontended)       // CAS already known to fail
2589                      wasUncontended = true;      // Continue after rehash
2590 <                else if (U.compareAndSwapLong(a, CELLVALUE, v = a.value, v + x))
2590 >                else if (U.compareAndSetLong(c, CELLVALUE, v = c.value, v + x))
2591                      break;
2592 <                else if (counterCells != as || n >= NCPU)
2592 >                else if (counterCells != cs || n >= NCPU)
2593                      collide = false;            // At max size or stale
2594                  else if (!collide)
2595                      collide = true;
2596                  else if (cellsBusy == 0 &&
2597 <                         U.compareAndSwapInt(this, CELLSBUSY, 0, 1)) {
2597 >                         U.compareAndSetInt(this, CELLSBUSY, 0, 1)) {
2598                      try {
2599 <                        if (counterCells == as) {// Expand table unless stale
2600 <                            CounterCell[] rs = new CounterCell[n << 1];
2600 <                            for (int i = 0; i < n; ++i)
2601 <                                rs[i] = as[i];
2602 <                            counterCells = rs;
2603 <                        }
2599 >                        if (counterCells == cs) // Expand table unless stale
2600 >                            counterCells = Arrays.copyOf(cs, n << 1);
2601                      } finally {
2602                          cellsBusy = 0;
2603                      }
# Line 2609 | Line 2606 | public class ConcurrentHashMap<K,V> exte
2606                  }
2607                  h = ThreadLocalRandom.advanceProbe(h);
2608              }
2609 <            else if (cellsBusy == 0 && counterCells == as &&
2610 <                     U.compareAndSwapInt(this, CELLSBUSY, 0, 1)) {
2609 >            else if (cellsBusy == 0 && counterCells == cs &&
2610 >                     U.compareAndSetInt(this, CELLSBUSY, 0, 1)) {
2611                  boolean init = false;
2612                  try {                           // Initialize table
2613 <                    if (counterCells == as) {
2613 >                    if (counterCells == cs) {
2614                          CounterCell[] rs = new CounterCell[2];
2615                          rs[h & 1] = new CounterCell(x);
2616                          counterCells = rs;
# Line 2625 | Line 2622 | public class ConcurrentHashMap<K,V> exte
2622                  if (init)
2623                      break;
2624              }
2625 <            else if (U.compareAndSwapLong(this, BASECOUNT, v = baseCount, v + x))
2625 >            else if (U.compareAndSetLong(this, BASECOUNT, v = baseCount, v + x))
2626                  break;                          // Fall back on using base
2627          }
2628      }
# Line 2821 | Line 2818 | public class ConcurrentHashMap<K,V> exte
2818           * Acquires write lock for tree restructuring.
2819           */
2820          private final void lockRoot() {
2821 <            if (!U.compareAndSwapInt(this, LOCKSTATE, 0, WRITER))
2821 >            if (!U.compareAndSetInt(this, LOCKSTATE, 0, WRITER))
2822                  contendedLock(); // offload to separate method
2823          }
2824  
# Line 2839 | Line 2836 | public class ConcurrentHashMap<K,V> exte
2836              boolean waiting = false;
2837              for (int s;;) {
2838                  if (((s = lockState) & ~WAITER) == 0) {
2839 <                    if (U.compareAndSwapInt(this, LOCKSTATE, s, WRITER)) {
2839 >                    if (U.compareAndSetInt(this, LOCKSTATE, s, WRITER)) {
2840                          if (waiting)
2841                              waiter = null;
2842                          return;
2843                      }
2844                  }
2845                  else if ((s & WAITER) == 0) {
2846 <                    if (U.compareAndSwapInt(this, LOCKSTATE, s, s | WAITER)) {
2846 >                    if (U.compareAndSetInt(this, LOCKSTATE, s, s | WAITER)) {
2847                          waiting = true;
2848                          waiter = Thread.currentThread();
2849                      }
# Line 2871 | Line 2868 | public class ConcurrentHashMap<K,V> exte
2868                              return e;
2869                          e = e.next;
2870                      }
2871 <                    else if (U.compareAndSwapInt(this, LOCKSTATE, s,
2871 >                    else if (U.compareAndSetInt(this, LOCKSTATE, s,
2872                                                   s + READER)) {
2873                          TreeNode<K,V> r, p;
2874                          try {
# Line 3268 | Line 3265 | public class ConcurrentHashMap<K,V> exte
3265              return true;
3266          }
3267  
3268 <        private static final Unsafe U = Unsafe.getUnsafe();
3269 <        private static final long LOCKSTATE;
3273 <        static {
3274 <            try {
3275 <                LOCKSTATE = U.objectFieldOffset
3276 <                    (TreeBin.class.getDeclaredField("lockState"));
3277 <            } catch (ReflectiveOperationException e) {
3278 <                throw new Error(e);
3279 <            }
3280 <        }
3268 >        private static final long LOCKSTATE
3269 >            = U.objectFieldOffset(TreeBin.class, "lockState");
3270      }
3271  
3272      /* ----------------Table Traversal -------------- */
# Line 3431 | Line 3420 | public class ConcurrentHashMap<K,V> exte
3420  
3421      static final class KeyIterator<K,V> extends BaseIterator<K,V>
3422          implements Iterator<K>, Enumeration<K> {
3423 <        KeyIterator(Node<K,V>[] tab, int index, int size, int limit,
3423 >        KeyIterator(Node<K,V>[] tab, int size, int index, int limit,
3424                      ConcurrentHashMap<K,V> map) {
3425 <            super(tab, index, size, limit, map);
3425 >            super(tab, size, index, limit, map);
3426          }
3427  
3428          public final K next() {
# Line 3451 | Line 3440 | public class ConcurrentHashMap<K,V> exte
3440  
3441      static final class ValueIterator<K,V> extends BaseIterator<K,V>
3442          implements Iterator<V>, Enumeration<V> {
3443 <        ValueIterator(Node<K,V>[] tab, int index, int size, int limit,
3443 >        ValueIterator(Node<K,V>[] tab, int size, int index, int limit,
3444                        ConcurrentHashMap<K,V> map) {
3445 <            super(tab, index, size, limit, map);
3445 >            super(tab, size, index, limit, map);
3446          }
3447  
3448          public final V next() {
# Line 3471 | Line 3460 | public class ConcurrentHashMap<K,V> exte
3460  
3461      static final class EntryIterator<K,V> extends BaseIterator<K,V>
3462          implements Iterator<Map.Entry<K,V>> {
3463 <        EntryIterator(Node<K,V>[] tab, int index, int size, int limit,
3463 >        EntryIterator(Node<K,V>[] tab, int size, int index, int limit,
3464                        ConcurrentHashMap<K,V> map) {
3465 <            super(tab, index, size, limit, map);
3465 >            super(tab, size, index, limit, map);
3466          }
3467  
3468          public final Map.Entry<K,V> next() {
# Line 4524 | Line 4513 | public class ConcurrentHashMap<K,V> exte
4513              return true;
4514          }
4515  
4516 <        public final boolean removeAll(Collection<?> c) {
4516 >        public boolean removeAll(Collection<?> c) {
4517              if (c == null) throw new NullPointerException();
4518              boolean modified = false;
4519 <            for (Iterator<E> it = iterator(); it.hasNext();) {
4520 <                if (c.contains(it.next())) {
4521 <                    it.remove();
4522 <                    modified = true;
4519 >            // Use (c instanceof Set) as a hint that lookup in c is as
4520 >            // efficient as this view
4521 >            Node<K,V>[] t;
4522 >            if ((t = map.table) == null) {
4523 >                return false;
4524 >            } else if (c instanceof Set<?> && c.size() > t.length) {
4525 >                for (Iterator<?> it = iterator(); it.hasNext(); ) {
4526 >                    if (c.contains(it.next())) {
4527 >                        it.remove();
4528 >                        modified = true;
4529 >                    }
4530                  }
4531 +            } else {
4532 +                for (Object e : c)
4533 +                    modified |= remove(e);
4534              }
4535              return modified;
4536          }
# Line 4564 | Line 4563 | public class ConcurrentHashMap<K,V> exte
4563      public static class KeySetView<K,V> extends CollectionView<K,V,K>
4564          implements Set<K>, java.io.Serializable {
4565          private static final long serialVersionUID = 7249069246763182397L;
4566 +        @SuppressWarnings("serial") // Conditionally serializable
4567          private final V value;
4568          KeySetView(ConcurrentHashMap<K,V> map, V value) {  // non-public
4569              super(map);
# Line 4718 | Line 4718 | public class ConcurrentHashMap<K,V> exte
4718              throw new UnsupportedOperationException();
4719          }
4720  
4721 +        @Override public boolean removeAll(Collection<?> c) {
4722 +            if (c == null) throw new NullPointerException();
4723 +            boolean modified = false;
4724 +            for (Iterator<V> it = iterator(); it.hasNext();) {
4725 +                if (c.contains(it.next())) {
4726 +                    it.remove();
4727 +                    modified = true;
4728 +                }
4729 +            }
4730 +            return modified;
4731 +        }
4732 +
4733          public boolean removeIf(Predicate<? super V> filter) {
4734              return map.removeValueIf(filter);
4735          }
# Line 6312 | Line 6324 | public class ConcurrentHashMap<K,V> exte
6324  
6325      // Unsafe mechanics
6326      private static final Unsafe U = Unsafe.getUnsafe();
6327 <    private static final long SIZECTL;
6328 <    private static final long TRANSFERINDEX;
6329 <    private static final long BASECOUNT;
6330 <    private static final long CELLSBUSY;
6331 <    private static final long CELLVALUE;
6332 <    private static final int ABASE;
6327 >    private static final long SIZECTL
6328 >        = U.objectFieldOffset(ConcurrentHashMap.class, "sizeCtl");
6329 >    private static final long TRANSFERINDEX
6330 >        = U.objectFieldOffset(ConcurrentHashMap.class, "transferIndex");
6331 >    private static final long BASECOUNT
6332 >        = U.objectFieldOffset(ConcurrentHashMap.class, "baseCount");
6333 >    private static final long CELLSBUSY
6334 >        = U.objectFieldOffset(ConcurrentHashMap.class, "cellsBusy");
6335 >    private static final long CELLVALUE
6336 >        = U.objectFieldOffset(CounterCell.class, "value");
6337 >    private static final int ABASE = U.arrayBaseOffset(Node[].class);
6338      private static final int ASHIFT;
6339  
6340      static {
6341 <        try {
6342 <            SIZECTL = U.objectFieldOffset
6343 <                (ConcurrentHashMap.class.getDeclaredField("sizeCtl"));
6344 <            TRANSFERINDEX = U.objectFieldOffset
6328 <                (ConcurrentHashMap.class.getDeclaredField("transferIndex"));
6329 <            BASECOUNT = U.objectFieldOffset
6330 <                (ConcurrentHashMap.class.getDeclaredField("baseCount"));
6331 <            CELLSBUSY = U.objectFieldOffset
6332 <                (ConcurrentHashMap.class.getDeclaredField("cellsBusy"));
6333 <
6334 <            CELLVALUE = U.objectFieldOffset
6335 <                (CounterCell.class.getDeclaredField("value"));
6336 <
6337 <            ABASE = U.arrayBaseOffset(Node[].class);
6338 <            int scale = U.arrayIndexScale(Node[].class);
6339 <            if ((scale & (scale - 1)) != 0)
6340 <                throw new Error("array index scale not a power of two");
6341 <            ASHIFT = 31 - Integer.numberOfLeadingZeros(scale);
6342 <        } catch (ReflectiveOperationException e) {
6343 <            throw new Error(e);
6344 <        }
6341 >        int scale = U.arrayIndexScale(Node[].class);
6342 >        if ((scale & (scale - 1)) != 0)
6343 >            throw new ExceptionInInitializerError("array index scale not a power of two");
6344 >        ASHIFT = 31 - Integer.numberOfLeadingZeros(scale);
6345  
6346          // Reduce the risk of rare disastrous classloading in first call to
6347          // LockSupport.park: https://bugs.openjdk.java.net/browse/JDK-8074773
6348          Class<?> ensureLoaded = LockSupport.class;
6349 +
6350 +        // Eager class load observed to help JIT during startup
6351 +        ensureLoaded = ReservationNode.class;
6352      }
6353   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines