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.299 by jsr166, Sat Mar 18 19:19:04 2017 UTC vs.
Revision 1.308 by jsr166, Mon Mar 12 03:29:09 2018 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/util/package-summary.html#CollectionsFramework">
228   * Java Collections Framework</a>.
229   *
230   * @since 1.5
# Line 689 | Line 688 | public class ConcurrentHashMap<K,V> exte
688       */
689      static Class<?> comparableClassFor(Object x) {
690          if (x instanceof Comparable) {
691 <            Class<?> c; Type[] ts, as; Type t; ParameterizedType p;
691 >            Class<?> c; Type[] ts, as; ParameterizedType p;
692              if ((c = x.getClass()) == String.class) // bypass checks
693                  return c;
694              if ((ts = c.getGenericInterfaces()) != null) {
695 <                for (int i = 0; i < ts.length; ++i) {
696 <                    if (((t = ts[i]) instanceof ParameterizedType) &&
695 >                for (Type t : ts) {
696 >                    if ((t instanceof ParameterizedType) &&
697                          ((p = (ParameterizedType)t).getRawType() ==
698                           Comparable.class) &&
699                          (as = p.getActualTypeArguments()) != null &&
# Line 739 | Line 738 | public class ConcurrentHashMap<K,V> exte
738  
739      static final <K,V> boolean casTabAt(Node<K,V>[] tab, int i,
740                                          Node<K,V> c, Node<K,V> v) {
741 <        return U.compareAndSwapObject(tab, ((long)i << ASHIFT) + ABASE, c, v);
741 >        return U.compareAndSetObject(tab, ((long)i << ASHIFT) + ABASE, c, v);
742      }
743  
744      static final <K,V> void setTabAt(Node<K,V>[] tab, int i, Node<K,V> v) {
# Line 1366 | Line 1365 | public class ConcurrentHashMap<K,V> exte
1365      }
1366  
1367      /**
1368 <     * Saves the state of the {@code ConcurrentHashMap} instance to a
1369 <     * stream (i.e., serializes it).
1368 >     * Saves this map to a stream (that is, serializes it).
1369 >     *
1370       * @param s the stream
1371       * @throws java.io.IOException if an I/O error occurs
1372       * @serialData
# Line 1411 | Line 1410 | public class ConcurrentHashMap<K,V> exte
1410      }
1411  
1412      /**
1413 <     * Reconstitutes the instance from a stream (that is, deserializes it).
1413 >     * Reconstitutes this map from a stream (that is, deserializes it).
1414       * @param s the stream
1415       * @throws ClassNotFoundException if the class of a serialized object
1416       *         could not be found
# Line 2271 | Line 2270 | public class ConcurrentHashMap<K,V> exte
2270          while ((tab = table) == null || tab.length == 0) {
2271              if ((sc = sizeCtl) < 0)
2272                  Thread.yield(); // lost initialization race; just spin
2273 <            else if (U.compareAndSwapInt(this, SIZECTL, sc, -1)) {
2273 >            else if (U.compareAndSetInt(this, SIZECTL, sc, -1)) {
2274                  try {
2275                      if ((tab = table) == null || tab.length == 0) {
2276                          int n = (sc > 0) ? sc : DEFAULT_CAPACITY;
# Line 2300 | Line 2299 | public class ConcurrentHashMap<K,V> exte
2299       * @param check if <0, don't check resize, if <= 1 only check if uncontended
2300       */
2301      private final void addCount(long x, int check) {
2302 <        CounterCell[] as; long b, s;
2303 <        if ((as = counterCells) != null ||
2304 <            !U.compareAndSwapLong(this, BASECOUNT, b = baseCount, s = b + x)) {
2305 <            CounterCell a; long v; int m;
2302 >        CounterCell[] cs; long b, s;
2303 >        if ((cs = counterCells) != null ||
2304 >            !U.compareAndSetLong(this, BASECOUNT, b = baseCount, s = b + x)) {
2305 >            CounterCell c; long v; int m;
2306              boolean uncontended = true;
2307 <            if (as == null || (m = as.length - 1) < 0 ||
2308 <                (a = as[ThreadLocalRandom.getProbe() & m]) == null ||
2307 >            if (cs == null || (m = cs.length - 1) < 0 ||
2308 >                (c = cs[ThreadLocalRandom.getProbe() & m]) == null ||
2309                  !(uncontended =
2310 <                  U.compareAndSwapLong(a, CELLVALUE, v = a.value, v + x))) {
2310 >                  U.compareAndSetLong(c, CELLVALUE, v = c.value, v + x))) {
2311                  fullAddCount(x, uncontended);
2312                  return;
2313              }
# Line 2326 | Line 2325 | public class ConcurrentHashMap<K,V> exte
2325                          sc == rs + MAX_RESIZERS || (nt = nextTable) == null ||
2326                          transferIndex <= 0)
2327                          break;
2328 <                    if (U.compareAndSwapInt(this, SIZECTL, sc, sc + 1))
2328 >                    if (U.compareAndSetInt(this, SIZECTL, sc, sc + 1))
2329                          transfer(tab, nt);
2330                  }
2331 <                else if (U.compareAndSwapInt(this, SIZECTL, sc,
2331 >                else if (U.compareAndSetInt(this, SIZECTL, sc,
2332                                               (rs << RESIZE_STAMP_SHIFT) + 2))
2333                      transfer(tab, null);
2334                  s = sumCount();
# Line 2350 | Line 2349 | public class ConcurrentHashMap<K,V> exte
2349                  if ((sc >>> RESIZE_STAMP_SHIFT) != rs || sc == rs + 1 ||
2350                      sc == rs + MAX_RESIZERS || transferIndex <= 0)
2351                      break;
2352 <                if (U.compareAndSwapInt(this, SIZECTL, sc, sc + 1)) {
2352 >                if (U.compareAndSetInt(this, SIZECTL, sc, sc + 1)) {
2353                      transfer(tab, nextTab);
2354                      break;
2355                  }
# Line 2373 | Line 2372 | public class ConcurrentHashMap<K,V> exte
2372              Node<K,V>[] tab = table; int n;
2373              if (tab == null || (n = tab.length) == 0) {
2374                  n = (sc > c) ? sc : c;
2375 <                if (U.compareAndSwapInt(this, SIZECTL, sc, -1)) {
2375 >                if (U.compareAndSetInt(this, SIZECTL, sc, -1)) {
2376                      try {
2377                          if (table == tab) {
2378                              @SuppressWarnings("unchecked")
# Line 2390 | Line 2389 | public class ConcurrentHashMap<K,V> exte
2389                  break;
2390              else if (tab == table) {
2391                  int rs = resizeStamp(n);
2392 <                if (U.compareAndSwapInt(this, SIZECTL, sc,
2392 >                if (U.compareAndSetInt(this, SIZECTL, sc,
2393                                          (rs << RESIZE_STAMP_SHIFT) + 2))
2394                      transfer(tab, null);
2395              }
# Line 2431 | Line 2430 | public class ConcurrentHashMap<K,V> exte
2430                      i = -1;
2431                      advance = false;
2432                  }
2433 <                else if (U.compareAndSwapInt
2433 >                else if (U.compareAndSetInt
2434                           (this, TRANSFERINDEX, nextIndex,
2435                            nextBound = (nextIndex > stride ?
2436                                         nextIndex - stride : 0))) {
# Line 2448 | Line 2447 | public class ConcurrentHashMap<K,V> exte
2447                      sizeCtl = (n << 1) - (n >>> 1);
2448                      return;
2449                  }
2450 <                if (U.compareAndSwapInt(this, SIZECTL, sc = sizeCtl, sc - 1)) {
2450 >                if (U.compareAndSetInt(this, SIZECTL, sc = sizeCtl, sc - 1)) {
2451                      if ((sc - 2) != resizeStamp(n) << RESIZE_STAMP_SHIFT)
2452                          return;
2453                      finishing = advance = true;
# Line 2546 | Line 2545 | public class ConcurrentHashMap<K,V> exte
2545      }
2546  
2547      final long sumCount() {
2548 <        CounterCell[] as = counterCells; CounterCell a;
2548 >        CounterCell[] cs = counterCells;
2549          long sum = baseCount;
2550 <        if (as != null) {
2551 <            for (int i = 0; i < as.length; ++i) {
2552 <                if ((a = as[i]) != null)
2553 <                    sum += a.value;
2555 <            }
2550 >        if (cs != null) {
2551 >            for (CounterCell c : cs)
2552 >                if (c != null)
2553 >                    sum += c.value;
2554          }
2555          return sum;
2556      }
# Line 2567 | Line 2565 | public class ConcurrentHashMap<K,V> exte
2565          }
2566          boolean collide = false;                // True if last slot nonempty
2567          for (;;) {
2568 <            CounterCell[] as; CounterCell a; int n; long v;
2569 <            if ((as = counterCells) != null && (n = as.length) > 0) {
2570 <                if ((a = as[(n - 1) & h]) == null) {
2568 >            CounterCell[] cs; CounterCell c; int n; long v;
2569 >            if ((cs = counterCells) != null && (n = cs.length) > 0) {
2570 >                if ((c = cs[(n - 1) & h]) == null) {
2571                      if (cellsBusy == 0) {            // Try to attach new Cell
2572                          CounterCell r = new CounterCell(x); // Optimistic create
2573                          if (cellsBusy == 0 &&
2574 <                            U.compareAndSwapInt(this, CELLSBUSY, 0, 1)) {
2574 >                            U.compareAndSetInt(this, CELLSBUSY, 0, 1)) {
2575                              boolean created = false;
2576                              try {               // Recheck under lock
2577                                  CounterCell[] rs; int m, j;
# Line 2595 | Line 2593 | public class ConcurrentHashMap<K,V> exte
2593                  }
2594                  else if (!wasUncontended)       // CAS already known to fail
2595                      wasUncontended = true;      // Continue after rehash
2596 <                else if (U.compareAndSwapLong(a, CELLVALUE, v = a.value, v + x))
2596 >                else if (U.compareAndSetLong(c, CELLVALUE, v = c.value, v + x))
2597                      break;
2598 <                else if (counterCells != as || n >= NCPU)
2598 >                else if (counterCells != cs || n >= NCPU)
2599                      collide = false;            // At max size or stale
2600                  else if (!collide)
2601                      collide = true;
2602                  else if (cellsBusy == 0 &&
2603 <                         U.compareAndSwapInt(this, CELLSBUSY, 0, 1)) {
2603 >                         U.compareAndSetInt(this, CELLSBUSY, 0, 1)) {
2604                      try {
2605 <                        if (counterCells == as) {// Expand table unless stale
2606 <                            CounterCell[] rs = new CounterCell[n << 1];
2609 <                            for (int i = 0; i < n; ++i)
2610 <                                rs[i] = as[i];
2611 <                            counterCells = rs;
2612 <                        }
2605 >                        if (counterCells == cs) // Expand table unless stale
2606 >                            counterCells = Arrays.copyOf(cs, n << 1);
2607                      } finally {
2608                          cellsBusy = 0;
2609                      }
# Line 2618 | Line 2612 | public class ConcurrentHashMap<K,V> exte
2612                  }
2613                  h = ThreadLocalRandom.advanceProbe(h);
2614              }
2615 <            else if (cellsBusy == 0 && counterCells == as &&
2616 <                     U.compareAndSwapInt(this, CELLSBUSY, 0, 1)) {
2615 >            else if (cellsBusy == 0 && counterCells == cs &&
2616 >                     U.compareAndSetInt(this, CELLSBUSY, 0, 1)) {
2617                  boolean init = false;
2618                  try {                           // Initialize table
2619 <                    if (counterCells == as) {
2619 >                    if (counterCells == cs) {
2620                          CounterCell[] rs = new CounterCell[2];
2621                          rs[h & 1] = new CounterCell(x);
2622                          counterCells = rs;
# Line 2634 | Line 2628 | public class ConcurrentHashMap<K,V> exte
2628                  if (init)
2629                      break;
2630              }
2631 <            else if (U.compareAndSwapLong(this, BASECOUNT, v = baseCount, v + x))
2631 >            else if (U.compareAndSetLong(this, BASECOUNT, v = baseCount, v + x))
2632                  break;                          // Fall back on using base
2633          }
2634      }
# Line 2830 | Line 2824 | public class ConcurrentHashMap<K,V> exte
2824           * Acquires write lock for tree restructuring.
2825           */
2826          private final void lockRoot() {
2827 <            if (!U.compareAndSwapInt(this, LOCKSTATE, 0, WRITER))
2827 >            if (!U.compareAndSetInt(this, LOCKSTATE, 0, WRITER))
2828                  contendedLock(); // offload to separate method
2829          }
2830  
# Line 2848 | Line 2842 | public class ConcurrentHashMap<K,V> exte
2842              boolean waiting = false;
2843              for (int s;;) {
2844                  if (((s = lockState) & ~WAITER) == 0) {
2845 <                    if (U.compareAndSwapInt(this, LOCKSTATE, s, WRITER)) {
2845 >                    if (U.compareAndSetInt(this, LOCKSTATE, s, WRITER)) {
2846                          if (waiting)
2847                              waiter = null;
2848                          return;
2849                      }
2850                  }
2851                  else if ((s & WAITER) == 0) {
2852 <                    if (U.compareAndSwapInt(this, LOCKSTATE, s, s | WAITER)) {
2852 >                    if (U.compareAndSetInt(this, LOCKSTATE, s, s | WAITER)) {
2853                          waiting = true;
2854                          waiter = Thread.currentThread();
2855                      }
# Line 2880 | Line 2874 | public class ConcurrentHashMap<K,V> exte
2874                              return e;
2875                          e = e.next;
2876                      }
2877 <                    else if (U.compareAndSwapInt(this, LOCKSTATE, s,
2877 >                    else if (U.compareAndSetInt(this, LOCKSTATE, s,
2878                                                   s + READER)) {
2879                          TreeNode<K,V> r, p;
2880                          try {
# Line 3284 | Line 3278 | public class ConcurrentHashMap<K,V> exte
3278                  LOCKSTATE = U.objectFieldOffset
3279                      (TreeBin.class.getDeclaredField("lockState"));
3280              } catch (ReflectiveOperationException e) {
3281 <                throw new Error(e);
3281 >                throw new ExceptionInInitializerError(e);
3282              }
3283          }
3284      }
# Line 6368 | Line 6362 | public class ConcurrentHashMap<K,V> exte
6362              ABASE = U.arrayBaseOffset(Node[].class);
6363              int scale = U.arrayIndexScale(Node[].class);
6364              if ((scale & (scale - 1)) != 0)
6365 <                throw new Error("array index scale not a power of two");
6365 >                throw new ExceptionInInitializerError("array index scale not a power of two");
6366              ASHIFT = 31 - Integer.numberOfLeadingZeros(scale);
6367          } catch (ReflectiveOperationException e) {
6368 <            throw new Error(e);
6368 >            throw new ExceptionInInitializerError(e);
6369          }
6370  
6371          // Reduce the risk of rare disastrous classloading in first call to

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines