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.278 by jsr166, Sat Sep 12 21:55:08 2015 UTC vs.
Revision 1.291 by jsr166, Tue Apr 19 22:55:29 2016 UTC

# Line 133 | Line 133 | import java.util.stream.Stream;
133   * setValue}.
134   *
135   * <ul>
136 < * <li> forEach: Perform a given action on each element.
136 > * <li>forEach: Performs a given action on each element.
137   * A variant form applies a given transformation on each element
138 < * before performing the action.</li>
138 > * before performing the action.
139   *
140 < * <li> search: Return the first available non-null result of
140 > * <li>search: Returns the first available non-null result of
141   * applying a given function on each element; skipping further
142 < * search when a result is found.</li>
142 > * search when a result is found.
143   *
144 < * <li> reduce: Accumulate each element.  The supplied reduction
144 > * <li>reduce: Accumulates each element.  The supplied reduction
145   * function cannot rely on ordering (more formally, it should be
146   * both associative and commutative).  There are five variants:
147   *
148   * <ul>
149   *
150 < * <li> Plain reductions. (There is not a form of this method for
150 > * <li>Plain reductions. (There is not a form of this method for
151   * (key, value) function arguments since there is no corresponding
152 < * return type.)</li>
152 > * return type.)
153   *
154 < * <li> Mapped reductions that accumulate the results of a given
155 < * function applied to each element.</li>
154 > * <li>Mapped reductions that accumulate the results of a given
155 > * function applied to each element.
156   *
157 < * <li> Reductions to scalar doubles, longs, and ints, using a
158 < * given basis value.</li>
157 > * <li>Reductions to scalar doubles, longs, and ints, using a
158 > * given basis value.
159   *
160   * </ul>
161 * </li>
161   * </ul>
162   *
163   * <p>These bulk operations accept a {@code parallelismThreshold}
# Line 269 | Line 268 | public class ConcurrentHashMap<K,V> exte
268       * Table accesses require volatile/atomic reads, writes, and
269       * CASes.  Because there is no other way to arrange this without
270       * adding further indirections, we use intrinsics
271 <     * (sun.misc.Unsafe) operations.
271 >     * (jdk.internal.misc.Unsafe) operations.
272       *
273       * We use the top (sign) bit of Node hash fields for control
274       * purposes -- it is available anyway because of addressing
# Line 544 | Line 543 | public class ConcurrentHashMap<K,V> exte
543       * The number of bits used for generation stamp in sizeCtl.
544       * Must be at least 6 for 32bit arrays.
545       */
546 <    private static int RESIZE_STAMP_BITS = 16;
546 >    private static final int RESIZE_STAMP_BITS = 16;
547  
548      /**
549       * The maximum number of threads that can help resize.
# Line 568 | Line 567 | public class ConcurrentHashMap<K,V> exte
567      /** Number of CPUS, to place bounds on some sizings */
568      static final int NCPU = Runtime.getRuntime().availableProcessors();
569  
570 <    /** For serialization compatibility. */
570 >    /**
571 >     * Serialized pseudo-fields, provided only for jdk7 compatibility.
572 >     * @serialField segments Segment[]
573 >     *   The segments, each of which is a specialized hash table.
574 >     * @serialField segmentMask int
575 >     *   Mask value for indexing into segments. The upper bits of a
576 >     *   key's hash code are used to choose the segment.
577 >     * @serialField segmentShift int
578 >     *   Shift value for indexing within segments.
579 >     */
580      private static final ObjectStreamField[] serialPersistentFields = {
581          new ObjectStreamField("segments", Segment[].class),
582          new ObjectStreamField("segmentMask", Integer.TYPE),
583 <        new ObjectStreamField("segmentShift", Integer.TYPE)
583 >        new ObjectStreamField("segmentShift", Integer.TYPE),
584      };
585  
586      /* ---------------- Nodes -------------- */
# Line 591 | Line 599 | public class ConcurrentHashMap<K,V> exte
599          volatile V val;
600          volatile Node<K,V> next;
601  
602 <        Node(int hash, K key, V val, Node<K,V> next) {
602 >        Node(int hash, K key, V val) {
603              this.hash = hash;
604              this.key = key;
605              this.val = val;
606 +        }
607 +
608 +        Node(int hash, K key, V val, Node<K,V> next) {
609 +            this(hash, key, val);
610              this.next = next;
611          }
612  
# Line 987 | Line 999 | public class ConcurrentHashMap<K,V> exte
999              if (tab == null || (n = tab.length) == 0)
1000                  tab = initTable();
1001              else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) {
1002 <                if (casTabAt(tab, i, null,
991 <                             new Node<K,V>(hash, key, value, null)))
1002 >                if (casTabAt(tab, i, null, new Node<K,V>(hash, key, value)))
1003                      break;                   // no lock when adding to empty bin
1004              }
1005              else if ((fh = f.hash) == MOVED)
# Line 1011 | Line 1022 | public class ConcurrentHashMap<K,V> exte
1022                                  }
1023                                  Node<K,V> pred = e;
1024                                  if ((e = e.next) == null) {
1025 <                                    pred.next = new Node<K,V>(hash, key,
1015 <                                                              value, null);
1025 >                                    pred.next = new Node<K,V>(hash, key, value);
1026                                      break;
1027                                  }
1028                              }
# Line 1340 | Line 1350 | public class ConcurrentHashMap<K,V> exte
1350  
1351      /**
1352       * Stripped-down version of helper class used in previous version,
1353 <     * declared for the sake of serialization compatibility
1353 >     * declared for the sake of serialization compatibility.
1354       */
1355      static class Segment<K,V> extends ReentrantLock implements Serializable {
1356          private static final long serialVersionUID = 2249069246763182397L;
# Line 1354 | Line 1364 | public class ConcurrentHashMap<K,V> exte
1364       * @param s the stream
1365       * @throws java.io.IOException if an I/O error occurs
1366       * @serialData
1367 <     * the key (Object) and value (Object)
1368 <     * for each key-value mapping, followed by a null pair.
1367 >     * the serialized fields, followed by the key (Object) and value
1368 >     * (Object) for each key-value mapping, followed by a null pair.
1369       * The key-value mappings are emitted in no particular order.
1370       */
1371      private void writeObject(java.io.ObjectOutputStream s)
# Line 1391 | Line 1401 | public class ConcurrentHashMap<K,V> exte
1401          }
1402          s.writeObject(null);
1403          s.writeObject(null);
1394        segments = null; // throw away
1404      }
1405  
1406      /**
# Line 1595 | Line 1604 | public class ConcurrentHashMap<K,V> exte
1604      }
1605  
1606      /**
1607 <     * Helper method for EntrySetView.removeIf
1607 >     * Helper method for EntrySetView.removeIf.
1608       */
1609      boolean removeEntryIf(Predicate<? super Entry<K,V>> function) {
1610          if (function == null) throw new NullPointerException();
# Line 1615 | Line 1624 | public class ConcurrentHashMap<K,V> exte
1624      }
1625  
1626      /**
1627 <     * Helper method for ValuesView.removeIf
1627 >     * Helper method for ValuesView.removeIf.
1628       */
1629      boolean removeValueIf(Predicate<? super V> function) {
1630          if (function == null) throw new NullPointerException();
# Line 1673 | Line 1682 | public class ConcurrentHashMap<K,V> exte
1682                          Node<K,V> node = null;
1683                          try {
1684                              if ((val = mappingFunction.apply(key)) != null)
1685 <                                node = new Node<K,V>(h, key, val, null);
1685 >                                node = new Node<K,V>(h, key, val);
1686                          } finally {
1687                              setTabAt(tab, i, node);
1688                          }
# Line 1704 | Line 1713 | public class ConcurrentHashMap<K,V> exte
1713                                          if (pred.next != null)
1714                                              throw new IllegalStateException("Recursive update");
1715                                          added = true;
1716 <                                        pred.next = new Node<K,V>(h, key, val, null);
1716 >                                        pred.next = new Node<K,V>(h, key, val);
1717                                      }
1718                                      break;
1719                                  }
# Line 1873 | Line 1882 | public class ConcurrentHashMap<K,V> exte
1882                          try {
1883                              if ((val = remappingFunction.apply(key, null)) != null) {
1884                                  delta = 1;
1885 <                                node = new Node<K,V>(h, key, val, null);
1885 >                                node = new Node<K,V>(h, key, val);
1886                              }
1887                          } finally {
1888                              setTabAt(tab, i, node);
# Line 1915 | Line 1924 | public class ConcurrentHashMap<K,V> exte
1924                                          if (pred.next != null)
1925                                              throw new IllegalStateException("Recursive update");
1926                                          delta = 1;
1927 <                                        pred.next =
1919 <                                            new Node<K,V>(h, key, val, null);
1927 >                                        pred.next = new Node<K,V>(h, key, val);
1928                                      }
1929                                      break;
1930                                  }
# Line 1994 | Line 2002 | public class ConcurrentHashMap<K,V> exte
2002              if (tab == null || (n = tab.length) == 0)
2003                  tab = initTable();
2004              else if ((f = tabAt(tab, i = (n - 1) & h)) == null) {
2005 <                if (casTabAt(tab, i, null, new Node<K,V>(h, key, value, null))) {
2005 >                if (casTabAt(tab, i, null, new Node<K,V>(h, key, value))) {
2006                      delta = 1;
2007                      val = value;
2008                      break;
# Line 2029 | Line 2037 | public class ConcurrentHashMap<K,V> exte
2037                                  if ((e = e.next) == null) {
2038                                      delta = 1;
2039                                      val = value;
2040 <                                    pred.next =
2033 <                                        new Node<K,V>(h, key, val, null);
2040 >                                    pred.next = new Node<K,V>(h, key, val);
2041                                      break;
2042                                  }
2043                              }
# Line 2081 | Line 2088 | public class ConcurrentHashMap<K,V> exte
2088       * <p>Note that this method is identical in functionality to
2089       * {@link #containsValue(Object)}, and exists solely to ensure
2090       * full compatibility with class {@link java.util.Hashtable},
2091 <     * which supported this method prior to introduction of the Java
2092 <     * Collections Framework.
2091 >     * which supported this method prior to introduction of the
2092 >     * Java Collections Framework.
2093       *
2094       * @param  value a value to search for
2095       * @return {@code true} if and only if some key maps to the
# Line 2191 | Line 2198 | public class ConcurrentHashMap<K,V> exte
2198      static final class ForwardingNode<K,V> extends Node<K,V> {
2199          final Node<K,V>[] nextTable;
2200          ForwardingNode(Node<K,V>[] tab) {
2201 <            super(MOVED, null, null, null);
2201 >            super(MOVED, null, null);
2202              this.nextTable = tab;
2203          }
2204  
# Line 2223 | Line 2230 | public class ConcurrentHashMap<K,V> exte
2230      }
2231  
2232      /**
2233 <     * A place-holder node used in computeIfAbsent and compute
2233 >     * A place-holder node used in computeIfAbsent and compute.
2234       */
2235      static final class ReservationNode<K,V> extends Node<K,V> {
2236          ReservationNode() {
2237 <            super(RESERVED, null, null, null);
2237 >            super(RESERVED, null, null);
2238          }
2239  
2240          Node<K,V> find(int h, Object k) {
# Line 2522 | Line 2529 | public class ConcurrentHashMap<K,V> exte
2529       * A padded cell for distributing counts.  Adapted from LongAdder
2530       * and Striped64.  See their internal docs for explanation.
2531       */
2532 <    @sun.misc.Contended static final class CounterCell {
2532 >    @jdk.internal.vm.annotation.Contended static final class CounterCell {
2533          volatile long value;
2534          CounterCell(long x) { value = x; }
2535      }
# Line 2654 | Line 2661 | public class ConcurrentHashMap<K,V> exte
2661      }
2662  
2663      /**
2664 <     * Returns a list on non-TreeNodes replacing those in given list.
2664 >     * Returns a list of non-TreeNodes replacing those in given list.
2665       */
2666      static <K,V> Node<K,V> untreeify(Node<K,V> b) {
2667          Node<K,V> hd = null, tl = null;
2668          for (Node<K,V> q = b; q != null; q = q.next) {
2669 <            Node<K,V> p = new Node<K,V>(q.hash, q.key, q.val, null);
2669 >            Node<K,V> p = new Node<K,V>(q.hash, q.key, q.val);
2670              if (tl == null)
2671                  hd = p;
2672              else
# Line 2672 | Line 2679 | public class ConcurrentHashMap<K,V> exte
2679      /* ---------------- TreeNodes -------------- */
2680  
2681      /**
2682 <     * Nodes for use in TreeBins
2682 >     * Nodes for use in TreeBins.
2683       */
2684      static final class TreeNode<K,V> extends Node<K,V> {
2685          TreeNode<K,V> parent;  // red-black tree links
# Line 2765 | Line 2772 | public class ConcurrentHashMap<K,V> exte
2772           * Creates bin with initial set of nodes headed by b.
2773           */
2774          TreeBin(TreeNode<K,V> b) {
2775 <            super(TREEBIN, null, null, null);
2775 >            super(TREEBIN, null, null);
2776              this.first = b;
2777              TreeNode<K,V> r = null;
2778              for (TreeNode<K,V> x = b, next; x != null; x = next) {
# Line 3235 | Line 3242 | public class ConcurrentHashMap<K,V> exte
3242          }
3243  
3244          /**
3245 <         * Recursive invariant check
3245 >         * Checks invariants recursively for the tree of Nodes rooted at t.
3246           */
3247          static <K,V> boolean checkInvariants(TreeNode<K,V> t) {
3248              TreeNode<K,V> tp = t.parent, tl = t.left, tr = t.right,
# Line 3259 | Line 3266 | public class ConcurrentHashMap<K,V> exte
3266              return true;
3267          }
3268  
3269 <        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
3269 >        private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
3270          private static final long LOCKSTATE;
3271          static {
3272              try {
# Line 3480 | Line 3487 | public class ConcurrentHashMap<K,V> exte
3487      }
3488  
3489      /**
3490 <     * Exported Entry for EntryIterator
3490 >     * Exported Entry for EntryIterator.
3491       */
3492      static final class MapEntry<K,V> implements Map.Entry<K,V> {
3493          final K key; // non-null
# Line 3533 | Line 3540 | public class ConcurrentHashMap<K,V> exte
3540              this.est = est;
3541          }
3542  
3543 <        public Spliterator<K> trySplit() {
3543 >        public KeySpliterator<K,V> trySplit() {
3544              int i, f, h;
3545              return (h = ((i = baseIndex) + (f = baseLimit)) >>> 1) <= i ? null :
3546                  new KeySpliterator<K,V>(tab, baseSize, baseLimit = h,
# Line 3572 | Line 3579 | public class ConcurrentHashMap<K,V> exte
3579              this.est = est;
3580          }
3581  
3582 <        public Spliterator<V> trySplit() {
3582 >        public ValueSpliterator<K,V> trySplit() {
3583              int i, f, h;
3584              return (h = ((i = baseIndex) + (f = baseLimit)) >>> 1) <= i ? null :
3585                  new ValueSpliterator<K,V>(tab, baseSize, baseLimit = h,
# Line 3612 | Line 3619 | public class ConcurrentHashMap<K,V> exte
3619              this.est = est;
3620          }
3621  
3622 <        public Spliterator<Map.Entry<K,V>> trySplit() {
3622 >        public EntrySpliterator<K,V> trySplit() {
3623              int i, f, h;
3624              return (h = ((i = baseIndex) + (f = baseLimit)) >>> 1) <= i ? null :
3625                  new EntrySpliterator<K,V>(tab, baseSize, baseLimit = h,
# Line 4424 | Line 4431 | public class ConcurrentHashMap<K,V> exte
4431          public abstract boolean contains(Object o);
4432          public abstract boolean remove(Object o);
4433  
4434 <        private static final String oomeMsg = "Required array size too large";
4434 >        private static final String OOME_MSG = "Required array size too large";
4435  
4436          public final Object[] toArray() {
4437              long sz = map.mappingCount();
4438              if (sz > MAX_ARRAY_SIZE)
4439 <                throw new OutOfMemoryError(oomeMsg);
4439 >                throw new OutOfMemoryError(OOME_MSG);
4440              int n = (int)sz;
4441              Object[] r = new Object[n];
4442              int i = 0;
4443              for (E e : this) {
4444                  if (i == n) {
4445                      if (n >= MAX_ARRAY_SIZE)
4446 <                        throw new OutOfMemoryError(oomeMsg);
4446 >                        throw new OutOfMemoryError(OOME_MSG);
4447                      if (n >= MAX_ARRAY_SIZE - (MAX_ARRAY_SIZE >>> 1) - 1)
4448                          n = MAX_ARRAY_SIZE;
4449                      else
# Line 4452 | Line 4459 | public class ConcurrentHashMap<K,V> exte
4459          public final <T> T[] toArray(T[] a) {
4460              long sz = map.mappingCount();
4461              if (sz > MAX_ARRAY_SIZE)
4462 <                throw new OutOfMemoryError(oomeMsg);
4462 >                throw new OutOfMemoryError(OOME_MSG);
4463              int m = (int)sz;
4464              T[] r = (a.length >= m) ? a :
4465                  (T[])java.lang.reflect.Array
# Line 4462 | Line 4469 | public class ConcurrentHashMap<K,V> exte
4469              for (E e : this) {
4470                  if (i == n) {
4471                      if (n >= MAX_ARRAY_SIZE)
4472 <                        throw new OutOfMemoryError(oomeMsg);
4472 >                        throw new OutOfMemoryError(OOME_MSG);
4473                      if (n >= MAX_ARRAY_SIZE - (MAX_ARRAY_SIZE >>> 1) - 1)
4474                          n = MAX_ARRAY_SIZE;
4475                      else
# Line 4857 | Line 4864 | public class ConcurrentHashMap<K,V> exte
4864          }
4865  
4866          /**
4867 <         * Same as Traverser version
4867 >         * Same as Traverser version.
4868           */
4869          final Node<K,V> advance() {
4870              Node<K,V> e;
# Line 6302 | Line 6309 | public class ConcurrentHashMap<K,V> exte
6309      }
6310  
6311      // Unsafe mechanics
6312 <    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
6312 >    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
6313      private static final long SIZECTL;
6314      private static final long TRANSFERINDEX;
6315      private static final long BASECOUNT;

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines