ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jsr166e/ConcurrentHashMapV8.java
(Generate patch)

Comparing jsr166/src/jsr166e/ConcurrentHashMapV8.java (file contents):
Revision 1.6 by jsr166, Tue Aug 30 13:30:35 2011 UTC vs.
Revision 1.26 by jsr166, Wed Sep 21 11:42:08 2011 UTC

# Line 6 | Line 6
6  
7   package jsr166e;
8   import jsr166e.LongAdder;
9 + import java.util.Arrays;
10   import java.util.Map;
11   import java.util.Set;
12   import java.util.Collection;
# Line 19 | Line 20 | import java.util.Enumeration;
20   import java.util.ConcurrentModificationException;
21   import java.util.NoSuchElementException;
22   import java.util.concurrent.ConcurrentMap;
23 + import java.util.concurrent.locks.LockSupport;
24   import java.io.Serializable;
25  
26   /**
# Line 49 | Line 51 | import java.io.Serializable;
51   * are typically useful only when a map is not undergoing concurrent
52   * updates in other threads.  Otherwise the results of these methods
53   * reflect transient states that may be adequate for monitoring
54 < * purposes, but not for program control.
54 > * or estimation purposes, but not for program control.
55   *
56 < * <p> Resizing this or any other kind of hash table is a relatively
57 < * slow operation, so, when possible, it is a good idea to provide
58 < * estimates of expected table sizes in constructors. Also, for
59 < * compatability with previous versions of this class, constructors
60 < * may optionally specify an expected {@code concurrencyLevel} as an
61 < * additional hint for internal sizing.
56 > * <p> The table is dynamically expanded when there are too many
57 > * collisions (i.e., keys that have distinct hash codes but fall into
58 > * the same slot modulo the table size), with the expected average
59 > * effect of maintaining roughly two bins per mapping (corresponding
60 > * to a 0.75 load factor threshold for resizing). There may be much
61 > * variance around this average as mappings are added and removed, but
62 > * overall, this maintains a commonly accepted time/space tradeoff for
63 > * hash tables.  However, resizing this or any other kind of hash
64 > * table may be a relatively slow operation. When possible, it is a
65 > * good idea to provide a size estimate as an optional {@code
66 > * initialCapacity} constructor argument. An additional optional
67 > * {@code loadFactor} constructor argument provides a further means of
68 > * customizing initial table capacity by specifying the table density
69 > * to be used in calculating the amount of space to allocate for the
70 > * given number of elements.  Also, for compatibility with previous
71 > * versions of this class, constructors may optionally specify an
72 > * expected {@code concurrencyLevel} as an additional hint for
73 > * internal sizing.  Note that using many keys with exactly the same
74 > * {@code hashCode{}} is a sure way to slow down performance of any
75 > * hash table.
76   *
77   * <p>This class and its views and iterators implement all of the
78   * <em>optional</em> methods of the {@link Map} and {@link Iterator}
# Line 83 | Line 99 | public class ConcurrentHashMapV8<K, V>
99  
100      /**
101       * A function computing a mapping from the given key to a value,
102 <     *  or <code>null</code> if there is no mapping. This is a
103 <     * place-holder for an upcoming JDK8 interface.
102 >     * or {@code null} if there is no mapping. This is a place-holder
103 >     * for an upcoming JDK8 interface.
104       */
105      public static interface MappingFunction<K, V> {
106          /**
# Line 108 | Line 124 | public class ConcurrentHashMapV8<K, V>
124       * The primary design goal of this hash table is to maintain
125       * concurrent readability (typically method get(), but also
126       * iterators and related methods) while minimizing update
127 <     * contention.
127 >     * contention. Secondary goals are to keep space consumption about
128 >     * the same or better than java.util.HashMap, and to support high
129 >     * initial insertion rates on an empty table by many threads.
130       *
131       * Each key-value mapping is held in a Node.  Because Node fields
132       * can contain special values, they are defined using plain Object
133       * types. Similarly in turn, all internal methods that use them
134 <     * work off Object types. All public generic-typed methods relay
135 <     * in/out of these internal methods, supplying casts as needed.
134 >     * work off Object types. And similarly, so do the internal
135 >     * methods of auxiliary iterator and view classes.  All public
136 >     * generic typed methods relay in/out of these internal methods,
137 >     * supplying null-checks and casts as needed.
138       *
139       * The table is lazily initialized to a power-of-two size upon the
140 <     * first insertion.  Each bin in the table contains a (typically
141 <     * short) list of Nodes.  Table accesses require volatile/atomic
142 <     * reads, writes, and CASes.  Because there is no other way to
143 <     * arrange this without adding further indirections, we use
144 <     * intrinsics (sun.misc.Unsafe) operations.  The lists of nodes
145 <     * within bins are always accurately traversable under volatile
146 <     * reads, so long as lookups check hash code and non-nullness of
147 <     * key and value before checking key equality. (All valid hash
148 <     * codes are nonnegative. Negative values are reserved for special
149 <     * forwarding nodes; see below.)
150 <     *
151 <     * A bin may be locked during update (insert, delete, and replace)
152 <     * operations.  We do not want to waste the space required to
153 <     * associate a distinct lock object with each bin, so instead use
154 <     * the first node of a bin list itself as a lock, using builtin
155 <     * "synchronized" locks. These save space and we can live with
156 <     * only plain block-structured lock/unlock operations. Using the
157 <     * first node of a list as a lock does not by itself suffice
158 <     * though: When a node is locked, any update must first validate
159 <     * that it is still the first node, and retry if not. (Because new
160 <     * nodes are always appended to lists, once a node is first in a
161 <     * bin, it remains first until deleted or the bin becomes
162 <     * invalidated.)  However, update operations can and usually do
163 <     * still traverse the bin until the point of update, which helps
164 <     * reduce cache misses on retries.  This is a converse of sorts to
165 <     * the lazy locking technique described by Herlihy & Shavit. If
166 <     * there is no existing node during a put operation, then one can
167 <     * be CAS'ed in (without need for lock except in computeIfAbsent);
168 <     * the CAS serves as validation. This is on average the most
169 <     * common case for put operations -- under random hash codes, the
170 <     * distribution of nodes in bins follows a Poisson distribution
171 <     * (see http://en.wikipedia.org/wiki/Poisson_distribution) with a
172 <     * parameter of 0.5 on average under the default loadFactor of
173 <     * 0.75.  The expected number of locks covering different elements
174 <     * (i.e., bins with 2 or more nodes) is approximately 10% at
175 <     * steady state under default settings.  Lock contention
176 <     * probability for two threads accessing arbitrary distinct
177 <     * elements is, roughly, 1 / (8 * #elements).
178 <     *
179 <     * The table is resized when occupancy exceeds a threshold.  Only
180 <     * a single thread performs the resize (using field "resizing", to
181 <     * arrange exclusion), but the table otherwise remains usable for
182 <     * both reads and updates. Resizing proceeds by transferring bins,
183 <     * one by one, from the table to the next table.  Upon transfer,
184 <     * the old table bin contains only a special forwarding node (with
185 <     * negative hash code ("MOVED")) that contains the next table as
140 >     * first insertion.  Each bin in the table contains a list of
141 >     * Nodes (most often, zero or one Node).  Table accesses require
142 >     * volatile/atomic reads, writes, and CASes.  Because there is no
143 >     * other way to arrange this without adding further indirections,
144 >     * we use intrinsics (sun.misc.Unsafe) operations.  The lists of
145 >     * nodes within bins are always accurately traversable under
146 >     * volatile reads, so long as lookups check hash code and
147 >     * non-nullness of value before checking key equality.
148 >     *
149 >     * We use the top two bits of Node hash fields for control
150 >     * purposes -- they are available anyway because of addressing
151 >     * constraints.  As explained further below, these top bits are
152 >     * usd as follows:
153 >     *  00 - Normal
154 >     *  01 - Locked
155 >     *  11 - Locked and may have a thread waiting for lock
156 >     *  10 - Node is a forwarding node
157 >     *
158 >     * The lower 30 bits of each Node's hash field contain a
159 >     * transformation (for better randomization -- method "spread") of
160 >     * the key's hash code, except for forwarding nodes, for which the
161 >     * lower bits are zero (and so always have hash field == "MOVED").
162 >     *
163 >     * Insertion (via put or putIfAbsent) of the first node in an
164 >     * empty bin is performed by just CASing it to the bin.  This is
165 >     * by far the most common case for put operations.  Other update
166 >     * operations (insert, delete, and replace) require locks.  We do
167 >     * not want to waste the space required to associate a distinct
168 >     * lock object with each bin, so instead use the first node of a
169 >     * bin list itself as a lock. Blocking support for these locks
170 >     * relies on the builtin "synchronized" monitors.  However, we
171 >     * also need a tryLock construction, so we overlay these by using
172 >     * bits of the Node hash field for lock control (see above), and
173 >     * so normally use builtin monitors only for blocking and
174 >     * signalling using wait/notifyAll constructions. See
175 >     * Node.tryAwaitLock.
176 >     *
177 >     * Using the first node of a list as a lock does not by itself
178 >     * suffice though: When a node is locked, any update must first
179 >     * validate that it is still the first node after locking it, and
180 >     * retry if not. Because new nodes are always appended to lists,
181 >     * once a node is first in a bin, it remains first until deleted
182 >     * or the bin becomes invalidated.  However, operations that only
183 >     * conditionally update may inspect nodes until the point of
184 >     * update. This is a converse of sorts to the lazy locking
185 >     * technique described by Herlihy & Shavit.
186 >     *
187 >     * The main disadvantage of per-bin locks is that other update
188 >     * operations on other nodes in a bin list protected by the same
189 >     * lock can stall, for example when user equals() or mapping
190 >     * functions take a long time.  However, statistically, this is
191 >     * not a common enough problem to outweigh the time/space overhead
192 >     * of alternatives: Under random hash codes, the frequency of
193 >     * nodes in bins follows a Poisson distribution
194 >     * (http://en.wikipedia.org/wiki/Poisson_distribution) with a
195 >     * parameter of about 0.5 on average, given the resizing threshold
196 >     * of 0.75, although with a large variance because of resizing
197 >     * granularity. Ignoring variance, the expected occurrences of
198 >     * list size k are (exp(-0.5) * pow(0.5, k) / factorial(k)). The
199 >     * first few values are:
200 >     *
201 >     * 0:    0.607
202 >     * 1:    0.303
203 >     * 2:    0.076
204 >     * 3:    0.012
205 >     * more: 0.002
206 >     *
207 >     * Lock contention probability for two threads accessing distinct
208 >     * elements is roughly 1 / (8 * #elements).  Function "spread"
209 >     * performs hashCode randomization that improves the likelihood
210 >     * that these assumptions hold unless users define exactly the
211 >     * same value for too many hashCodes.
212 >     *
213 >     * The table is resized when occupancy exceeds an occupancy
214 >     * threshold (nominally, 0.75, but see below).  Only a single
215 >     * thread performs the resize (using field "sizeCtl", to arrange
216 >     * exclusion), but the table otherwise remains usable for reads
217 >     * and updates. Resizing proceeds by transferring bins, one by
218 >     * one, from the table to the next table.  Because we are using
219 >     * power-of-two expansion, the elements from each bin must either
220 >     * stay at same index, or move with a power of two offset. We
221 >     * eliminate unnecessary node creation by catching cases where old
222 >     * nodes can be reused because their next fields won't change.  On
223 >     * average, only about one-sixth of them need cloning when a table
224 >     * doubles. The nodes they replace will be garbage collectable as
225 >     * soon as they are no longer referenced by any reader thread that
226 >     * may be in the midst of concurrently traversing table.  Upon
227 >     * transfer, the old table bin contains only a special forwarding
228 >     * node (with hash field "MOVED") that contains the next table as
229       * its key. On encountering a forwarding node, access and update
230 <     * operations restart, using the new table. To ensure concurrent
231 <     * readability of traversals, transfers must proceed from the last
232 <     * bin (table.length - 1) up towards the first.  Any traversal
233 <     * starting from the first bin can then arrange to move to the new
234 <     * table for the rest of the traversal without revisiting nodes.
235 <     * This constrains bin transfers to a particular order, and so can
236 <     * block indefinitely waiting for the next lock, and other threads
237 <     * cannot help with the transfer. However, expected stalls are
238 <     * infrequent enough to not warrant the additional overhead and
239 <     * complexity of access and iteration schemes that could admit
240 <     * out-of-order or concurrent bin transfers.
241 <     *
242 <     * A similar traversal scheme (not yet implemented) can apply to
243 <     * partial traversals during partitioned aggregate operations.
244 <     * Also, read-only operations give up if ever forwarded to a null
245 <     * table, which provides support for shutdown-style clearing,
246 <     * which is also not currently implemented.
230 >     * operations restart, using the new table.
231 >     *
232 >     * Each bin transfer requires its bin lock. However, unlike other
233 >     * cases, a transfer can skip a bin if it fails to acquire its
234 >     * lock, and revisit it later. Method rebuild maintains a buffer
235 >     * of TRANSFER_BUFFER_SIZE bins that have been skipped because of
236 >     * failure to acquire a lock, and blocks only if none are
237 >     * available (i.e., only very rarely).  The transfer operation
238 >     * must also ensure that all accessible bins in both the old and
239 >     * new table are usable by any traversal.  When there are no lock
240 >     * acquisition failures, this is arranged simply by proceeding
241 >     * from the last bin (table.length - 1) up towards the first.
242 >     * Upon seeing a forwarding node, traversals (see class
243 >     * InternalIterator) arrange to move to the new table without
244 >     * revisiting nodes.  However, when any node is skipped during a
245 >     * transfer, all earlier table bins may have become visible, so
246 >     * are initialized with a reverse-forwarding node back to the old
247 >     * table until the new ones are established. (This sometimes
248 >     * requires transiently locking a forwarding node, which is
249 >     * possible under the above encoding.) These more expensive
250 >     * mechanics trigger only when necessary.
251 >     *
252 >     * The traversal scheme also applies to partial traversals of
253 >     * ranges of bins (via an alternate InternalIterator constructor)
254 >     * to support partitioned aggregate operations (that are not
255 >     * otherwise implemented yet).  Also, read-only operations give up
256 >     * if ever forwarded to a null table, which provides support for
257 >     * shutdown-style clearing, which is also not currently
258 >     * implemented.
259 >     *
260 >     * Lazy table initialization minimizes footprint until first use,
261 >     * and also avoids resizings when the first operation is from a
262 >     * putAll, constructor with map argument, or deserialization.
263 >     * These cases attempt to override the initial capacity settings,
264 >     * but harmlessly fail to take effect in cases of races.
265       *
266       * The element count is maintained using a LongAdder, which avoids
267       * contention on updates but can encounter cache thrashing if read
268 <     * too frequently during concurrent updates. To avoid reading so
268 >     * too frequently during concurrent access. To avoid reading so
269       * often, resizing is normally attempted only upon adding to a bin
270 <     * already holding two or more nodes. Under the default threshold
271 <     * (0.75), and uniform hash distributions, the probability of this
272 <     * occurring at threshold is around 13%, meaning that only about 1
273 <     * in 8 puts check threshold (and after resizing, many fewer do
274 <     * so). But this approximation has high variance for small table
275 <     * sizes, so we check on any collision for sizes <= 64.  Further,
276 <     * to increase the probablity that a resize occurs soon enough, we
277 <     * offset the threshold (see THRESHOLD_OFFSET) by the expected
278 <     * number of puts between checks. This is currently set to 8, in
279 <     * accord with the default load factor. In practice, this is
280 <     * rarely overridden, and in any case is close enough to other
281 <     * plausible values not to waste dynamic probablity computation
282 <     * for more precision.
270 >     * already holding two or more nodes. Under uniform hash
271 >     * distributions, the probability of this occurring at threshold
272 >     * is around 13%, meaning that only about 1 in 8 puts check
273 >     * threshold (and after resizing, many fewer do so). But this
274 >     * approximation has high variance for small table sizes, so we
275 >     * check on any collision for sizes <= 64.
276 >     *
277 >     * Maintaining API and serialization compatibility with previous
278 >     * versions of this class introduces several oddities. Mainly: We
279 >     * leave untouched but unused constructor arguments refering to
280 >     * concurrencyLevel. We accept a loadFactor constructor argument,
281 >     * but apply it only to initial table capacity (which is the only
282 >     * time that we can guarantee to honor it.) We also declare an
283 >     * unused "Segment" class that is instantiated in minimal form
284 >     * only when serializing.
285       */
286  
287      /* ---------------- Constants -------------- */
288  
289      /**
290 <     * The smallest allowed table capacity.  Must be a power of 2, at
291 <     * least 2.
290 >     * The largest possible table capacity.  This value must be
291 >     * exactly 1<<30 to stay within Java array allocation and indexing
292 >     * bounds for power of two table sizes, and is further required
293 >     * because the top two bits of 32bit hash fields are used for
294 >     * control purposes.
295       */
296 <    static final int MINIMUM_CAPACITY = 2;
296 >    private static final int MAXIMUM_CAPACITY = 1 << 30;
297  
298      /**
299 <     * The largest allowed table capacity.  Must be a power of 2, at
300 <     * most 1<<30.
299 >     * The default initial table capacity.  Must be a power of 2
300 >     * (i.e., at least 1) and at most MAXIMUM_CAPACITY.
301       */
302 <    static final int MAXIMUM_CAPACITY = 1 << 30;
302 >    private static final int DEFAULT_CAPACITY = 16;
303  
304      /**
305 <     * The default initial table capacity.  Must be a power of 2, at
306 <     * least MINIMUM_CAPACITY and at most MAXIMUM_CAPACITY
305 >     * The largest possible (non-power of two) array size.
306 >     * Needed by toArray and related methods.
307       */
308 <    static final int DEFAULT_CAPACITY = 16;
308 >    static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
309  
310      /**
311 <     * The default load factor for this table, used when not otherwise
312 <     * specified in a constructor.
311 >     * The default concurrency level for this table. Unused but
312 >     * defined for compatibility with previous versions of this class.
313       */
314 <    static final float DEFAULT_LOAD_FACTOR = 0.75f;
314 >    private static final int DEFAULT_CONCURRENCY_LEVEL = 16;
315  
316      /**
317 <     * The default concurrency level for this table. Unused, but
318 <     * defined for compatibility with previous versions of this class.
317 >     * The load factor for this table. Overrides of this value in
318 >     * constructors affect only the initial table capacity.  The
319 >     * actual floating point value isn't normally used -- it is
320 >     * simpler to use expressions such as {@code n - (n >>> 2)} for
321 >     * the associated resizing threshold.
322       */
323 <    static final int DEFAULT_CONCURRENCY_LEVEL = 16;
323 >    private static final float LOAD_FACTOR = 0.75f;
324  
325      /**
326 <     * The count value to offset thesholds to compensate for checking
327 <     * for resizing only when inserting into bins with two or more
328 <     * elements. See above for explanation.
326 >     * The buffer size for skipped bins during transfers. The
327 >     * value is arbitrary but should be large enough to avoid
328 >     * most locking stalls during resizes.
329       */
330 <    static final int THRESHOLD_OFFSET = 8;
330 >    private static final int TRANSFER_BUFFER_SIZE = 32;
331  
332 <    /**
333 <     * Special node hash value indicating to use table in node.key
334 <     * Must be negative.
332 >    /*
333 >     * Encodings for special uses of Node hash fields. See above for
334 >     * explanation.
335       */
336 <    static final int MOVED = -1;
336 >    static final int MOVED     = 0x80000000; // hash field for fowarding nodes
337 >    static final int LOCKED    = 0x40000000; // set/tested only as a bit
338 >    static final int WAITING   = 0xc0000000; // both bits set/tested together
339 >    static final int HASH_BITS = 0x3fffffff; // usable bits of normal node hash
340  
341      /* ---------------- Fields -------------- */
342  
343      /**
344       * The array of bins. Lazily initialized upon first insertion.
345 <     * Size is always a power of two. Accessed directly by inner
254 <     * classes.
345 >     * Size is always a power of two. Accessed directly by iterators.
346       */
347      transient volatile Node[] table;
348  
349 <    /** The counter maintaining number of elements. */
349 >    /**
350 >     * The counter maintaining number of elements.
351 >     */
352      private transient final LongAdder counter;
353 <    /** Nonzero when table is being initialized or resized. Updated via CAS. */
354 <    private transient volatile int resizing;
355 <    /** The target load factor for the table. */
356 <    private transient float loadFactor;
357 <    /** The next element count value upon which to resize the table. */
358 <    private transient int threshold;
359 <    /** The initial capacity of the table. */
360 <    private transient int initCap;
353 >
354 >    /**
355 >     * Table initialization and resizing control.  When negative, the
356 >     * table is being initialized or resized. Otherwise, when table is
357 >     * null, holds the initial table size to use upon creation, or 0
358 >     * for default. After initialization, holds the next element count
359 >     * value upon which to resize the table.
360 >     */
361 >    private transient volatile int sizeCtl;
362  
363      // views
364 <    transient Set<K> keySet;
365 <    transient Set<Map.Entry<K,V>> entrySet;
366 <    transient Collection<V> values;
364 >    private transient KeySet<K,V> keySet;
365 >    private transient Values<K,V> values;
366 >    private transient EntrySet<K,V> entrySet;
367  
368 <    /** For serialization compatability. Null unless serialized; see below */
369 <    Segment<K,V>[] segments;
368 >    /** For serialization compatibility. Null unless serialized; see below */
369 >    private Segment<K,V>[] segments;
370  
371 <    /**
278 <     * Applies a supplemental hash function to a given hashCode, which
279 <     * defends against poor quality hash functions.  The result must
280 <     * be non-negative, and for reasonable performance must have good
281 <     * avalanche properties; i.e., that each bit of the argument
282 <     * affects each bit (except sign bit) of the result.
283 <     */
284 <    private static final int spread(int h) {
285 <        // Apply base step of MurmurHash; see http://code.google.com/p/smhasher/
286 <        h ^= h >>> 16;
287 <        h *= 0x85ebca6b;
288 <        h ^= h >>> 13;
289 <        h *= 0xc2b2ae35;
290 <        return (h >>> 16) ^ (h & 0x7fffffff); // mask out sign bit
291 <    }
371 >    /* ---------------- Nodes -------------- */
372  
373      /**
374       * Key-value entry. Note that this is never exported out as a
375 <     * user-visible Map.Entry.
375 >     * user-visible Map.Entry (see WriteThroughEntry and SnapshotEntry
376 >     * below). Nodes with a negative hash field are special, and do
377 >     * not contain user keys or values.  Otherwise, keys are never
378 >     * null, and null val fields indicate that a node is in the
379 >     * process of being deleted or created. For purposes of read-only
380 >     * access, a key may be read before a val, but can only be used
381 >     * after checking val to be non-null.
382       */
383      static final class Node {
384 <        final int hash;
384 >        volatile int hash;
385          final Object key;
386          volatile Object val;
387          volatile Node next;
# Line 306 | Line 392 | public class ConcurrentHashMapV8<K, V>
392              this.val = val;
393              this.next = next;
394          }
395 +
396 +        /** CompareAndSet the hash field */
397 +        final boolean casHash(int cmp, int val) {
398 +            return UNSAFE.compareAndSwapInt(this, hashOffset, cmp, val);
399 +        }
400 +
401 +        /** The number of spins before blocking for a lock */
402 +        static final int MAX_SPINS =
403 +            Runtime.getRuntime().availableProcessors() > 1 ? 64 : 1;
404 +
405 +        /**
406 +         * Spins a while if LOCKED bit set and this node is the first
407 +         * of its bin, and then sets WAITING bits on hash field and
408 +         * blocks (once) if they are still set.  It is OK for this
409 +         * method to return even if lock is not available upon exit,
410 +         * which enables these simple single-wait mechanics.
411 +         *
412 +         * The corresponding signalling operation is performed within
413 +         * callers: Upon detecting that WAITING has been set when
414 +         * unlocking lock (via a failed CAS from non-waiting LOCKED
415 +         * state), unlockers acquire the sync lock and perform a
416 +         * notifyAll.
417 +         */
418 +        final void tryAwaitLock(Node[] tab, int i) {
419 +            if (tab != null && i >= 0 && i < tab.length) { // bounds check
420 +                int spins = MAX_SPINS, h;
421 +                while (tabAt(tab, i) == this && ((h = hash) & LOCKED) != 0) {
422 +                    if (spins >= 0) {
423 +                        if (--spins == MAX_SPINS >>> 1)
424 +                            Thread.yield();  // heuristically yield mid-way
425 +                    }
426 +                    else if (casHash(h, h | WAITING)) {
427 +                        synchronized (this) {
428 +                            if (tabAt(tab, i) == this &&
429 +                                (hash & WAITING) == WAITING) {
430 +                                try {
431 +                                    wait();
432 +                                } catch (InterruptedException ie) {
433 +                                    Thread.currentThread().interrupt();
434 +                                }
435 +                            }
436 +                            else
437 +                                notifyAll(); // possibly won race vs signaller
438 +                        }
439 +                        break;
440 +                    }
441 +                }
442 +            }
443 +        }
444 +
445 +        // Unsafe mechanics for casHash
446 +        private static final sun.misc.Unsafe UNSAFE;
447 +        private static final long hashOffset;
448 +
449 +        static {
450 +            try {
451 +                UNSAFE = getUnsafe();
452 +                Class<?> k = Node.class;
453 +                hashOffset = UNSAFE.objectFieldOffset
454 +                    (k.getDeclaredField("hash"));
455 +            } catch (Exception e) {
456 +                throw new Error(e);
457 +            }
458 +        }
459      }
460  
461 +    /* ---------------- Table element access -------------- */
462 +
463      /*
464 <     * Volatile access nethods are used for table elements as well as
465 <     * elements of in-progress next table while resizing.  Uses in
466 <     * access and update methods are null checked by callers, and
467 <     * implicitly bounds-checked, relying on the invariants that tab
468 <     * arrays have non-zero size, and all indices are masked with
469 <     * (tab.length - 1) which is never negative and always less than
470 <     * length. The "relaxed" non-volatile forms are used only during
471 <     * table initialization. The only other usage is in
472 <     * HashIterator.advance, which performs explicit checks.
464 >     * Volatile access methods are used for table elements as well as
465 >     * elements of in-progress next table while resizing.  Uses are
466 >     * null checked by callers, and implicitly bounds-checked, relying
467 >     * on the invariants that tab arrays have non-zero size, and all
468 >     * indices are masked with (tab.length - 1) which is never
469 >     * negative and always less than length. Note that, to be correct
470 >     * wrt arbitrary concurrency errors by users, bounds checks must
471 >     * operate on local variables, which accounts for some odd-looking
472 >     * inline assignments below.
473       */
474  
475 <    static final Node tabAt(Node[] tab, int i) { // used in HashIterator
475 >    static final Node tabAt(Node[] tab, int i) { // used by InternalIterator
476          return (Node)UNSAFE.getObjectVolatile(tab, ((long)i<<ASHIFT)+ABASE);
477      }
478  
# Line 332 | Line 484 | public class ConcurrentHashMapV8<K, V>
484          UNSAFE.putObjectVolatile(tab, ((long)i<<ASHIFT)+ABASE, v);
485      }
486  
487 <    private static final Node relaxedTabAt(Node[] tab, int i) {
336 <        return (Node)UNSAFE.getObject(tab, ((long)i<<ASHIFT)+ABASE);
337 <    }
487 >    /* ---------------- Internal access and update methods -------------- */
488  
489 <    private static final void relaxedSetTabAt(Node[] tab, int i, Node v) {
490 <        UNSAFE.putObject(tab, ((long)i<<ASHIFT)+ABASE, v);
489 >    /**
490 >     * Applies a supplemental hash function to a given hashCode, which
491 >     * defends against poor quality hash functions.  The result must
492 >     * be have the top 2 bits clear. For reasonable performance, this
493 >     * function must have good avalanche properties; i.e., that each
494 >     * bit of the argument affects each bit of the result. (Although
495 >     * we don't care about the unused top 2 bits.)
496 >     */
497 >    private static final int spread(int h) {
498 >        // Apply base step of MurmurHash; see http://code.google.com/p/smhasher/
499 >        h ^= h >>> 16;
500 >        h *= 0x85ebca6b;
501 >        h ^= h >>> 13;
502 >        h *= 0xc2b2ae35;
503 >        return ((h >>> 16) ^ h) & HASH_BITS; // mask out top bits
504      }
505  
506 <    /* ---------------- Access and update operations -------------- */
344 <
345 <    /** Implementation for get and containsKey **/
506 >    /** Implementation for get and containsKey */
507      private final Object internalGet(Object k) {
508          int h = spread(k.hashCode());
509 <        Node[] tab = table;
510 <        retry: while (tab != null) {
511 <            Node e = tabAt(tab, (tab.length - 1) & h);
512 <            while (e != null) {
513 <                int eh = e.hash;
353 <                if (eh == h) {
354 <                    Object ek = e.key, ev = e.val;
355 <                    if (ev != null && ek != null && (k == ek || k.equals(ek)))
356 <                        return ev;
357 <                }
358 <                else if (eh < 0) { // bin was moved during resize
359 <                    tab = (Node[])e.key;
509 >        retry: for (Node[] tab = table; tab != null;) {
510 >            Node e; Object ek, ev; int eh;    // locals to read fields once
511 >            for (e = tabAt(tab, (tab.length - 1) & h); e != null; e = e.next) {
512 >                if ((eh = e.hash) == MOVED) {
513 >                    tab = (Node[])e.key;      // restart with new table
514                      continue retry;
515                  }
516 <                e = e.next;
516 >                if ((eh & HASH_BITS) == h && (ev = e.val) != null &&
517 >                    ((ek = e.key) == k || k.equals(ek)))
518 >                    return ev;
519              }
520              break;
521          }
522          return null;
523      }
524  
525 <    /** Implementation for put and putIfAbsent **/
525 >    /** Implementation for put and putIfAbsent */
526      private final Object internalPut(Object k, Object v, boolean replace) {
527          int h = spread(k.hashCode());
528 <        Object oldVal = null;  // the previous value or null if none
529 <        Node[] tab = table;
530 <        for (;;) {
375 <            Node e; int i;
528 >        Object oldVal = null;               // previous value or null if none
529 >        for (Node[] tab = table;;) {
530 >            int i; Node f; int fh; Object fk, fv;
531              if (tab == null)
532 <                tab = grow(0);
533 <            else if ((e = tabAt(tab, i = (tab.length - 1) & h)) == null) {
532 >                tab = initTable();
533 >            else if ((f = tabAt(tab, i = (tab.length - 1) & h)) == null) {
534                  if (casTabAt(tab, i, null, new Node(h, k, v, null)))
535 <                    break;
535 >                    break;                   // no lock when adding to empty bin
536              }
537 <            else if (e.hash < 0)
538 <                tab = (Node[])e.key;
539 <            else {
537 >            else if ((fh = f.hash) == MOVED)
538 >                tab = (Node[])f.key;
539 >            else if (!replace && (fh & HASH_BITS) == h && (fv = f.val) != null &&
540 >                     ((fk = f.key) == k || k.equals(fk))) {
541 >                oldVal = fv;                // precheck 1st node for putIfAbsent
542 >                break;
543 >            }
544 >            else if ((fh & LOCKED) != 0)
545 >                f.tryAwaitLock(tab, i);
546 >            else if (f.casHash(fh, fh | LOCKED)) {
547                  boolean validated = false;
548                  boolean checkSize = false;
549 <                synchronized (e) {
550 <                    Node first = e;
551 <                    for (;;) {
552 <                        Object ek, ev;
553 <                        if ((ev = e.val) == null)
554 <                            break;
555 <                        if (e.hash == h && (ek = e.key) != null &&
556 <                            (k == ek || k.equals(ek))) {
395 <                            if (tabAt(tab, i) == first) {
396 <                                validated = true;
549 >                try {
550 >                    if (tabAt(tab, i) == f) {
551 >                        validated = true;    // retry if 1st already deleted
552 >                        for (Node e = f;;) {
553 >                            Object ek, ev;
554 >                            if ((e.hash & HASH_BITS) == h &&
555 >                                (ev = e.val) != null &&
556 >                                ((ek = e.key) == k || k.equals(ek))) {
557                                  oldVal = ev;
558                                  if (replace)
559                                      e.val = v;
560 +                                break;
561                              }
562 <                            break;
563 <                        }
403 <                        Node last = e;
404 <                        if ((e = e.next) == null) {
405 <                            if (tabAt(tab, i) == first) {
406 <                                validated = true;
562 >                            Node last = e;
563 >                            if ((e = e.next) == null) {
564                                  last.next = new Node(h, k, v, null);
565 <                                if (last != first || tab.length <= 64)
565 >                                if (last != f || tab.length <= 64)
566                                      checkSize = true;
567 +                                break;
568                              }
411                            break;
569                          }
570                      }
571 +                } finally {                  // unlock and signal if needed
572 +                    if (!f.casHash(fh | LOCKED, fh)) {
573 +                        f.hash = fh;
574 +                        synchronized (f) { f.notifyAll(); };
575 +                    }
576                  }
577                  if (validated) {
578 +                    int sc;
579                      if (checkSize && tab.length < MAXIMUM_CAPACITY &&
580 <                        resizing == 0 && counter.sum() >= threshold)
581 <                        grow(0);
580 >                        (sc = sizeCtl) >= 0 && counter.sum() >= (long)sc)
581 >                        growTable();
582                      break;
583                  }
584              }
585          }
586          if (oldVal == null)
587 <            counter.increment();
587 >            counter.increment();             // update counter outside of locks
588          return oldVal;
589      }
590  
591      /**
592 <     * Covers the four public remove/replace methods: Replaces node
593 <     * value with v, conditional upon match of cv if non-null.  If
594 <     * resulting value is null, delete.
592 >     * Implementation for the four public remove/replace methods:
593 >     * Replaces node value with v, conditional upon match of cv if
594 >     * non-null.  If resulting value is null, delete.
595       */
596      private final Object internalReplace(Object k, Object v, Object cv) {
597          int h = spread(k.hashCode());
598          Object oldVal = null;
599 <        Node e; int i;
600 <        Node[] tab = table;
601 <        while (tab != null &&
602 <               (e = tabAt(tab, i = (tab.length - 1) & h)) != null) {
603 <            if (e.hash < 0)
604 <                tab = (Node[])e.key;
605 <            else {
599 >        for (Node[] tab = table;;) {
600 >            Node f; int i, fh;
601 >            if (tab == null ||
602 >                (f = tabAt(tab, i = (tab.length - 1) & h)) == null)
603 >                break;
604 >            else if ((fh = f.hash) == MOVED)
605 >                tab = (Node[])f.key;
606 >            else if ((fh & HASH_BITS) != h && f.next == null) // precheck
607 >                break;                          // rules out possible existence
608 >            else if ((fh & LOCKED) != 0)
609 >                f.tryAwaitLock(tab, i);
610 >            else if (f.casHash(fh, fh | LOCKED)) {
611                  boolean validated = false;
612                  boolean deleted = false;
613 <                synchronized (e) {
614 <                    Node pred = null;
615 <                    Node first = e;
616 <                    for (;;) {
617 <                        Object ek, ev;
618 <                        if ((ev = e.val) == null)
619 <                            break;
620 <                        if (e.hash == h && (ek = e.key) != null &&
453 <                            (k == ek || k.equals(ek))) {
454 <                            if (tabAt(tab, i) == first) {
455 <                                validated = true;
613 >                try {
614 >                    if (tabAt(tab, i) == f) {
615 >                        validated = true;
616 >                        for (Node e = f, pred = null;;) {
617 >                            Object ek, ev;
618 >                            if ((e.hash & HASH_BITS) == h &&
619 >                                ((ev = e.val) != null) &&
620 >                                ((ek = e.key) == k || k.equals(ek))) {
621                                  if (cv == null || cv == ev || cv.equals(ev)) {
622                                      oldVal = ev;
623                                      if ((e.val = v) == null) {
# Line 464 | Line 629 | public class ConcurrentHashMapV8<K, V>
629                                              setTabAt(tab, i, en);
630                                      }
631                                  }
632 +                                break;
633                              }
634 <                            break;
635 <                        }
636 <                        pred = e;
471 <                        if ((e = e.next) == null) {
472 <                            if (tabAt(tab, i) == first)
473 <                                validated = true;
474 <                            break;
634 >                            pred = e;
635 >                            if ((e = e.next) == null)
636 >                                break;
637                          }
638                      }
639 +                } finally {
640 +                    if (!f.casHash(fh | LOCKED, fh)) {
641 +                        f.hash = fh;
642 +                        synchronized (f) { f.notifyAll(); };
643 +                    }
644                  }
645                  if (validated) {
646                      if (deleted)
# Line 485 | Line 652 | public class ConcurrentHashMapV8<K, V>
652          return oldVal;
653      }
654  
655 <    /** Implementation for computeIfAbsent and compute */
655 >    /** Implementation for computeIfAbsent and compute. Like put, but messier. */
656 >    // Todo: Somehow reinstate non-termination check
657      @SuppressWarnings("unchecked")
658      private final V internalCompute(K k,
659 <                                    MappingFunction<? super K, ? extends V> f,
659 >                                    MappingFunction<? super K, ? extends V> fn,
660                                      boolean replace) {
661          int h = spread(k.hashCode());
662          V val = null;
663          boolean added = false;
496        boolean validated = false;
664          Node[] tab = table;
665 <        do {
666 <            Node e; int i;
665 >        outer:for (;;) {
666 >            Node f; int i, fh; Object fk, fv;
667              if (tab == null)
668 <                tab = grow(0);
669 <            else if ((e = tabAt(tab, i = (tab.length - 1) & h)) == null) {
670 <                Node node = new Node(h, k, null, null);
671 <                synchronized (node) {
672 <                    if (casTabAt(tab, i, null, node)) {
673 <                        validated = true;
674 <                        try {
675 <                            val = f.map(k);
676 <                            if (val != null) {
677 <                                node.val = val;
678 <                                added = true;
679 <                            }
680 <                        } finally {
681 <                            if (!added)
682 <                                setTabAt(tab, i, null);
668 >                tab = initTable();
669 >            else if ((f = tabAt(tab, i = (tab.length - 1) & h)) == null) {
670 >                Node node = new Node(fh = h | LOCKED, k, null, null);
671 >                boolean validated = false;
672 >                if (casTabAt(tab, i, null, node)) {
673 >                    validated = true;
674 >                    try {
675 >                        val = fn.map(k);
676 >                        if (val != null) {
677 >                            node.val = val;
678 >                            added = true;
679 >                        }
680 >                    } finally {
681 >                        if (!added)
682 >                            setTabAt(tab, i, null);
683 >                        if (!node.casHash(fh, h)) {
684 >                            node.hash = h;
685 >                            synchronized (node) { node.notifyAll(); };
686                          }
687                      }
688                  }
689 +                if (validated)
690 +                    break;
691              }
692 <            else if (e.hash < 0)
693 <                tab = (Node[])e.key;
694 <            else if (Thread.holdsLock(e))
695 <                throw new IllegalStateException("Recursive map computation");
696 <            else {
692 >            else if ((fh = f.hash) == MOVED)
693 >                tab = (Node[])f.key;
694 >            else if (!replace && (fh & HASH_BITS) == h && (fv = f.val) != null &&
695 >                     ((fk = f.key) == k || k.equals(fk))) {
696 >                if (tabAt(tab, i) == f) {
697 >                    val = (V)fv;
698 >                    break;
699 >                }
700 >            }
701 >            else if ((fh & LOCKED) != 0)
702 >                f.tryAwaitLock(tab, i);
703 >            else if (f.casHash(fh, fh | LOCKED)) {
704 >                boolean validated = false;
705                  boolean checkSize = false;
706 <                synchronized (e) {
707 <                    Node first = e;
708 <                    for (;;) {
709 <                        Object ek, ev;
710 <                        if ((ev = e.val) == null)
711 <                            break;
712 <                        if (e.hash == h && (ek = e.key) != null &&
713 <                            (k == ek || k.equals(ek))) {
714 <                            if (tabAt(tab, i) == first) {
715 <                                validated = true;
536 <                                if (replace && (ev = f.map(k)) != null)
537 <                                    e.val = ev;
706 >                try {
707 >                    if (tabAt(tab, i) == f) {
708 >                        validated = true;
709 >                        for (Node e = f;;) {
710 >                            Object ek, ev, v;
711 >                            if ((e.hash & HASH_BITS) == h &&
712 >                                (ev = e.val) != null &&
713 >                                ((ek = e.key) == k || k.equals(ek))) {
714 >                                if (replace && (v = fn.map(k)) != null)
715 >                                    ev = e.val = v;
716                                  val = (V)ev;
717 +                                break;
718                              }
719 <                            break;
720 <                        }
721 <                        Node last = e;
543 <                        if ((e = e.next) == null) {
544 <                            if (tabAt(tab, i) == first) {
545 <                                validated = true;
546 <                                if ((val = f.map(k)) != null) {
719 >                            Node last = e;
720 >                            if ((e = e.next) == null) {
721 >                                if ((val = fn.map(k)) != null) {
722                                      last.next = new Node(h, k, val, null);
723                                      added = true;
724 <                                    if (last != first || tab.length <= 64)
724 >                                    if (last != f || tab.length <= 64)
725                                          checkSize = true;
726                                  }
727 +                                break;
728                              }
553                            break;
729                          }
730                      }
731 +                } finally {
732 +                    if (!f.casHash(fh | LOCKED, fh)) {
733 +                        f.hash = fh;
734 +                        synchronized (f) { f.notifyAll(); };
735 +                    }
736 +                }
737 +                if (validated) {
738 +                    int sc;
739 +                    if (checkSize && tab.length < MAXIMUM_CAPACITY &&
740 +                        (sc = sizeCtl) >= 0 && counter.sum() >= (long)sc)
741 +                        growTable();
742 +                    break;
743                  }
557                if (checkSize && tab.length < MAXIMUM_CAPACITY &&
558                    resizing == 0 && counter.sum() >= threshold)
559                    grow(0);
744              }
745 <        } while (!validated);
745 >        }
746          if (added)
747              counter.increment();
748          return val;
749      }
750  
751 <    /*
752 <     * Reclassifies nodes in each bin to new table.  Because we are
569 <     * using power-of-two expansion, the elements from each bin must
570 <     * either stay at same index, or move with a power of two
571 <     * offset. We eliminate unnecessary node creation by catching
572 <     * cases where old nodes can be reused because their next fields
573 <     * won't change.  Statistically, at the default threshold, only
574 <     * about one-sixth of them need cloning when a table doubles. The
575 <     * nodes they replace will be garbage collectable as soon as they
576 <     * are no longer referenced by any reader thread that may be in
577 <     * the midst of concurrently traversing table.
578 <     *
579 <     * Transfers are done from the bottom up to preserve iterator
580 <     * traversability. On each step, the old bin is locked,
581 <     * moved/copied, and then replaced with a forwarding node.
751 >    /**
752 >     * Implementation for clear. Steps through each bin, removing all nodes.
753       */
754 <    private static final void transfer(Node[] tab, Node[] nextTab) {
755 <        int n = tab.length;
756 <        int mask = nextTab.length - 1;
757 <        Node fwd = new Node(MOVED, nextTab, null, null);
758 <        for (int i = n - 1; i >= 0; --i) {
759 <            for (Node e;;) {
760 <                if ((e = tabAt(tab, i)) == null) {
761 <                    if (casTabAt(tab, i, e, fwd))
762 <                        break;
763 <                }
764 <                else {
765 <                    boolean validated = false;
766 <                    synchronized (e) {
767 <                        int idx = e.hash & mask;
768 <                        Node lastRun = e;
769 <                        for (Node p = e.next; p != null; p = p.next) {
770 <                            int j = p.hash & mask;
771 <                            if (j != idx) {
772 <                                idx = j;
773 <                                lastRun = p;
774 <                            }
775 <                        }
605 <                        if (tabAt(tab, i) == e) {
606 <                            validated = true;
607 <                            relaxedSetTabAt(nextTab, idx, lastRun);
608 <                            for (Node p = e; p != lastRun; p = p.next) {
609 <                                int h = p.hash;
610 <                                int j = h & mask;
611 <                                Node r = relaxedTabAt(nextTab, j);
612 <                                relaxedSetTabAt(nextTab, j,
613 <                                                new Node(h, p.key, p.val, r));
754 >    private final void internalClear() {
755 >        long delta = 0L; // negative number of deletions
756 >        int i = 0;
757 >        Node[] tab = table;
758 >        while (tab != null && i < tab.length) {
759 >            int fh;
760 >            Node f = tabAt(tab, i);
761 >            if (f == null)
762 >                ++i;
763 >            else if ((fh = f.hash) == MOVED)
764 >                tab = (Node[])f.key;
765 >            else if ((fh & LOCKED) != 0)
766 >                f.tryAwaitLock(tab, i);
767 >            else if (f.casHash(fh, fh | LOCKED)) {
768 >                boolean validated = false;
769 >                try {
770 >                    if (tabAt(tab, i) == f) {
771 >                        validated = true;
772 >                        for (Node e = f; e != null; e = e.next) {
773 >                            if (e.val != null) { // currently always true
774 >                                e.val = null;
775 >                                --delta;
776                              }
615                            setTabAt(tab, i, fwd);
777                          }
778 +                        setTabAt(tab, i, null);
779 +                    }
780 +                } finally {
781 +                    if (!f.casHash(fh | LOCKED, fh)) {
782 +                        f.hash = fh;
783 +                        synchronized (f) { f.notifyAll(); };
784                      }
618                    if (validated)
619                        break;
785                  }
786 +                if (validated)
787 +                    ++i;
788              }
789          }
790 +        counter.add(delta);
791      }
792  
793 +    /* ----------------Table Initialization and Resizing -------------- */
794 +
795      /**
796 <     * If not already resizing, initializes or creates next table and
797 <     * transfers bins. Rechecks occupancy after a transfer to see if
798 <     * another resize is already needed because resizings are lagging
799 <     * additions.
800 <     *
801 <     * @param sizeHint overridden capacity target (nonzero only from putAll)
802 <     * @return current table
803 <     */
804 <    private final Node[] grow(int sizeHint) {
805 <        if (resizing == 0 &&
806 <            UNSAFE.compareAndSwapInt(this, resizingOffset, 0, 1)) {
807 <            try {
808 <                for (;;) {
809 <                    int cap, n;
810 <                    Node[] tab = table;
811 <                    if (tab == null) {
812 <                        int c = initCap;
813 <                        if (c < sizeHint)
814 <                            c = sizeHint;
815 <                        if (c == DEFAULT_CAPACITY)
816 <                            cap = c;
817 <                        else if (c >= MAXIMUM_CAPACITY)
818 <                            cap = MAXIMUM_CAPACITY;
819 <                        else {
820 <                            cap = MINIMUM_CAPACITY;
821 <                            while (cap < c)
822 <                                cap <<= 1;
653 <                        }
796 >     * Returns a power of two table size for the given desired capacity.
797 >     * See Hackers Delight, sec 3.2
798 >     */
799 >    private static final int tableSizeFor(int c) {
800 >        int n = c - 1;
801 >        n |= n >>> 1;
802 >        n |= n >>> 2;
803 >        n |= n >>> 4;
804 >        n |= n >>> 8;
805 >        n |= n >>> 16;
806 >        return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
807 >    }
808 >
809 >    /**
810 >     * Initializes table, using the size recorded in sizeCtl.
811 >     */
812 >    private final Node[] initTable() {
813 >        Node[] tab; int sc;
814 >        while ((tab = table) == null) {
815 >            if ((sc = sizeCtl) < 0)
816 >                Thread.yield(); // lost initialization race; just spin
817 >            else if (UNSAFE.compareAndSwapInt(this, sizeCtlOffset, sc, -1)) {
818 >                try {
819 >                    if ((tab = table) == null) {
820 >                        int n = (sc > 0) ? sc : DEFAULT_CAPACITY;
821 >                        tab = table = new Node[n];
822 >                        sc = n - (n >>> 2) - 1;
823                      }
824 <                    else if ((n = tab.length) < MAXIMUM_CAPACITY &&
825 <                             (sizeHint <= 0 || n < sizeHint))
657 <                        cap = n << 1;
658 <                    else
659 <                        break;
660 <                    threshold = (int)(cap * loadFactor) - THRESHOLD_OFFSET;
661 <                    Node[] nextTab = new Node[cap];
662 <                    if (tab != null)
663 <                        transfer(tab, nextTab);
664 <                    table = nextTab;
665 <                    if (tab == null || cap >= MAXIMUM_CAPACITY ||
666 <                        (sizeHint > 0 && cap >= sizeHint) ||
667 <                        counter.sum() < threshold)
668 <                        break;
824 >                } finally {
825 >                    sizeCtl = sc;
826                  }
827 <            } finally {
671 <                resizing = 0;
827 >                break;
828              }
829          }
830 <        else if (table == null)
675 <            Thread.yield(); // lost initialization race; just spin
676 <        return table;
830 >        return tab;
831      }
832  
833      /**
834 <     * Implementation for putAll and constructor with Map
835 <     * argument. Tries to first override initial capacity or grow
836 <     * based on map size to pre-allocate table space.
834 >     * If not already resizing, creates next table and transfers bins.
835 >     * Rechecks occupancy after a transfer to see if another resize is
836 >     * already needed because resizings are lagging additions.
837       */
838 <    private final void internalPutAll(Map<? extends K, ? extends V> m) {
839 <        int s = m.size();
840 <        grow((s >= (MAXIMUM_CAPACITY >>> 1)) ? s : s + (s >>> 1));
841 <        for (Map.Entry<? extends K, ? extends V> e : m.entrySet()) {
842 <            Object k = e.getKey();
843 <            Object v = e.getValue();
844 <            if (k == null || v == null)
845 <                throw new NullPointerException();
846 <            internalPut(k, v, true);
838 >    private final void growTable() {
839 >        int sc = sizeCtl;
840 >        if (sc >= 0 && UNSAFE.compareAndSwapInt(this, sizeCtlOffset, sc, -1)) {
841 >            try {
842 >                Node[] tab; int n;
843 >                while ((tab = table) != null &&
844 >                       (n = tab.length) > 0 && n < MAXIMUM_CAPACITY &&
845 >                       counter.sum() >= (long)sc) {
846 >                    table = rebuild(tab);
847 >                    sc = (n << 1) - (n >>> 1) - 1;
848 >                }
849 >            } finally {
850 >                sizeCtl = sc;
851 >            }
852          }
853      }
854  
855 <    /**
856 <     * Implementation for clear. Steps through each bin, removing all nodes.
855 >    /*
856 >     * Moves and/or copies the nodes in each bin to new table. See
857 >     * above for explanation.
858 >     *
859 >     * @return the new table
860       */
861 <    private final void internalClear() {
862 <        long deletions = 0L;
863 <        int i = 0;
864 <        Node[] tab = table;
865 <        while (tab != null && i < tab.length) {
866 <            Node e = tabAt(tab, i);
867 <            if (e == null)
868 <                ++i;
869 <            else if (e.hash < 0)
870 <                tab = (Node[])e.key;
871 <            else {
861 >    private static final Node[] rebuild(Node[] tab) {
862 >        int n = tab.length;
863 >        Node[] nextTab = new Node[n << 1];
864 >        Node fwd = new Node(MOVED, nextTab, null, null);
865 >        int[] buffer = null;       // holds bins to revisit; null until needed
866 >        Node rev = null;           // reverse forwarder; null until needed
867 >        int nbuffered = 0;         // the number of bins in buffer list
868 >        int bufferIndex = 0;       // buffer index of current buffered bin
869 >        int bin = n - 1;           // current non-buffered bin or -1 if none
870 >
871 >        for (int i = bin;;) {      // start upwards sweep
872 >            int fh; Node f;
873 >            if ((f = tabAt(tab, i)) == null) {
874 >                if (bin >= 0) {    // no lock needed (or available)
875 >                    if (!casTabAt(tab, i, f, fwd))
876 >                        continue;
877 >                }
878 >                else {             // transiently use a locked forwarding node
879 >                    Node g =  new Node(MOVED|LOCKED, nextTab, null, null);
880 >                    if (!casTabAt(tab, i, f, g))
881 >                        continue;
882 >                    setTabAt(nextTab, i, null);
883 >                    setTabAt(nextTab, i + n, null);
884 >                    setTabAt(tab, i, fwd);
885 >                    if (!g.casHash(MOVED|LOCKED, MOVED)) {
886 >                        g.hash = MOVED;
887 >                        synchronized (g) { g.notifyAll(); }
888 >                    }
889 >                }
890 >            }
891 >            else if (((fh = f.hash) & LOCKED) == 0 && f.casHash(fh, fh|LOCKED)) {
892                  boolean validated = false;
893 <                synchronized (e) {
894 <                    if (tabAt(tab, i) == e) {
893 >                try {              // split to lo and hi lists; copying as needed
894 >                    if (tabAt(tab, i) == f) {
895                          validated = true;
896 <                        do {
897 <                            if (e.val != null) {
898 <                                e.val = null;
899 <                                ++deletions;
896 >                        Node e = f, lastRun = f;
897 >                        Node lo = null, hi = null;
898 >                        int runBit = e.hash & n;
899 >                        for (Node p = e.next; p != null; p = p.next) {
900 >                            int b = p.hash & n;
901 >                            if (b != runBit) {
902 >                                runBit = b;
903 >                                lastRun = p;
904                              }
905 <                        } while ((e = e.next) != null);
906 <                        setTabAt(tab, i, null);
905 >                        }
906 >                        if (runBit == 0)
907 >                            lo = lastRun;
908 >                        else
909 >                            hi = lastRun;
910 >                        for (Node p = e; p != lastRun; p = p.next) {
911 >                            int ph = p.hash & HASH_BITS;
912 >                            Object pk = p.key, pv = p.val;
913 >                            if ((ph & n) == 0)
914 >                                lo = new Node(ph, pk, pv, lo);
915 >                            else
916 >                                hi = new Node(ph, pk, pv, hi);
917 >                        }
918 >                        setTabAt(nextTab, i, lo);
919 >                        setTabAt(nextTab, i + n, hi);
920 >                        setTabAt(tab, i, fwd);
921                      }
922 <                }
923 <                if (validated) {
924 <                    ++i;
925 <                    if (deletions > THRESHOLD_OFFSET) { // bound lag in counts
726 <                        counter.add(-deletions);
727 <                        deletions = 0L;
922 >                } finally {
923 >                    if (!f.casHash(fh | LOCKED, fh)) {
924 >                        f.hash = fh;
925 >                        synchronized (f) { f.notifyAll(); };
926                      }
927                  }
928 +                if (!validated)
929 +                    continue;
930              }
731        }
732        if (deletions != 0L)
733            counter.add(-deletions);
734    }
735
736    /**
737     * Base class for key, value, and entry iterators, plus internal
738     * implementations of public traversal-based methods, to avoid
739     * duplicating traversal code.
740     */
741    class HashIterator {
742        private Node next;          // the next entry to return
743        private Node[] tab;         // current table; updated if resized
744        private Node lastReturned;  // the last entry returned, for remove
745        private Object nextVal;     // cached value of next
746        private int index;          // index of bin to use next
747        private int baseIndex;      // current index of initial table
748        private final int baseSize; // initial table size
749
750        HashIterator() {
751            Node[] t = tab = table;
752            if (t == null)
753                baseSize = 0;
931              else {
932 <                baseSize = t.length;
933 <                advance(null);
934 <            }
935 <        }
936 <
937 <        public final boolean hasNext()         { return next != null; }
938 <        public final boolean hasMoreElements() { return next != null; }
762 <
763 <        /**
764 <         * Advances next.  Normally, iteration proceeds bin-by-bin
765 <         * traversing lists.  However, if the table has been resized,
766 <         * then all future steps must traverse both the bin at the
767 <         * current index as well as at (index + baseSize); and so on
768 <         * for further resizings. To paranoically cope with potential
769 <         * (improper) sharing of iterators across threads, table reads
770 <         * are bounds-checked.
771 <         */
772 <        final void advance(Node e) {
773 <            for (;;) {
774 <                Node[] t; int i; // for bounds checks
775 <                if (e != null) {
776 <                    Object ek = e.key, ev = e.val;
777 <                    if (ev != null && ek != null) {
778 <                        nextVal = ev;
779 <                        next = e;
780 <                        break;
781 <                    }
782 <                    e = e.next;
932 >                if (buffer == null) // initialize buffer for revisits
933 >                    buffer = new int[TRANSFER_BUFFER_SIZE];
934 >                if (bin < 0 && bufferIndex > 0) {
935 >                    int j = buffer[--bufferIndex];
936 >                    buffer[bufferIndex] = i;
937 >                    i = j;         // swap with another bin
938 >                    continue;
939                  }
940 <                else if (baseIndex < baseSize && (t = tab) != null &&
941 <                         t.length > (i = index) && i >= 0) {
942 <                    if ((e = tabAt(t, i)) != null && e.hash < 0) {
787 <                        tab = (Node[])e.key;
788 <                        e = null;
789 <                    }
790 <                    else if (i + baseSize < t.length)
791 <                        index += baseSize;    // visit forwarded upper slots
792 <                    else
793 <                        index = ++baseIndex;
940 >                if (bin < 0 || nbuffered >= TRANSFER_BUFFER_SIZE) {
941 >                    f.tryAwaitLock(tab, i);
942 >                    continue;      // no other options -- block
943                  }
944 <                else {
945 <                    next = null;
946 <                    break;
947 <                }
948 <            }
949 <        }
950 <
802 <        final Object nextKey() {
803 <            Node e = next;
804 <            if (e == null)
805 <                throw new NoSuchElementException();
806 <            Object k = e.key;
807 <            advance((lastReturned = e).next);
808 <            return k;
809 <        }
810 <
811 <        final Object nextValue() {
812 <            Node e = next;
813 <            if (e == null)
814 <                throw new NoSuchElementException();
815 <            Object v = nextVal;
816 <            advance((lastReturned = e).next);
817 <            return v;
818 <        }
819 <
820 <        final WriteThroughEntry nextEntry() {
821 <            Node e = next;
822 <            if (e == null)
823 <                throw new NoSuchElementException();
824 <            WriteThroughEntry entry =
825 <                new WriteThroughEntry(e.key, nextVal);
826 <            advance((lastReturned = e).next);
827 <            return entry;
828 <        }
829 <
830 <        public final void remove() {
831 <            if (lastReturned == null)
832 <                throw new IllegalStateException();
833 <            ConcurrentHashMapV8.this.remove(lastReturned.key);
834 <            lastReturned = null;
835 <        }
836 <
837 <        /** Helper for serialization */
838 <        final void writeEntries(java.io.ObjectOutputStream s)
839 <            throws java.io.IOException {
840 <            Node e;
841 <            while ((e = next) != null) {
842 <                s.writeObject(e.key);
843 <                s.writeObject(nextVal);
844 <                advance(e.next);
944 >                if (rev == null)   // initialize reverse-forwarder
945 >                    rev = new Node(MOVED, tab, null, null);
946 >                if (tabAt(tab, i) != f || (f.hash & LOCKED) == 0)
947 >                    continue;      // recheck before adding to list
948 >                buffer[nbuffered++] = i;
949 >                setTabAt(nextTab, i, rev);     // install place-holders
950 >                setTabAt(nextTab, i + n, rev);
951              }
846        }
952  
953 <        /** Helper for containsValue */
954 <        final boolean containsVal(Object value) {
955 <            if (value != null) {
956 <                Node e;
957 <                while ((e = next) != null) {
853 <                    Object v = nextVal;
854 <                    if (value == v || value.equals(v))
855 <                        return true;
856 <                    advance(e.next);
857 <                }
953 >            if (bin > 0)
954 >                i = --bin;
955 >            else if (buffer != null && nbuffered > 0) {
956 >                bin = -1;
957 >                i = buffer[bufferIndex = --nbuffered];
958              }
959 <            return false;
959 >            else
960 >                return nextTab;
961          }
962 +    }
963  
964 <        /** Helper for Map.hashCode */
863 <        final int mapHashCode() {
864 <            int h = 0;
865 <            Node e;
866 <            while ((e = next) != null) {
867 <                h += e.key.hashCode() ^ nextVal.hashCode();
868 <                advance(e.next);
869 <            }
870 <            return h;
871 <        }
964 >    /* ----------------Table Traversal -------------- */
965  
966 <        /** Helper for Map.toString */
967 <        final String mapToString() {
968 <            Node e = next;
969 <            if (e == null)
970 <                return "{}";
971 <            StringBuilder sb = new StringBuilder();
972 <            sb.append('{');
973 <            for (;;) {
974 <                sb.append(e.key   == this ? "(this Map)" : e.key);
975 <                sb.append('=');
976 <                sb.append(nextVal == this ? "(this Map)" : nextVal);
977 <                advance(e.next);
978 <                if ((e = next) != null)
979 <                    sb.append(',').append(' ');
980 <                else
981 <                    return sb.append('}').toString();
982 <            }
966 >    /**
967 >     * Encapsulates traversal for methods such as containsValue; also
968 >     * serves as a base class for other iterators.
969 >     *
970 >     * At each step, the iterator snapshots the key ("nextKey") and
971 >     * value ("nextVal") of a valid node (i.e., one that, at point of
972 >     * snapshot, has a nonnull user value). Because val fields can
973 >     * change (including to null, indicating deletion), field nextVal
974 >     * might not be accurate at point of use, but still maintains the
975 >     * weak consistency property of holding a value that was once
976 >     * valid.
977 >     *
978 >     * Internal traversals directly access these fields, as in:
979 >     * {@code while (it.next != null) { process(it.nextKey); it.advance(); }}
980 >     *
981 >     * Exported iterators (subclasses of ViewIterator) extract key,
982 >     * value, or key-value pairs as return values of Iterator.next(),
983 >     * and encapsulate the it.next check as hasNext();
984 >     *
985 >     * The iterator visits each valid node that was reachable upon
986 >     * iterator construction once. It might miss some that were added
987 >     * to a bin after the bin was visited, which is OK wrt consistency
988 >     * guarantees. Maintaining this property in the face of possible
989 >     * ongoing resizes requires a fair amount of bookkeeping state
990 >     * that is difficult to optimize away amidst volatile accesses.
991 >     * Even so, traversal maintains reasonable throughput.
992 >     *
993 >     * Normally, iteration proceeds bin-by-bin traversing lists.
994 >     * However, if the table has been resized, then all future steps
995 >     * must traverse both the bin at the current index as well as at
996 >     * (index + baseSize); and so on for further resizings. To
997 >     * paranoically cope with potential sharing by users of iterators
998 >     * across threads, iteration terminates if a bounds checks fails
999 >     * for a table read.
1000 >     *
1001 >     * The range-based constructor enables creation of parallel
1002 >     * range-splitting traversals. (Not yet implemented.)
1003 >     */
1004 >    static class InternalIterator {
1005 >        Node next;           // the next entry to use
1006 >        Node last;           // the last entry used
1007 >        Object nextKey;      // cached key field of next
1008 >        Object nextVal;      // cached val field of next
1009 >        Node[] tab;          // current table; updated if resized
1010 >        int index;           // index of bin to use next
1011 >        int baseIndex;       // current index of initial table
1012 >        final int baseLimit; // index bound for initial table
1013 >        final int baseSize;  // initial table size
1014 >
1015 >        /** Creates iterator for all entries in the table. */
1016 >        InternalIterator(Node[] tab) {
1017 >            this.tab = tab;
1018 >            baseLimit = baseSize = (tab == null) ? 0 : tab.length;
1019 >            index = baseIndex = 0;
1020 >            next = null;
1021 >            advance();
1022 >        }
1023 >
1024 >        /** Creates iterator for the given range of the table */
1025 >        InternalIterator(Node[] tab, int lo, int hi) {
1026 >            this.tab = tab;
1027 >            baseSize = (tab == null) ? 0 : tab.length;
1028 >            baseLimit = (hi <= baseSize) ? hi : baseSize;
1029 >            index = baseIndex = lo;
1030 >            next = null;
1031 >            advance();
1032 >        }
1033 >
1034 >        /** Advances next. See above for explanation. */
1035 >        final void advance() {
1036 >            Node e = last = next;
1037 >            outer: do {
1038 >                if (e != null)                  // advance past used/skipped node
1039 >                    e = e.next;
1040 >                while (e == null) {             // get to next non-null bin
1041 >                    Node[] t; int b, i, n;      // checks must use locals
1042 >                    if ((b = baseIndex) >= baseLimit || (i = index) < 0 ||
1043 >                        (t = tab) == null || i >= (n = t.length))
1044 >                        break outer;
1045 >                    else if ((e = tabAt(t, i)) != null && e.hash == MOVED)
1046 >                        tab = (Node[])e.key;    // restarts due to null val
1047 >                    else                        // visit upper slots if present
1048 >                        index = (i += baseSize) < n ? i : (baseIndex = b + 1);
1049 >                }
1050 >                nextKey = e.key;
1051 >            } while ((nextVal = e.val) == null);// skip deleted or special nodes
1052 >            next = e;
1053          }
1054      }
1055  
1056      /* ---------------- Public operations -------------- */
1057  
1058      /**
1059 <     * Creates a new, empty map with the specified initial
897 <     * capacity, load factor and concurrency level.
898 <     *
899 <     * @param initialCapacity the initial capacity. The implementation
900 <     * performs internal sizing to accommodate this many elements.
901 <     * @param loadFactor  the load factor threshold, used to control resizing.
902 <     * Resizing may be performed when the average number of elements per
903 <     * bin exceeds this threshold.
904 <     * @param concurrencyLevel the estimated number of concurrently
905 <     * updating threads. The implementation may use this value as
906 <     * a sizing hint.
907 <     * @throws IllegalArgumentException if the initial capacity is
908 <     * negative or the load factor or concurrencyLevel are
909 <     * nonpositive.
1059 >     * Creates a new, empty map with the default initial table size (16),
1060       */
1061 <    public ConcurrentHashMapV8(int initialCapacity,
912 <                             float loadFactor, int concurrencyLevel) {
913 <        if (!(loadFactor > 0) || initialCapacity < 0 || concurrencyLevel <= 0)
914 <            throw new IllegalArgumentException();
915 <        this.initCap = initialCapacity;
916 <        this.loadFactor = loadFactor;
1061 >    public ConcurrentHashMapV8() {
1062          this.counter = new LongAdder();
1063      }
1064  
1065      /**
1066 <     * Creates a new, empty map with the specified initial capacity
1067 <     * and load factor and with the default concurrencyLevel (16).
1066 >     * Creates a new, empty map with an initial table size
1067 >     * accommodating the specified number of elements without the need
1068 >     * to dynamically resize.
1069       *
1070       * @param initialCapacity The implementation performs internal
1071       * sizing to accommodate this many elements.
926     * @param loadFactor  the load factor threshold, used to control resizing.
927     * Resizing may be performed when the average number of elements per
928     * bin exceeds this threshold.
1072       * @throws IllegalArgumentException if the initial capacity of
1073 <     * elements is negative or the load factor is nonpositive
931 <     *
932 <     * @since 1.6
1073 >     * elements is negative
1074       */
1075 <    public ConcurrentHashMapV8(int initialCapacity, float loadFactor) {
1076 <        this(initialCapacity, loadFactor, DEFAULT_CONCURRENCY_LEVEL);
1075 >    public ConcurrentHashMapV8(int initialCapacity) {
1076 >        if (initialCapacity < 0)
1077 >            throw new IllegalArgumentException();
1078 >        int cap = ((initialCapacity >= (MAXIMUM_CAPACITY >>> 1)) ?
1079 >                   MAXIMUM_CAPACITY :
1080 >                   tableSizeFor(initialCapacity + (initialCapacity >>> 1) + 1));
1081 >        this.counter = new LongAdder();
1082 >        this.sizeCtl = cap;
1083      }
1084  
1085      /**
1086 <     * Creates a new, empty map with the specified initial capacity,
940 <     * and with default load factor (0.75) and concurrencyLevel (16).
1086 >     * Creates a new map with the same mappings as the given map.
1087       *
1088 <     * @param initialCapacity the initial capacity. The implementation
943 <     * performs internal sizing to accommodate this many elements.
944 <     * @throws IllegalArgumentException if the initial capacity of
945 <     * elements is negative.
1088 >     * @param m the map
1089       */
1090 <    public ConcurrentHashMapV8(int initialCapacity) {
1091 <        this(initialCapacity, DEFAULT_LOAD_FACTOR, DEFAULT_CONCURRENCY_LEVEL);
1090 >    public ConcurrentHashMapV8(Map<? extends K, ? extends V> m) {
1091 >        this.counter = new LongAdder();
1092 >        this.sizeCtl = DEFAULT_CAPACITY;
1093 >        putAll(m);
1094      }
1095  
1096      /**
1097 <     * Creates a new, empty map with a default initial capacity (16),
1098 <     * load factor (0.75) and concurrencyLevel (16).
1097 >     * Creates a new, empty map with an initial table size based on
1098 >     * the given number of elements ({@code initialCapacity}) and
1099 >     * initial table density ({@code loadFactor}).
1100 >     *
1101 >     * @param initialCapacity the initial capacity. The implementation
1102 >     * performs internal sizing to accommodate this many elements,
1103 >     * given the specified load factor.
1104 >     * @param loadFactor the load factor (table density) for
1105 >     * establishing the initial table size
1106 >     * @throws IllegalArgumentException if the initial capacity of
1107 >     * elements is negative or the load factor is nonpositive
1108 >     *
1109 >     * @since 1.6
1110       */
1111 <    public ConcurrentHashMapV8() {
1112 <        this(DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR, DEFAULT_CONCURRENCY_LEVEL);
1111 >    public ConcurrentHashMapV8(int initialCapacity, float loadFactor) {
1112 >        this(initialCapacity, loadFactor, 1);
1113      }
1114  
1115      /**
1116 <     * Creates a new map with the same mappings as the given map.
1117 <     * The map is created with a capacity of 1.5 times the number
1118 <     * of mappings in the given map or 16 (whichever is greater),
1119 <     * and a default load factor (0.75) and concurrencyLevel (16).
1116 >     * Creates a new, empty map with an initial table size based on
1117 >     * the given number of elements ({@code initialCapacity}), table
1118 >     * density ({@code loadFactor}), and number of concurrently
1119 >     * updating threads ({@code concurrencyLevel}).
1120       *
1121 <     * @param m the map
1121 >     * @param initialCapacity the initial capacity. The implementation
1122 >     * performs internal sizing to accommodate this many elements,
1123 >     * given the specified load factor.
1124 >     * @param loadFactor the load factor (table density) for
1125 >     * establishing the initial table size
1126 >     * @param concurrencyLevel the estimated number of concurrently
1127 >     * updating threads. The implementation may use this value as
1128 >     * a sizing hint.
1129 >     * @throws IllegalArgumentException if the initial capacity is
1130 >     * negative or the load factor or concurrencyLevel are
1131 >     * nonpositive
1132       */
1133 <    public ConcurrentHashMapV8(Map<? extends K, ? extends V> m) {
1134 <        this(DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR, DEFAULT_CONCURRENCY_LEVEL);
1135 <        if (m == null)
1136 <            throw new NullPointerException();
1137 <        internalPutAll(m);
1133 >    public ConcurrentHashMapV8(int initialCapacity,
1134 >                               float loadFactor, int concurrencyLevel) {
1135 >        if (!(loadFactor > 0.0f) || initialCapacity < 0 || concurrencyLevel <= 0)
1136 >            throw new IllegalArgumentException();
1137 >        if (initialCapacity < concurrencyLevel)   // Use at least as many bins
1138 >            initialCapacity = concurrencyLevel;   // as estimated threads
1139 >        long size = (long)(1.0 + (long)initialCapacity / loadFactor);
1140 >        int cap =  ((size >= (long)MAXIMUM_CAPACITY) ?
1141 >                    MAXIMUM_CAPACITY: tableSizeFor((int)size));
1142 >        this.counter = new LongAdder();
1143 >        this.sizeCtl = cap;
1144      }
1145  
1146      /**
1147 <     * Returns {@code true} if this map contains no key-value mappings.
976 <     *
977 <     * @return {@code true} if this map contains no key-value mappings
1147 >     * {@inheritDoc}
1148       */
1149      public boolean isEmpty() {
1150          return counter.sum() <= 0L; // ignore transient negative values
1151      }
1152  
1153      /**
1154 <     * Returns the number of key-value mappings in this map.  If the
985 <     * map contains more than {@code Integer.MAX_VALUE} elements, returns
986 <     * {@code Integer.MAX_VALUE}.
987 <     *
988 <     * @return the number of key-value mappings in this map
1154 >     * {@inheritDoc}
1155       */
1156      public int size() {
1157          long n = counter.sum();
1158 <        return ((n >>> 31) == 0) ? (int)n : (n < 0L) ? 0 : Integer.MAX_VALUE;
1158 >        return ((n < 0L) ? 0 :
1159 >                (n > (long)Integer.MAX_VALUE) ? Integer.MAX_VALUE :
1160 >                (int)n);
1161 >    }
1162 >
1163 >    final long longSize() { // accurate version of size needed for views
1164 >        long n = counter.sum();
1165 >        return (n < 0L) ? 0L : n;
1166      }
1167  
1168      /**
# Line 1016 | Line 1189 | public class ConcurrentHashMapV8<K, V>
1189       * @param  key   possible key
1190       * @return {@code true} if and only if the specified object
1191       *         is a key in this table, as determined by the
1192 <     *         {@code equals} method; {@code false} otherwise.
1192 >     *         {@code equals} method; {@code false} otherwise
1193       * @throws NullPointerException if the specified key is null
1194       */
1195      public boolean containsKey(Object key) {
# Line 1027 | Line 1200 | public class ConcurrentHashMapV8<K, V>
1200  
1201      /**
1202       * Returns {@code true} if this map maps one or more keys to the
1203 <     * specified value. Note: This method requires a full internal
1204 <     * traversal of the hash table, and so is much slower than
1032 <     * method {@code containsKey}.
1203 >     * specified value. Note: This method may require a full traversal
1204 >     * of the map, and is much slower than method {@code containsKey}.
1205       *
1206       * @param value value whose presence in this map is to be tested
1207       * @return {@code true} if this map maps one or more keys to the
# Line 1039 | Line 1211 | public class ConcurrentHashMapV8<K, V>
1211      public boolean containsValue(Object value) {
1212          if (value == null)
1213              throw new NullPointerException();
1214 <        return new HashIterator().containsVal(value);
1214 >        Object v;
1215 >        InternalIterator it = new InternalIterator(table);
1216 >        while (it.next != null) {
1217 >            if ((v = it.nextVal) == value || value.equals(v))
1218 >                return true;
1219 >            it.advance();
1220 >        }
1221 >        return false;
1222      }
1223  
1224      /**
# Line 1105 | Line 1284 | public class ConcurrentHashMapV8<K, V>
1284      public void putAll(Map<? extends K, ? extends V> m) {
1285          if (m == null)
1286              throw new NullPointerException();
1287 <        internalPutAll(m);
1287 >        /*
1288 >         * If uninitialized, try to preallocate big enough table
1289 >         */
1290 >        if (table == null) {
1291 >            int size = m.size();
1292 >            int n = (size >= (MAXIMUM_CAPACITY >>> 1)) ? MAXIMUM_CAPACITY :
1293 >                tableSizeFor(size + (size >>> 1) + 1);
1294 >            int sc = sizeCtl;
1295 >            if (n < sc)
1296 >                n = sc;
1297 >            if (sc >= 0 &&
1298 >                UNSAFE.compareAndSwapInt(this, sizeCtlOffset, sc, -1)) {
1299 >                try {
1300 >                    if (table == null) {
1301 >                        table = new Node[n];
1302 >                        sc = n - (n >>> 2) - 1;
1303 >                    }
1304 >                } finally {
1305 >                    sizeCtl = sc;
1306 >                }
1307 >            }
1308 >        }
1309 >        for (Map.Entry<? extends K, ? extends V> e : m.entrySet()) {
1310 >            Object ek = e.getKey(), ev = e.getValue();
1311 >            if (ek == null || ev == null)
1312 >                throw new NullPointerException();
1313 >            internalPut(ek, ev, true);
1314 >        }
1315      }
1316  
1317      /**
1318       * If the specified key is not already associated with a value,
1319       * computes its value using the given mappingFunction, and if
1320       * non-null, enters it into the map.  This is equivalent to
1321 <     *
1322 <     * <pre>
1323 <     *   if (map.containsKey(key))
1324 <     *       return map.get(key);
1325 <     *   value = mappingFunction.map(key);
1326 <     *   if (value != null)
1327 <     *      map.put(key, value);
1122 <     *   return value;
1123 <     * </pre>
1321 >     *  <pre> {@code
1322 >     * if (map.containsKey(key))
1323 >     *   return map.get(key);
1324 >     * value = mappingFunction.map(key);
1325 >     * if (value != null)
1326 >     *   map.put(key, value);
1327 >     * return value;}</pre>
1328       *
1329       * except that the action is performed atomically.  Some attempted
1330       * update operations on this map by other threads may be blocked
# Line 1129 | Line 1333 | public class ConcurrentHashMapV8<K, V>
1333       * mappings of this Map. The most appropriate usage is to
1334       * construct a new object serving as an initial mapped value, or
1335       * memoized result, as in:
1336 <     * <pre>{@code
1336 >     *  <pre> {@code
1337       * map.computeIfAbsent(key, new MappingFunction<K, V>() {
1338 <     *   public V map(K k) { return new Value(f(k)); }};
1135 <     * }</pre>
1338 >     *   public V map(K k) { return new Value(f(k)); }});}</pre>
1339       *
1340       * @param key key with which the specified value is to be associated
1341       * @param mappingFunction the function to compute a value
1342       * @return the current (existing or computed) value associated with
1343       *         the specified key, or {@code null} if the computation
1344 <     *         returned {@code null}.
1344 >     *         returned {@code null}
1345       * @throws NullPointerException if the specified key or mappingFunction
1346 <     *         is null,
1346 >     *         is null
1347       * @throws IllegalStateException if the computation detectably
1348       *         attempts a recursive update to this map that would
1349 <     *         otherwise never complete.
1349 >     *         otherwise never complete
1350       * @throws RuntimeException or Error if the mappingFunction does so,
1351 <     *         in which case the mapping is left unestablished.
1351 >     *         in which case the mapping is left unestablished
1352       */
1353      public V computeIfAbsent(K key, MappingFunction<? super K, ? extends V> mappingFunction) {
1354          if (key == null || mappingFunction == null)
# Line 1157 | Line 1360 | public class ConcurrentHashMapV8<K, V>
1360       * Computes the value associated with the given key using the given
1361       * mappingFunction, and if non-null, enters it into the map.  This
1362       * is equivalent to
1363 <     *
1364 <     * <pre>
1365 <     *   value = mappingFunction.map(key);
1366 <     *   if (value != null)
1367 <     *      map.put(key, value);
1368 <     *   else
1369 <     *      value = map.get(key);
1167 <     *   return value;
1168 <     * </pre>
1363 >     *  <pre> {@code
1364 >     * value = mappingFunction.map(key);
1365 >     * if (value != null)
1366 >     *   map.put(key, value);
1367 >     * else
1368 >     *   value = map.get(key);
1369 >     * return value;}</pre>
1370       *
1371       * except that the action is performed atomically.  Some attempted
1372       * update operations on this map by other threads may be blocked
# Line 1177 | Line 1378 | public class ConcurrentHashMapV8<K, V>
1378       * @param mappingFunction the function to compute a value
1379       * @return the current value associated with
1380       *         the specified key, or {@code null} if the computation
1381 <     *         returned {@code null} and the value was not otherwise present.
1381 >     *         returned {@code null} and the value was not otherwise present
1382       * @throws NullPointerException if the specified key or mappingFunction
1383 <     *         is null,
1383 >     *         is null
1384       * @throws IllegalStateException if the computation detectably
1385       *         attempts a recursive update to this map that would
1386 <     *         otherwise never complete.
1386 >     *         otherwise never complete
1387       * @throws RuntimeException or Error if the mappingFunction does so,
1388 <     *         in which case the mapping is unchanged.
1388 >     *         in which case the mapping is unchanged
1389       */
1390      public V compute(K key, MappingFunction<? super K, ? extends V> mappingFunction) {
1391          if (key == null || mappingFunction == null)
# Line 1270 | Line 1471 | public class ConcurrentHashMapV8<K, V>
1471       * reflect any modifications subsequent to construction.
1472       */
1473      public Set<K> keySet() {
1474 <        Set<K> ks = keySet;
1475 <        return (ks != null) ? ks : (keySet = new KeySet());
1474 >        KeySet<K,V> ks = keySet;
1475 >        return (ks != null) ? ks : (keySet = new KeySet<K,V>(this));
1476      }
1477  
1478      /**
# Line 1291 | Line 1492 | public class ConcurrentHashMapV8<K, V>
1492       * reflect any modifications subsequent to construction.
1493       */
1494      public Collection<V> values() {
1495 <        Collection<V> vs = values;
1496 <        return (vs != null) ? vs : (values = new Values());
1495 >        Values<K,V> vs = values;
1496 >        return (vs != null) ? vs : (values = new Values<K,V>(this));
1497      }
1498  
1499      /**
# Line 1312 | Line 1513 | public class ConcurrentHashMapV8<K, V>
1513       * reflect any modifications subsequent to construction.
1514       */
1515      public Set<Map.Entry<K,V>> entrySet() {
1516 <        Set<Map.Entry<K,V>> es = entrySet;
1517 <        return (es != null) ? es : (entrySet = new EntrySet());
1516 >        EntrySet<K,V> es = entrySet;
1517 >        return (es != null) ? es : (entrySet = new EntrySet<K,V>(this));
1518      }
1519  
1520      /**
# Line 1323 | Line 1524 | public class ConcurrentHashMapV8<K, V>
1524       * @see #keySet()
1525       */
1526      public Enumeration<K> keys() {
1527 <        return new KeyIterator();
1527 >        return new KeyIterator<K,V>(this);
1528      }
1529  
1530      /**
# Line 1333 | Line 1534 | public class ConcurrentHashMapV8<K, V>
1534       * @see #values()
1535       */
1536      public Enumeration<V> elements() {
1537 <        return new ValueIterator();
1537 >        return new ValueIterator<K,V>(this);
1538      }
1539  
1540      /**
# Line 1344 | Line 1545 | public class ConcurrentHashMapV8<K, V>
1545       * @return the hash code value for this map
1546       */
1547      public int hashCode() {
1548 <        return new HashIterator().mapHashCode();
1548 >        int h = 0;
1549 >        InternalIterator it = new InternalIterator(table);
1550 >        while (it.next != null) {
1551 >            h += it.nextKey.hashCode() ^ it.nextVal.hashCode();
1552 >            it.advance();
1553 >        }
1554 >        return h;
1555      }
1556  
1557      /**
# Line 1359 | Line 1566 | public class ConcurrentHashMapV8<K, V>
1566       * @return a string representation of this map
1567       */
1568      public String toString() {
1569 <        return new HashIterator().mapToString();
1569 >        InternalIterator it = new InternalIterator(table);
1570 >        StringBuilder sb = new StringBuilder();
1571 >        sb.append('{');
1572 >        if (it.next != null) {
1573 >            for (;;) {
1574 >                Object k = it.nextKey, v = it.nextVal;
1575 >                sb.append(k == this ? "(this Map)" : k);
1576 >                sb.append('=');
1577 >                sb.append(v == this ? "(this Map)" : v);
1578 >                it.advance();
1579 >                if (it.next == null)
1580 >                    break;
1581 >                sb.append(',').append(' ');
1582 >            }
1583 >        }
1584 >        return sb.append('}').toString();
1585      }
1586  
1587      /**
# Line 1373 | Line 1595 | public class ConcurrentHashMapV8<K, V>
1595       * @return {@code true} if the specified object is equal to this map
1596       */
1597      public boolean equals(Object o) {
1598 <        if (o == this)
1599 <            return true;
1600 <        if (!(o instanceof Map))
1601 <            return false;
1602 <        Map<?,?> m = (Map<?,?>) o;
1603 <        try {
1604 <            for (Map.Entry<K,V> e : this.entrySet())
1605 <                if (! e.getValue().equals(m.get(e.getKey())))
1598 >        if (o != this) {
1599 >            if (!(o instanceof Map))
1600 >                return false;
1601 >            Map<?,?> m = (Map<?,?>) o;
1602 >            InternalIterator it = new InternalIterator(table);
1603 >            while (it.next != null) {
1604 >                Object val = it.nextVal;
1605 >                Object v = m.get(it.nextKey);
1606 >                if (v == null || (v != val && !v.equals(val)))
1607                      return false;
1608 +                it.advance();
1609 +            }
1610              for (Map.Entry<?,?> e : m.entrySet()) {
1611 <                Object k = e.getKey();
1612 <                Object v = e.getValue();
1613 <                if (k == null || v == null || !v.equals(get(k)))
1611 >                Object mk, mv, v;
1612 >                if ((mk = e.getKey()) == null ||
1613 >                    (mv = e.getValue()) == null ||
1614 >                    (v = internalGet(mk)) == null ||
1615 >                    (mv != v && !mv.equals(v)))
1616                      return false;
1617              }
1391            return true;
1392        } catch (ClassCastException unused) {
1393            return false;
1394        } catch (NullPointerException unused) {
1395            return false;
1618          }
1619 +        return true;
1620      }
1621  
1622 +    /* ----------------Iterators -------------- */
1623 +
1624      /**
1625 <     * Custom Entry class used by EntryIterator.next(), that relays
1626 <     * setValue changes to the underlying map.
1625 >     * Base class for key, value, and entry iterators.  Adds a map
1626 >     * reference to InternalIterator to support Iterator.remove.
1627       */
1628 <    final class WriteThroughEntry extends AbstractMap.SimpleEntry<K,V> {
1628 >    static abstract class ViewIterator<K,V> extends InternalIterator {
1629 >        final ConcurrentHashMapV8<K, V> map;
1630 >        ViewIterator(ConcurrentHashMapV8<K, V> map) {
1631 >            super(map.table);
1632 >            this.map = map;
1633 >        }
1634 >
1635 >        public final void remove() {
1636 >            if (last == null)
1637 >                throw new IllegalStateException();
1638 >            map.remove(last.key);
1639 >            last = null;
1640 >        }
1641 >
1642 >        public final boolean hasNext()         { return next != null; }
1643 >        public final boolean hasMoreElements() { return next != null; }
1644 >    }
1645 >
1646 >    static final class KeyIterator<K,V> extends ViewIterator<K,V>
1647 >        implements Iterator<K>, Enumeration<K> {
1648 >        KeyIterator(ConcurrentHashMapV8<K, V> map) { super(map); }
1649 >
1650          @SuppressWarnings("unchecked")
1651 <        WriteThroughEntry(Object k, Object v) {
1652 <            super((K)k, (V)v);
1651 >        public final K next() {
1652 >            if (next == null)
1653 >                throw new NoSuchElementException();
1654 >            Object k = nextKey;
1655 >            advance();
1656 >            return (K)k;
1657 >        }
1658 >
1659 >        public final K nextElement() { return next(); }
1660 >    }
1661 >
1662 >    static final class ValueIterator<K,V> extends ViewIterator<K,V>
1663 >        implements Iterator<V>, Enumeration<V> {
1664 >        ValueIterator(ConcurrentHashMapV8<K, V> map) { super(map); }
1665 >
1666 >        @SuppressWarnings("unchecked")
1667 >        public final V next() {
1668 >            if (next == null)
1669 >                throw new NoSuchElementException();
1670 >            Object v = nextVal;
1671 >            advance();
1672 >            return (V)v;
1673 >        }
1674 >
1675 >        public final V nextElement() { return next(); }
1676 >    }
1677 >
1678 >    static final class EntryIterator<K,V> extends ViewIterator<K,V>
1679 >        implements Iterator<Map.Entry<K,V>> {
1680 >        EntryIterator(ConcurrentHashMapV8<K, V> map) { super(map); }
1681 >
1682 >        @SuppressWarnings("unchecked")
1683 >        public final Map.Entry<K,V> next() {
1684 >            if (next == null)
1685 >                throw new NoSuchElementException();
1686 >            Object k = nextKey;
1687 >            Object v = nextVal;
1688 >            advance();
1689 >            return new WriteThroughEntry<K,V>((K)k, (V)v, map);
1690 >        }
1691 >    }
1692 >
1693 >    static final class SnapshotEntryIterator<K,V> extends ViewIterator<K,V>
1694 >        implements Iterator<Map.Entry<K,V>> {
1695 >        SnapshotEntryIterator(ConcurrentHashMapV8<K, V> map) { super(map); }
1696 >
1697 >        @SuppressWarnings("unchecked")
1698 >        public final Map.Entry<K,V> next() {
1699 >            if (next == null)
1700 >                throw new NoSuchElementException();
1701 >            Object k = nextKey;
1702 >            Object v = nextVal;
1703 >            advance();
1704 >            return new SnapshotEntry<K,V>((K)k, (V)v);
1705 >        }
1706 >    }
1707 >
1708 >    /**
1709 >     * Base of writeThrough and Snapshot entry classes
1710 >     */
1711 >    static abstract class MapEntry<K,V> implements Map.Entry<K, V> {
1712 >        final K key; // non-null
1713 >        V val;       // non-null
1714 >        MapEntry(K key, V val)        { this.key = key; this.val = val; }
1715 >        public final K getKey()       { return key; }
1716 >        public final V getValue()     { return val; }
1717 >        public final int hashCode()   { return key.hashCode() ^ val.hashCode(); }
1718 >        public final String toString(){ return key + "=" + val; }
1719 >
1720 >        public final boolean equals(Object o) {
1721 >            Object k, v; Map.Entry<?,?> e;
1722 >            return ((o instanceof Map.Entry) &&
1723 >                    (k = (e = (Map.Entry<?,?>)o).getKey()) != null &&
1724 >                    (v = e.getValue()) != null &&
1725 >                    (k == key || k.equals(key)) &&
1726 >                    (v == val || v.equals(val)));
1727 >        }
1728 >
1729 >        public abstract V setValue(V value);
1730 >    }
1731 >
1732 >    /**
1733 >     * Entry used by EntryIterator.next(), that relays setValue
1734 >     * changes to the underlying map.
1735 >     */
1736 >    static final class WriteThroughEntry<K,V> extends MapEntry<K,V>
1737 >        implements Map.Entry<K, V> {
1738 >        final ConcurrentHashMapV8<K, V> map;
1739 >        WriteThroughEntry(K key, V val, ConcurrentHashMapV8<K, V> map) {
1740 >            super(key, val);
1741 >            this.map = map;
1742          }
1743  
1744          /**
# Line 1415 | Line 1750 | public class ConcurrentHashMapV8<K, V>
1750           * removed in which case the put will re-establish). We do not
1751           * and cannot guarantee more.
1752           */
1753 <        public V setValue(V value) {
1753 >        public final V setValue(V value) {
1754              if (value == null) throw new NullPointerException();
1755 <            V v = super.setValue(value);
1756 <            ConcurrentHashMapV8.this.put(getKey(), value);
1755 >            V v = val;
1756 >            val = value;
1757 >            map.put(key, value);
1758              return v;
1759          }
1760      }
1761  
1762 <    final class KeyIterator extends HashIterator
1763 <        implements Iterator<K>, Enumeration<K> {
1764 <        @SuppressWarnings("unchecked")
1765 <        public final K next()        { return (K)super.nextKey(); }
1766 <        @SuppressWarnings("unchecked")
1767 <        public final K nextElement() { return (K)super.nextKey(); }
1762 >    /**
1763 >     * Internal version of entry, that doesn't write though changes
1764 >     */
1765 >    static final class SnapshotEntry<K,V> extends MapEntry<K,V>
1766 >        implements Map.Entry<K, V> {
1767 >        SnapshotEntry(K key, V val) { super(key, val); }
1768 >        public final V setValue(V value) { // only locally update
1769 >            if (value == null) throw new NullPointerException();
1770 >            V v = val;
1771 >            val = value;
1772 >            return v;
1773 >        }
1774      }
1775  
1776 <    final class ValueIterator extends HashIterator
1777 <        implements Iterator<V>, Enumeration<V> {
1778 <        @SuppressWarnings("unchecked")
1779 <        public final V next()        { return (V)super.nextValue(); }
1776 >    /* ----------------Views -------------- */
1777 >
1778 >    /**
1779 >     * Base class for views. This is done mainly to allow adding
1780 >     * customized parallel traversals (not yet implemented.)
1781 >     */
1782 >    static abstract class MapView<K, V> {
1783 >        final ConcurrentHashMapV8<K, V> map;
1784 >        MapView(ConcurrentHashMapV8<K, V> map)  { this.map = map; }
1785 >        public final int size()                 { return map.size(); }
1786 >        public final boolean isEmpty()          { return map.isEmpty(); }
1787 >        public final void clear()               { map.clear(); }
1788 >
1789 >        // implementations below rely on concrete classes supplying these
1790 >        abstract Iterator<?> iter();
1791 >        abstract public boolean contains(Object o);
1792 >        abstract public boolean remove(Object o);
1793 >
1794 >        private static final String oomeMsg = "Required array size too large";
1795 >
1796 >        public final Object[] toArray() {
1797 >            long sz = map.longSize();
1798 >            if (sz > (long)(MAX_ARRAY_SIZE))
1799 >                throw new OutOfMemoryError(oomeMsg);
1800 >            int n = (int)sz;
1801 >            Object[] r = new Object[n];
1802 >            int i = 0;
1803 >            Iterator<?> it = iter();
1804 >            while (it.hasNext()) {
1805 >                if (i == n) {
1806 >                    if (n >= MAX_ARRAY_SIZE)
1807 >                        throw new OutOfMemoryError(oomeMsg);
1808 >                    if (n >= MAX_ARRAY_SIZE - (MAX_ARRAY_SIZE >>> 1) - 1)
1809 >                        n = MAX_ARRAY_SIZE;
1810 >                    else
1811 >                        n += (n >>> 1) + 1;
1812 >                    r = Arrays.copyOf(r, n);
1813 >                }
1814 >                r[i++] = it.next();
1815 >            }
1816 >            return (i == n) ? r : Arrays.copyOf(r, i);
1817 >        }
1818 >
1819          @SuppressWarnings("unchecked")
1820 <        public final V nextElement() { return (V)super.nextValue(); }
1821 <    }
1820 >        public final <T> T[] toArray(T[] a) {
1821 >            long sz = map.longSize();
1822 >            if (sz > (long)(MAX_ARRAY_SIZE))
1823 >                throw new OutOfMemoryError(oomeMsg);
1824 >            int m = (int)sz;
1825 >            T[] r = (a.length >= m) ? a :
1826 >                (T[])java.lang.reflect.Array
1827 >                .newInstance(a.getClass().getComponentType(), m);
1828 >            int n = r.length;
1829 >            int i = 0;
1830 >            Iterator<?> it = iter();
1831 >            while (it.hasNext()) {
1832 >                if (i == n) {
1833 >                    if (n >= MAX_ARRAY_SIZE)
1834 >                        throw new OutOfMemoryError(oomeMsg);
1835 >                    if (n >= MAX_ARRAY_SIZE - (MAX_ARRAY_SIZE >>> 1) - 1)
1836 >                        n = MAX_ARRAY_SIZE;
1837 >                    else
1838 >                        n += (n >>> 1) + 1;
1839 >                    r = Arrays.copyOf(r, n);
1840 >                }
1841 >                r[i++] = (T)it.next();
1842 >            }
1843 >            if (a == r && i < n) {
1844 >                r[i] = null; // null-terminate
1845 >                return r;
1846 >            }
1847 >            return (i == n) ? r : Arrays.copyOf(r, i);
1848 >        }
1849  
1850 <    final class EntryIterator extends HashIterator
1851 <        implements Iterator<Entry<K,V>> {
1852 <        public final Map.Entry<K,V> next() { return super.nextEntry(); }
1853 <    }
1850 >        public final int hashCode() {
1851 >            int h = 0;
1852 >            for (Iterator<?> it = iter(); it.hasNext();)
1853 >                h += it.next().hashCode();
1854 >            return h;
1855 >        }
1856 >
1857 >        public final String toString() {
1858 >            StringBuilder sb = new StringBuilder();
1859 >            sb.append('[');
1860 >            Iterator<?> it = iter();
1861 >            if (it.hasNext()) {
1862 >                for (;;) {
1863 >                    Object e = it.next();
1864 >                    sb.append(e == this ? "(this Collection)" : e);
1865 >                    if (!it.hasNext())
1866 >                        break;
1867 >                    sb.append(',').append(' ');
1868 >                }
1869 >            }
1870 >            return sb.append(']').toString();
1871 >        }
1872  
1873 <    final class KeySet extends AbstractSet<K> {
1874 <        public int size() {
1875 <            return ConcurrentHashMapV8.this.size();
1873 >        public final boolean containsAll(Collection<?> c) {
1874 >            if (c != this) {
1875 >                for (Iterator<?> it = c.iterator(); it.hasNext();) {
1876 >                    Object e = it.next();
1877 >                    if (e == null || !contains(e))
1878 >                        return false;
1879 >                }
1880 >            }
1881 >            return true;
1882 >        }
1883 >
1884 >        public final boolean removeAll(Collection c) {
1885 >            boolean modified = false;
1886 >            for (Iterator<?> it = iter(); it.hasNext();) {
1887 >                if (c.contains(it.next())) {
1888 >                    it.remove();
1889 >                    modified = true;
1890 >                }
1891 >            }
1892 >            return modified;
1893          }
1894 <        public boolean isEmpty() {
1895 <            return ConcurrentHashMapV8.this.isEmpty();
1894 >
1895 >        public final boolean retainAll(Collection<?> c) {
1896 >            boolean modified = false;
1897 >            for (Iterator<?> it = iter(); it.hasNext();) {
1898 >                if (!c.contains(it.next())) {
1899 >                    it.remove();
1900 >                    modified = true;
1901 >                }
1902 >            }
1903 >            return modified;
1904 >        }
1905 >
1906 >    }
1907 >
1908 >    static final class KeySet<K,V> extends MapView<K,V> implements Set<K> {
1909 >        KeySet(ConcurrentHashMapV8<K, V> map)   { super(map); }
1910 >        public final boolean contains(Object o) { return map.containsKey(o); }
1911 >        public final boolean remove(Object o)   { return map.remove(o) != null; }
1912 >
1913 >        public final Iterator<K> iterator() {
1914 >            return new KeyIterator<K,V>(map);
1915          }
1916 <        public void clear() {
1917 <            ConcurrentHashMapV8.this.clear();
1916 >        final Iterator<?> iter() {
1917 >            return new KeyIterator<K,V>(map);
1918          }
1919 <        public Iterator<K> iterator() {
1920 <            return new KeyIterator();
1919 >        public final boolean add(K e) {
1920 >            throw new UnsupportedOperationException();
1921          }
1922 <        public boolean contains(Object o) {
1923 <            return ConcurrentHashMapV8.this.containsKey(o);
1922 >        public final boolean addAll(Collection<? extends K> c) {
1923 >            throw new UnsupportedOperationException();
1924          }
1925 <        public boolean remove(Object o) {
1926 <            return ConcurrentHashMapV8.this.remove(o) != null;
1925 >        public boolean equals(Object o) {
1926 >            Set<?> c;
1927 >            return ((o instanceof Set) &&
1928 >                    ((c = (Set<?>)o) == this ||
1929 >                     (containsAll(c) && c.containsAll(this))));
1930          }
1931      }
1932  
1933 <    final class Values extends AbstractCollection<V> {
1934 <        public int size() {
1935 <            return ConcurrentHashMapV8.this.size();
1933 >    static final class Values<K,V> extends MapView<K,V>
1934 >        implements Collection<V>  {
1935 >        Values(ConcurrentHashMapV8<K, V> map)   { super(map); }
1936 >        public final boolean contains(Object o) { return map.containsValue(o); }
1937 >
1938 >        public final boolean remove(Object o) {
1939 >            if (o != null) {
1940 >                Iterator<V> it = new ValueIterator<K,V>(map);
1941 >                while (it.hasNext()) {
1942 >                    if (o.equals(it.next())) {
1943 >                        it.remove();
1944 >                        return true;
1945 >                    }
1946 >                }
1947 >            }
1948 >            return false;
1949          }
1950 <        public boolean isEmpty() {
1951 <            return ConcurrentHashMapV8.this.isEmpty();
1950 >        public final Iterator<V> iterator() {
1951 >            return new ValueIterator<K,V>(map);
1952          }
1953 <        public void clear() {
1954 <            ConcurrentHashMapV8.this.clear();
1953 >        final Iterator<?> iter() {
1954 >            return new ValueIterator<K,V>(map);
1955          }
1956 <        public Iterator<V> iterator() {
1957 <            return new ValueIterator();
1956 >        public final boolean add(V e) {
1957 >            throw new UnsupportedOperationException();
1958          }
1959 <        public boolean contains(Object o) {
1960 <            return ConcurrentHashMapV8.this.containsValue(o);
1959 >        public final boolean addAll(Collection<? extends V> c) {
1960 >            throw new UnsupportedOperationException();
1961          }
1962      }
1963  
1964 <    final class EntrySet extends AbstractSet<Map.Entry<K,V>> {
1965 <        public int size() {
1966 <            return ConcurrentHashMapV8.this.size();
1964 >    static final class EntrySet<K,V>  extends MapView<K,V>
1965 >        implements Set<Map.Entry<K,V>> {
1966 >        EntrySet(ConcurrentHashMapV8<K, V> map) { super(map); }
1967 >
1968 >        public final boolean contains(Object o) {
1969 >            Object k, v, r; Map.Entry<?,?> e;
1970 >            return ((o instanceof Map.Entry) &&
1971 >                    (k = (e = (Map.Entry<?,?>)o).getKey()) != null &&
1972 >                    (r = map.get(k)) != null &&
1973 >                    (v = e.getValue()) != null &&
1974 >                    (v == r || v.equals(r)));
1975          }
1976 <        public boolean isEmpty() {
1977 <            return ConcurrentHashMapV8.this.isEmpty();
1976 >
1977 >        public final boolean remove(Object o) {
1978 >            Object k, v; Map.Entry<?,?> e;
1979 >            return ((o instanceof Map.Entry) &&
1980 >                    (k = (e = (Map.Entry<?,?>)o).getKey()) != null &&
1981 >                    (v = e.getValue()) != null &&
1982 >                    map.remove(k, v));
1983          }
1984 <        public void clear() {
1985 <            ConcurrentHashMapV8.this.clear();
1984 >
1985 >        public final Iterator<Map.Entry<K,V>> iterator() {
1986 >            return new EntryIterator<K,V>(map);
1987          }
1988 <        public Iterator<Map.Entry<K,V>> iterator() {
1989 <            return new EntryIterator();
1988 >        final Iterator<?> iter() {
1989 >            return new SnapshotEntryIterator<K,V>(map);
1990          }
1991 <        public boolean contains(Object o) {
1992 <            if (!(o instanceof Map.Entry))
1501 <                return false;
1502 <            Map.Entry<?,?> e = (Map.Entry<?,?>)o;
1503 <            V v = ConcurrentHashMapV8.this.get(e.getKey());
1504 <            return v != null && v.equals(e.getValue());
1991 >        public final boolean add(Entry<K,V> e) {
1992 >            throw new UnsupportedOperationException();
1993          }
1994 <        public boolean remove(Object o) {
1995 <            if (!(o instanceof Map.Entry))
1996 <                return false;
1997 <            Map.Entry<?,?> e = (Map.Entry<?,?>)o;
1998 <            return ConcurrentHashMapV8.this.remove(e.getKey(), e.getValue());
1994 >        public final boolean addAll(Collection<? extends Entry<K,V>> c) {
1995 >            throw new UnsupportedOperationException();
1996 >        }
1997 >        public boolean equals(Object o) {
1998 >            Set<?> c;
1999 >            return ((o instanceof Set) &&
2000 >                    ((c = (Set<?>)o) == this ||
2001 >                     (containsAll(c) && c.containsAll(this))));
2002          }
2003      }
2004  
2005      /* ---------------- Serialization Support -------------- */
2006  
2007      /**
2008 <     * Helper class used in previous version, declared for the sake of
2009 <     * serialization compatibility
2008 >     * Stripped-down version of helper class used in previous version,
2009 >     * declared for the sake of serialization compatibility
2010       */
2011 <    static class Segment<K,V> extends java.util.concurrent.locks.ReentrantLock
1521 <        implements Serializable {
2011 >    static class Segment<K,V> implements Serializable {
2012          private static final long serialVersionUID = 2249069246763182397L;
2013          final float loadFactor;
2014          Segment(float lf) { this.loadFactor = lf; }
# Line 1540 | Line 2030 | public class ConcurrentHashMapV8<K, V>
2030              segments = (Segment<K,V>[])
2031                  new Segment<?,?>[DEFAULT_CONCURRENCY_LEVEL];
2032              for (int i = 0; i < segments.length; ++i)
2033 <                segments[i] = new Segment<K,V>(loadFactor);
2033 >                segments[i] = new Segment<K,V>(LOAD_FACTOR);
2034          }
2035          s.defaultWriteObject();
2036 <        new HashIterator().writeEntries(s);
2036 >        InternalIterator it = new InternalIterator(table);
2037 >        while (it.next != null) {
2038 >            s.writeObject(it.nextKey);
2039 >            s.writeObject(it.nextVal);
2040 >            it.advance();
2041 >        }
2042          s.writeObject(null);
2043          s.writeObject(null);
2044          segments = null; // throw away
2045      }
2046  
2047      /**
2048 <     * Reconstitutes the  instance from a
1554 <     * stream (i.e., deserializes it).
2048 >     * Reconstitutes the instance from a stream (that is, deserializes it).
2049       * @param s the stream
2050       */
2051      @SuppressWarnings("unchecked")
2052      private void readObject(java.io.ObjectInputStream s)
2053              throws java.io.IOException, ClassNotFoundException {
2054          s.defaultReadObject();
1561        // find load factor in a segment, if one exists
1562        if (segments != null && segments.length != 0)
1563            this.loadFactor = segments[0].loadFactor;
1564        else
1565            this.loadFactor = DEFAULT_LOAD_FACTOR;
1566        this.initCap = DEFAULT_CAPACITY;
1567        LongAdder ct = new LongAdder(); // force final field write
1568        UNSAFE.putObjectVolatile(this, counterOffset, ct);
2055          this.segments = null; // unneeded
2056 +        // initialize transient final field
2057 +        UNSAFE.putObjectVolatile(this, counterOffset, new LongAdder());
2058  
2059 <        // Read the keys and values, and put the mappings in the table
2059 >        // Create all nodes, then place in table once size is known
2060 >        long size = 0L;
2061 >        Node p = null;
2062          for (;;) {
2063 <            K key = (K) s.readObject();
2064 <            V value = (V) s.readObject();
2065 <            if (key == null)
2063 >            K k = (K) s.readObject();
2064 >            V v = (V) s.readObject();
2065 >            if (k != null && v != null) {
2066 >                p = new Node(spread(k.hashCode()), k, v, p);
2067 >                ++size;
2068 >            }
2069 >            else
2070                  break;
2071 <            put(key, value);
2071 >        }
2072 >        if (p != null) {
2073 >            boolean init = false;
2074 >            int n;
2075 >            if (size >= (long)(MAXIMUM_CAPACITY >>> 1))
2076 >                n = MAXIMUM_CAPACITY;
2077 >            else {
2078 >                int sz = (int)size;
2079 >                n = tableSizeFor(sz + (sz >>> 1) + 1);
2080 >            }
2081 >            int sc = sizeCtl;
2082 >            if (n > sc &&
2083 >                UNSAFE.compareAndSwapInt(this, sizeCtlOffset, sc, -1)) {
2084 >                try {
2085 >                    if (table == null) {
2086 >                        init = true;
2087 >                        Node[] tab = new Node[n];
2088 >                        int mask = n - 1;
2089 >                        while (p != null) {
2090 >                            int j = p.hash & mask;
2091 >                            Node next = p.next;
2092 >                            p.next = tabAt(tab, j);
2093 >                            setTabAt(tab, j, p);
2094 >                            p = next;
2095 >                        }
2096 >                        table = tab;
2097 >                        counter.add(size);
2098 >                        sc = n - (n >>> 2) - 1;
2099 >                    }
2100 >                } finally {
2101 >                    sizeCtl = sc;
2102 >                }
2103 >            }
2104 >            if (!init) { // Can only happen if unsafely published.
2105 >                while (p != null) {
2106 >                    internalPut(p.key, p.val, true);
2107 >                    p = p.next;
2108 >                }
2109 >            }
2110          }
2111      }
2112  
2113      // Unsafe mechanics
2114      private static final sun.misc.Unsafe UNSAFE;
2115      private static final long counterOffset;
2116 <    private static final long resizingOffset;
2116 >    private static final long sizeCtlOffset;
2117      private static final long ABASE;
2118      private static final int ASHIFT;
2119  
# Line 1592 | Line 2124 | public class ConcurrentHashMapV8<K, V>
2124              Class<?> k = ConcurrentHashMapV8.class;
2125              counterOffset = UNSAFE.objectFieldOffset
2126                  (k.getDeclaredField("counter"));
2127 <            resizingOffset = UNSAFE.objectFieldOffset
2128 <                (k.getDeclaredField("resizing"));
2127 >            sizeCtlOffset = UNSAFE.objectFieldOffset
2128 >                (k.getDeclaredField("sizeCtl"));
2129              Class<?> sc = Node[].class;
2130              ABASE = UNSAFE.arrayBaseOffset(sc);
2131              ss = UNSAFE.arrayIndexScale(sc);

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines