ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jsr166e/ConcurrentHashMapV8.java
Revision: 1.69
Committed: Sun Oct 21 06:14:11 2012 UTC (11 years, 6 months ago) by jsr166
Branch: MAIN
Changes since 1.68: +0 -3 lines
Log Message:
delete trailing empty lines of javadoc

File Contents

# User Rev Content
1 dl 1.1 /*
2     * Written by Doug Lea with assistance from members of JCP JSR-166
3     * Expert Group and released to the public domain, as explained at
4     * http://creativecommons.org/publicdomain/zero/1.0/
5     */
6    
7     package jsr166e;
8     import jsr166e.LongAdder;
9 dl 1.52 import jsr166e.ForkJoinPool;
10     import jsr166e.ForkJoinTask;
11    
12     import java.util.Comparator;
13 dl 1.24 import java.util.Arrays;
14 dl 1.1 import java.util.Map;
15     import java.util.Set;
16     import java.util.Collection;
17     import java.util.AbstractMap;
18     import java.util.AbstractSet;
19     import java.util.AbstractCollection;
20     import java.util.Hashtable;
21     import java.util.HashMap;
22     import java.util.Iterator;
23     import java.util.Enumeration;
24     import java.util.ConcurrentModificationException;
25     import java.util.NoSuchElementException;
26     import java.util.concurrent.ConcurrentMap;
27 dl 1.37 import java.util.concurrent.ThreadLocalRandom;
28 dl 1.24 import java.util.concurrent.locks.LockSupport;
29 dl 1.38 import java.util.concurrent.locks.AbstractQueuedSynchronizer;
30 dl 1.52 import java.util.concurrent.atomic.AtomicReference;
31    
32 dl 1.1 import java.io.Serializable;
33    
34     /**
35     * A hash table supporting full concurrency of retrievals and
36     * high expected concurrency for updates. This class obeys the
37     * same functional specification as {@link java.util.Hashtable}, and
38     * includes versions of methods corresponding to each method of
39     * {@code Hashtable}. However, even though all operations are
40     * thread-safe, retrieval operations do <em>not</em> entail locking,
41     * and there is <em>not</em> any support for locking the entire table
42     * in a way that prevents all access. This class is fully
43     * interoperable with {@code Hashtable} in programs that rely on its
44     * thread safety but not on its synchronization details.
45     *
46     * <p> Retrieval operations (including {@code get}) generally do not
47     * block, so may overlap with update operations (including {@code put}
48     * and {@code remove}). Retrievals reflect the results of the most
49     * recently <em>completed</em> update operations holding upon their
50 dl 1.59 * onset. (More formally, an update operation for a given key bears a
51     * <em>happens-before</em> relation with any (non-null) retrieval for
52     * that key reporting the updated value.) For aggregate operations
53     * such as {@code putAll} and {@code clear}, concurrent retrievals may
54     * reflect insertion or removal of only some entries. Similarly,
55     * Iterators and Enumerations return elements reflecting the state of
56     * the hash table at some point at or since the creation of the
57     * iterator/enumeration. They do <em>not</em> throw {@link
58     * ConcurrentModificationException}. However, iterators are designed
59     * to be used by only one thread at a time. Bear in mind that the
60     * results of aggregate status methods including {@code size}, {@code
61     * isEmpty}, and {@code containsValue} are typically useful only when
62     * a map is not undergoing concurrent updates in other threads.
63     * Otherwise the results of these methods reflect transient states
64     * that may be adequate for monitoring or estimation purposes, but not
65     * for program control.
66 dl 1.1 *
67 dl 1.16 * <p> The table is dynamically expanded when there are too many
68     * collisions (i.e., keys that have distinct hash codes but fall into
69     * the same slot modulo the table size), with the expected average
70 dl 1.24 * effect of maintaining roughly two bins per mapping (corresponding
71     * to a 0.75 load factor threshold for resizing). There may be much
72     * variance around this average as mappings are added and removed, but
73     * overall, this maintains a commonly accepted time/space tradeoff for
74     * hash tables. However, resizing this or any other kind of hash
75     * table may be a relatively slow operation. When possible, it is a
76     * good idea to provide a size estimate as an optional {@code
77 dl 1.16 * initialCapacity} constructor argument. An additional optional
78     * {@code loadFactor} constructor argument provides a further means of
79     * customizing initial table capacity by specifying the table density
80     * to be used in calculating the amount of space to allocate for the
81     * given number of elements. Also, for compatibility with previous
82     * versions of this class, constructors may optionally specify an
83     * expected {@code concurrencyLevel} as an additional hint for
84     * internal sizing. Note that using many keys with exactly the same
85 jsr166 1.31 * {@code hashCode()} is a sure way to slow down performance of any
86 dl 1.16 * hash table.
87 dl 1.1 *
88     * <p>This class and its views and iterators implement all of the
89     * <em>optional</em> methods of the {@link Map} and {@link Iterator}
90     * interfaces.
91     *
92     * <p> Like {@link Hashtable} but unlike {@link HashMap}, this class
93     * does <em>not</em> allow {@code null} to be used as a key or value.
94     *
95     * <p>This class is a member of the
96     * <a href="{@docRoot}/../technotes/guides/collections/index.html">
97     * Java Collections Framework</a>.
98     *
99     * <p><em>jsr166e note: This class is a candidate replacement for
100 dl 1.52 * java.util.concurrent.ConcurrentHashMap. During transition, this
101     * class declares and uses nested functional interfaces with different
102     * names but the same forms as those expected for JDK8.<em>
103 dl 1.1 *
104 jsr166 1.22 * @since 1.5
105 dl 1.1 * @author Doug Lea
106     * @param <K> the type of keys maintained by this map
107     * @param <V> the type of mapped values
108     */
109     public class ConcurrentHashMapV8<K, V>
110 dl 1.52 implements ConcurrentMap<K, V>, Serializable {
111 dl 1.1 private static final long serialVersionUID = 7249069246763182397L;
112    
113     /**
114 dl 1.41 * A partitionable iterator. A Spliterator can be traversed
115     * directly, but can also be partitioned (before traversal) by
116     * creating another Spliterator that covers a non-overlapping
117     * portion of the elements, and so may be amenable to parallel
118     * execution.
119     *
120     * <p> This interface exports a subset of expected JDK8
121     * functionality.
122     *
123     * <p>Sample usage: Here is one (of the several) ways to compute
124     * the sum of the values held in a map using the ForkJoin
125     * framework. As illustrated here, Spliterators are well suited to
126     * designs in which a task repeatedly splits off half its work
127     * into forked subtasks until small enough to process directly,
128 jsr166 1.44 * and then joins these subtasks. Variants of this style can also
129     * be used in completion-based designs.
130 dl 1.41 *
131     * <pre>
132     * {@code ConcurrentHashMapV8<String, Long> m = ...
133 dl 1.52 * // split as if have 8 * parallelism, for load balance
134     * int n = m.size();
135     * int p = aForkJoinPool.getParallelism() * 8;
136     * int split = (n < p)? n : p;
137     * long sum = aForkJoinPool.invoke(new SumValues(m.valueSpliterator(), split, null));
138 dl 1.41 * // ...
139     * static class SumValues extends RecursiveTask<Long> {
140     * final Spliterator<Long> s;
141 dl 1.52 * final int split; // split while > 1
142 dl 1.41 * final SumValues nextJoin; // records forked subtasks to join
143     * SumValues(Spliterator<Long> s, int depth, SumValues nextJoin) {
144     * this.s = s; this.depth = depth; this.nextJoin = nextJoin;
145     * }
146     * public Long compute() {
147     * long sum = 0;
148     * SumValues subtasks = null; // fork subtasks
149 dl 1.52 * for (int s = split >>> 1; s > 0; s >>>= 1)
150     * (subtasks = new SumValues(s.split(), s, subtasks)).fork();
151 dl 1.41 * while (s.hasNext()) // directly process remaining elements
152     * sum += s.next();
153     * for (SumValues t = subtasks; t != null; t = t.nextJoin)
154     * sum += t.join(); // collect subtask results
155     * return sum;
156     * }
157     * }
158     * }</pre>
159     */
160     public static interface Spliterator<T> extends Iterator<T> {
161     /**
162     * Returns a Spliterator covering approximately half of the
163     * elements, guaranteed not to overlap with those subsequently
164     * returned by this Spliterator. After invoking this method,
165     * the current Spliterator will <em>not</em> produce any of
166     * the elements of the returned Spliterator, but the two
167     * Spliterators together will produce all of the elements that
168     * would have been produced by this Spliterator had this
169     * method not been called. The exact number of elements
170     * produced by the returned Spliterator is not guaranteed, and
171     * may be zero (i.e., with {@code hasNext()} reporting {@code
172     * false}) if this Spliterator cannot be further split.
173     *
174     * @return a Spliterator covering approximately half of the
175     * elements
176     * @throws IllegalStateException if this Spliterator has
177 jsr166 1.45 * already commenced traversing elements
178 dl 1.41 */
179     Spliterator<T> split();
180     }
181    
182 dl 1.1 /*
183     * Overview:
184     *
185     * The primary design goal of this hash table is to maintain
186     * concurrent readability (typically method get(), but also
187     * iterators and related methods) while minimizing update
188 dl 1.24 * contention. Secondary goals are to keep space consumption about
189     * the same or better than java.util.HashMap, and to support high
190     * initial insertion rates on an empty table by many threads.
191 dl 1.1 *
192     * Each key-value mapping is held in a Node. Because Node fields
193     * can contain special values, they are defined using plain Object
194     * types. Similarly in turn, all internal methods that use them
195 dl 1.14 * work off Object types. And similarly, so do the internal
196     * methods of auxiliary iterator and view classes. All public
197     * generic typed methods relay in/out of these internal methods,
198 dl 1.27 * supplying null-checks and casts as needed. This also allows
199     * many of the public methods to be factored into a smaller number
200     * of internal methods (although sadly not so for the five
201 dl 1.38 * variants of put-related operations). The validation-based
202     * approach explained below leads to a lot of code sprawl because
203     * retry-control precludes factoring into smaller methods.
204 dl 1.1 *
205     * The table is lazily initialized to a power-of-two size upon the
206 dl 1.38 * first insertion. Each bin in the table normally contains a
207     * list of Nodes (most often, the list has only zero or one Node).
208     * Table accesses require volatile/atomic reads, writes, and
209     * CASes. Because there is no other way to arrange this without
210     * adding further indirections, we use intrinsics
211     * (sun.misc.Unsafe) operations. The lists of nodes within bins
212     * are always accurately traversable under volatile reads, so long
213     * as lookups check hash code and non-nullness of value before
214     * checking key equality.
215 dl 1.24 *
216     * We use the top two bits of Node hash fields for control
217     * purposes -- they are available anyway because of addressing
218     * constraints. As explained further below, these top bits are
219 dl 1.27 * used as follows:
220 dl 1.24 * 00 - Normal
221     * 01 - Locked
222     * 11 - Locked and may have a thread waiting for lock
223     * 10 - Node is a forwarding node
224     *
225     * The lower 30 bits of each Node's hash field contain a
226 dl 1.38 * transformation of the key's hash code, except for forwarding
227     * nodes, for which the lower bits are zero (and so always have
228     * hash field == MOVED).
229 dl 1.14 *
230 dl 1.27 * Insertion (via put or its variants) of the first node in an
231 dl 1.14 * empty bin is performed by just CASing it to the bin. This is
232 dl 1.38 * by far the most common case for put operations under most
233     * key/hash distributions. Other update operations (insert,
234     * delete, and replace) require locks. We do not want to waste
235     * the space required to associate a distinct lock object with
236     * each bin, so instead use the first node of a bin list itself as
237     * a lock. Blocking support for these locks relies on the builtin
238     * "synchronized" monitors. However, we also need a tryLock
239     * construction, so we overlay these by using bits of the Node
240     * hash field for lock control (see above), and so normally use
241     * builtin monitors only for blocking and signalling using
242     * wait/notifyAll constructions. See Node.tryAwaitLock.
243 dl 1.24 *
244     * Using the first node of a list as a lock does not by itself
245     * suffice though: When a node is locked, any update must first
246     * validate that it is still the first node after locking it, and
247     * retry if not. Because new nodes are always appended to lists,
248     * once a node is first in a bin, it remains first until deleted
249 dl 1.27 * or the bin becomes invalidated (upon resizing). However,
250     * operations that only conditionally update may inspect nodes
251     * until the point of update. This is a converse of sorts to the
252     * lazy locking technique described by Herlihy & Shavit.
253 dl 1.14 *
254 dl 1.24 * The main disadvantage of per-bin locks is that other update
255 dl 1.14 * operations on other nodes in a bin list protected by the same
256     * lock can stall, for example when user equals() or mapping
257 dl 1.38 * functions take a long time. However, statistically, under
258     * random hash codes, this is not a common problem. Ideally, the
259     * frequency of nodes in bins follows a Poisson distribution
260 dl 1.14 * (http://en.wikipedia.org/wiki/Poisson_distribution) with a
261 dl 1.16 * parameter of about 0.5 on average, given the resizing threshold
262     * of 0.75, although with a large variance because of resizing
263     * granularity. Ignoring variance, the expected occurrences of
264     * list size k are (exp(-0.5) * pow(0.5, k) / factorial(k)). The
265 dl 1.38 * first values are:
266 dl 1.16 *
267 dl 1.38 * 0: 0.60653066
268     * 1: 0.30326533
269     * 2: 0.07581633
270     * 3: 0.01263606
271     * 4: 0.00157952
272     * 5: 0.00015795
273     * 6: 0.00001316
274     * 7: 0.00000094
275     * 8: 0.00000006
276     * more: less than 1 in ten million
277 dl 1.16 *
278     * Lock contention probability for two threads accessing distinct
279 dl 1.38 * elements is roughly 1 / (8 * #elements) under random hashes.
280     *
281     * Actual hash code distributions encountered in practice
282     * sometimes deviate significantly from uniform randomness. This
283     * includes the case when N > (1<<30), so some keys MUST collide.
284     * Similarly for dumb or hostile usages in which multiple keys are
285     * designed to have identical hash codes. Also, although we guard
286     * against the worst effects of this (see method spread), sets of
287     * hashes may differ only in bits that do not impact their bin
288     * index for a given power-of-two mask. So we use a secondary
289     * strategy that applies when the number of nodes in a bin exceeds
290     * a threshold, and at least one of the keys implements
291     * Comparable. These TreeBins use a balanced tree to hold nodes
292     * (a specialized form of red-black trees), bounding search time
293     * to O(log N). Each search step in a TreeBin is around twice as
294     * slow as in a regular list, but given that N cannot exceed
295     * (1<<64) (before running out of addresses) this bounds search
296     * steps, lock hold times, etc, to reasonable constants (roughly
297     * 100 nodes inspected per operation worst case) so long as keys
298     * are Comparable (which is very common -- String, Long, etc).
299     * TreeBin nodes (TreeNodes) also maintain the same "next"
300     * traversal pointers as regular nodes, so can be traversed in
301     * iterators in the same way.
302 dl 1.1 *
303 dl 1.38 * The table is resized when occupancy exceeds a percentage
304 dl 1.24 * threshold (nominally, 0.75, but see below). Only a single
305     * thread performs the resize (using field "sizeCtl", to arrange
306     * exclusion), but the table otherwise remains usable for reads
307     * and updates. Resizing proceeds by transferring bins, one by
308     * one, from the table to the next table. Because we are using
309     * power-of-two expansion, the elements from each bin must either
310     * stay at same index, or move with a power of two offset. We
311     * eliminate unnecessary node creation by catching cases where old
312     * nodes can be reused because their next fields won't change. On
313     * average, only about one-sixth of them need cloning when a table
314     * doubles. The nodes they replace will be garbage collectable as
315     * soon as they are no longer referenced by any reader thread that
316     * may be in the midst of concurrently traversing table. Upon
317     * transfer, the old table bin contains only a special forwarding
318     * node (with hash field "MOVED") that contains the next table as
319     * its key. On encountering a forwarding node, access and update
320     * operations restart, using the new table.
321     *
322     * Each bin transfer requires its bin lock. However, unlike other
323     * cases, a transfer can skip a bin if it fails to acquire its
324 dl 1.38 * lock, and revisit it later (unless it is a TreeBin). Method
325     * rebuild maintains a buffer of TRANSFER_BUFFER_SIZE bins that
326     * have been skipped because of failure to acquire a lock, and
327     * blocks only if none are available (i.e., only very rarely).
328     * The transfer operation must also ensure that all accessible
329     * bins in both the old and new table are usable by any traversal.
330     * When there are no lock acquisition failures, this is arranged
331     * simply by proceeding from the last bin (table.length - 1) up
332     * towards the first. Upon seeing a forwarding node, traversals
333 dl 1.52 * (see class Iter) arrange to move to the new table
334 dl 1.38 * without revisiting nodes. However, when any node is skipped
335     * during a transfer, all earlier table bins may have become
336     * visible, so are initialized with a reverse-forwarding node back
337     * to the old table until the new ones are established. (This
338     * sometimes requires transiently locking a forwarding node, which
339     * is possible under the above encoding.) These more expensive
340 dl 1.24 * mechanics trigger only when necessary.
341 dl 1.14 *
342 dl 1.24 * The traversal scheme also applies to partial traversals of
343 dl 1.52 * ranges of bins (via an alternate Traverser constructor)
344 dl 1.41 * to support partitioned aggregate operations. Also, read-only
345     * operations give up if ever forwarded to a null table, which
346     * provides support for shutdown-style clearing, which is also not
347     * currently implemented.
348 dl 1.14 *
349     * Lazy table initialization minimizes footprint until first use,
350     * and also avoids resizings when the first operation is from a
351     * putAll, constructor with map argument, or deserialization.
352 dl 1.24 * These cases attempt to override the initial capacity settings,
353     * but harmlessly fail to take effect in cases of races.
354 dl 1.1 *
355     * The element count is maintained using a LongAdder, which avoids
356     * contention on updates but can encounter cache thrashing if read
357 dl 1.14 * too frequently during concurrent access. To avoid reading so
358 dl 1.27 * often, resizing is attempted either when a bin lock is
359     * contended, or upon adding to a bin already holding two or more
360     * nodes (checked before adding in the xIfAbsent methods, after
361     * adding in others). Under uniform hash distributions, the
362     * probability of this occurring at threshold is around 13%,
363     * meaning that only about 1 in 8 puts check threshold (and after
364     * resizing, many fewer do so). But this approximation has high
365     * variance for small table sizes, so we check on any collision
366     * for sizes <= 64. The bulk putAll operation further reduces
367     * contention by only committing count updates upon these size
368     * checks.
369 dl 1.14 *
370     * Maintaining API and serialization compatibility with previous
371     * versions of this class introduces several oddities. Mainly: We
372     * leave untouched but unused constructor arguments refering to
373 dl 1.24 * concurrencyLevel. We accept a loadFactor constructor argument,
374     * but apply it only to initial table capacity (which is the only
375     * time that we can guarantee to honor it.) We also declare an
376     * unused "Segment" class that is instantiated in minimal form
377     * only when serializing.
378 dl 1.1 */
379    
380     /* ---------------- Constants -------------- */
381    
382     /**
383 dl 1.16 * The largest possible table capacity. This value must be
384     * exactly 1<<30 to stay within Java array allocation and indexing
385 dl 1.24 * bounds for power of two table sizes, and is further required
386     * because the top two bits of 32bit hash fields are used for
387     * control purposes.
388 dl 1.1 */
389 dl 1.14 private static final int MAXIMUM_CAPACITY = 1 << 30;
390 dl 1.1
391     /**
392 dl 1.14 * The default initial table capacity. Must be a power of 2
393     * (i.e., at least 1) and at most MAXIMUM_CAPACITY.
394 dl 1.1 */
395 dl 1.14 private static final int DEFAULT_CAPACITY = 16;
396 dl 1.1
397     /**
398 dl 1.24 * The largest possible (non-power of two) array size.
399     * Needed by toArray and related methods.
400     */
401     static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
402    
403     /**
404     * The default concurrency level for this table. Unused but
405     * defined for compatibility with previous versions of this class.
406     */
407     private static final int DEFAULT_CONCURRENCY_LEVEL = 16;
408    
409     /**
410 dl 1.16 * The load factor for this table. Overrides of this value in
411     * constructors affect only the initial table capacity. The
412 dl 1.24 * actual floating point value isn't normally used -- it is
413     * simpler to use expressions such as {@code n - (n >>> 2)} for
414     * the associated resizing threshold.
415 dl 1.1 */
416 dl 1.16 private static final float LOAD_FACTOR = 0.75f;
417 dl 1.1
418     /**
419 dl 1.24 * The buffer size for skipped bins during transfers. The
420     * value is arbitrary but should be large enough to avoid
421     * most locking stalls during resizes.
422     */
423     private static final int TRANSFER_BUFFER_SIZE = 32;
424    
425 dl 1.38 /**
426     * The bin count threshold for using a tree rather than list for a
427     * bin. The value reflects the approximate break-even point for
428     * using tree-based operations.
429     */
430     private static final int TREE_THRESHOLD = 8;
431    
432 dl 1.24 /*
433     * Encodings for special uses of Node hash fields. See above for
434     * explanation.
435 dl 1.1 */
436 jsr166 1.35 static final int MOVED = 0x80000000; // hash field for forwarding nodes
437 dl 1.24 static final int LOCKED = 0x40000000; // set/tested only as a bit
438     static final int WAITING = 0xc0000000; // both bits set/tested together
439     static final int HASH_BITS = 0x3fffffff; // usable bits of normal node hash
440    
441     /* ---------------- Fields -------------- */
442    
443     /**
444     * The array of bins. Lazily initialized upon first insertion.
445     * Size is always a power of two. Accessed directly by iterators.
446     */
447     transient volatile Node[] table;
448 dl 1.14
449 dl 1.16 /**
450 dl 1.24 * The counter maintaining number of elements.
451 dl 1.16 */
452 dl 1.24 private transient final LongAdder counter;
453    
454     /**
455     * Table initialization and resizing control. When negative, the
456     * table is being initialized or resized. Otherwise, when table is
457     * null, holds the initial table size to use upon creation, or 0
458     * for default. After initialization, holds the next element count
459     * value upon which to resize the table.
460     */
461     private transient volatile int sizeCtl;
462    
463     // views
464     private transient KeySet<K,V> keySet;
465     private transient Values<K,V> values;
466     private transient EntrySet<K,V> entrySet;
467    
468     /** For serialization compatibility. Null unless serialized; see below */
469     private Segment<K,V>[] segments;
470 dl 1.16
471 dl 1.38 /* ---------------- Table element access -------------- */
472    
473     /*
474     * Volatile access methods are used for table elements as well as
475     * elements of in-progress next table while resizing. Uses are
476     * null checked by callers, and implicitly bounds-checked, relying
477     * on the invariants that tab arrays have non-zero size, and all
478     * indices are masked with (tab.length - 1) which is never
479     * negative and always less than length. Note that, to be correct
480     * wrt arbitrary concurrency errors by users, bounds checks must
481     * operate on local variables, which accounts for some odd-looking
482     * inline assignments below.
483     */
484    
485 dl 1.52 static final Node tabAt(Node[] tab, int i) { // used by Iter
486 dl 1.38 return (Node)UNSAFE.getObjectVolatile(tab, ((long)i<<ASHIFT)+ABASE);
487     }
488    
489     private static final boolean casTabAt(Node[] tab, int i, Node c, Node v) {
490     return UNSAFE.compareAndSwapObject(tab, ((long)i<<ASHIFT)+ABASE, c, v);
491     }
492    
493     private static final void setTabAt(Node[] tab, int i, Node v) {
494     UNSAFE.putObjectVolatile(tab, ((long)i<<ASHIFT)+ABASE, v);
495     }
496    
497 dl 1.14 /* ---------------- Nodes -------------- */
498 dl 1.1
499     /**
500 dl 1.14 * Key-value entry. Note that this is never exported out as a
501 dl 1.41 * user-visible Map.Entry (see MapEntry below). Nodes with a hash
502     * field of MOVED are special, and do not contain user keys or
503     * values. Otherwise, keys are never null, and null val fields
504     * indicate that a node is in the process of being deleted or
505     * created. For purposes of read-only access, a key may be read
506     * before a val, but can only be used after checking val to be
507     * non-null.
508 dl 1.1 */
509 dl 1.38 static class Node {
510 dl 1.24 volatile int hash;
511 dl 1.14 final Object key;
512     volatile Object val;
513     volatile Node next;
514    
515     Node(int hash, Object key, Object val, Node next) {
516     this.hash = hash;
517     this.key = key;
518     this.val = val;
519     this.next = next;
520     }
521    
522 dl 1.24 /** CompareAndSet the hash field */
523     final boolean casHash(int cmp, int val) {
524     return UNSAFE.compareAndSwapInt(this, hashOffset, cmp, val);
525     }
526 dl 1.1
527 dl 1.24 /** The number of spins before blocking for a lock */
528     static final int MAX_SPINS =
529     Runtime.getRuntime().availableProcessors() > 1 ? 64 : 1;
530 dl 1.1
531 dl 1.24 /**
532     * Spins a while if LOCKED bit set and this node is the first
533     * of its bin, and then sets WAITING bits on hash field and
534     * blocks (once) if they are still set. It is OK for this
535     * method to return even if lock is not available upon exit,
536     * which enables these simple single-wait mechanics.
537     *
538     * The corresponding signalling operation is performed within
539     * callers: Upon detecting that WAITING has been set when
540     * unlocking lock (via a failed CAS from non-waiting LOCKED
541     * state), unlockers acquire the sync lock and perform a
542     * notifyAll.
543 dl 1.61 *
544     * The initial sanity check on tab and bounds is not currently
545     * necessary in the only usages of this method, but enables
546     * use in other future contexts.
547 dl 1.24 */
548     final void tryAwaitLock(Node[] tab, int i) {
549 dl 1.61 if (tab != null && i >= 0 && i < tab.length) { // sanity check
550 dl 1.37 int r = ThreadLocalRandom.current().nextInt(); // randomize spins
551 dl 1.24 int spins = MAX_SPINS, h;
552     while (tabAt(tab, i) == this && ((h = hash) & LOCKED) != 0) {
553     if (spins >= 0) {
554 dl 1.37 r ^= r << 1; r ^= r >>> 3; r ^= r << 10; // xorshift
555     if (r >= 0 && --spins == 0)
556     Thread.yield(); // yield before block
557 dl 1.24 }
558     else if (casHash(h, h | WAITING)) {
559 jsr166 1.26 synchronized (this) {
560 dl 1.24 if (tabAt(tab, i) == this &&
561     (hash & WAITING) == WAITING) {
562     try {
563     wait();
564     } catch (InterruptedException ie) {
565     Thread.currentThread().interrupt();
566     }
567     }
568     else
569     notifyAll(); // possibly won race vs signaller
570     }
571     break;
572     }
573     }
574     }
575     }
576 dl 1.1
577 dl 1.24 // Unsafe mechanics for casHash
578     private static final sun.misc.Unsafe UNSAFE;
579     private static final long hashOffset;
580 dl 1.1
581 dl 1.24 static {
582     try {
583     UNSAFE = getUnsafe();
584     Class<?> k = Node.class;
585     hashOffset = UNSAFE.objectFieldOffset
586     (k.getDeclaredField("hash"));
587     } catch (Exception e) {
588     throw new Error(e);
589     }
590     }
591     }
592 dl 1.1
593 dl 1.38 /* ---------------- TreeBins -------------- */
594    
595     /**
596     * Nodes for use in TreeBins
597     */
598     static final class TreeNode extends Node {
599     TreeNode parent; // red-black tree links
600     TreeNode left;
601     TreeNode right;
602     TreeNode prev; // needed to unlink next upon deletion
603     boolean red;
604    
605     TreeNode(int hash, Object key, Object val, Node next, TreeNode parent) {
606     super(hash, key, val, next);
607     this.parent = parent;
608     }
609     }
610 dl 1.1
611 dl 1.38 /**
612     * A specialized form of red-black tree for use in bins
613     * whose size exceeds a threshold.
614     *
615     * TreeBins use a special form of comparison for search and
616     * related operations (which is the main reason we cannot use
617     * existing collections such as TreeMaps). TreeBins contain
618     * Comparable elements, but may contain others, as well as
619     * elements that are Comparable but not necessarily Comparable<T>
620     * for the same T, so we cannot invoke compareTo among them. To
621     * handle this, the tree is ordered primarily by hash value, then
622     * by getClass().getName() order, and then by Comparator order
623     * among elements of the same class. On lookup at a node, if
624 dl 1.41 * elements are not comparable or compare as 0, both left and
625     * right children may need to be searched in the case of tied hash
626     * values. (This corresponds to the full list search that would be
627     * necessary if all elements were non-Comparable and had tied
628     * hashes.) The red-black balancing code is updated from
629     * pre-jdk-collections
630     * (http://gee.cs.oswego.edu/dl/classes/collections/RBCell.java)
631     * based in turn on Cormen, Leiserson, and Rivest "Introduction to
632     * Algorithms" (CLR).
633 dl 1.38 *
634     * TreeBins also maintain a separate locking discipline than
635     * regular bins. Because they are forwarded via special MOVED
636     * nodes at bin heads (which can never change once established),
637 jsr166 1.51 * we cannot use those nodes as locks. Instead, TreeBin
638 dl 1.38 * extends AbstractQueuedSynchronizer to support a simple form of
639     * read-write lock. For update operations and table validation,
640     * the exclusive form of lock behaves in the same way as bin-head
641     * locks. However, lookups use shared read-lock mechanics to allow
642     * multiple readers in the absence of writers. Additionally,
643     * these lookups do not ever block: While the lock is not
644     * available, they proceed along the slow traversal path (via
645     * next-pointers) until the lock becomes available or the list is
646     * exhausted, whichever comes first. (These cases are not fast,
647     * but maximize aggregate expected throughput.) The AQS mechanics
648     * for doing this are straightforward. The lock state is held as
649     * AQS getState(). Read counts are negative; the write count (1)
650     * is positive. There are no signalling preferences among readers
651     * and writers. Since we don't need to export full Lock API, we
652     * just override the minimal AQS methods and use them directly.
653 dl 1.1 */
654 dl 1.38 static final class TreeBin extends AbstractQueuedSynchronizer {
655     private static final long serialVersionUID = 2249069246763182397L;
656 dl 1.41 transient TreeNode root; // root of tree
657     transient TreeNode first; // head of next-pointer list
658 dl 1.1
659 dl 1.38 /* AQS overrides */
660     public final boolean isHeldExclusively() { return getState() > 0; }
661     public final boolean tryAcquire(int ignore) {
662     if (compareAndSetState(0, 1)) {
663     setExclusiveOwnerThread(Thread.currentThread());
664     return true;
665     }
666     return false;
667     }
668     public final boolean tryRelease(int ignore) {
669     setExclusiveOwnerThread(null);
670     setState(0);
671     return true;
672     }
673     public final int tryAcquireShared(int ignore) {
674     for (int c;;) {
675     if ((c = getState()) > 0)
676     return -1;
677     if (compareAndSetState(c, c -1))
678     return 1;
679     }
680     }
681     public final boolean tryReleaseShared(int ignore) {
682     int c;
683     do {} while (!compareAndSetState(c = getState(), c + 1));
684     return c == -1;
685     }
686    
687 dl 1.41 /** From CLR */
688     private void rotateLeft(TreeNode p) {
689     if (p != null) {
690     TreeNode r = p.right, pp, rl;
691     if ((rl = p.right = r.left) != null)
692     rl.parent = p;
693     if ((pp = r.parent = p.parent) == null)
694     root = r;
695     else if (pp.left == p)
696     pp.left = r;
697     else
698     pp.right = r;
699     r.left = p;
700     p.parent = r;
701     }
702     }
703    
704     /** From CLR */
705     private void rotateRight(TreeNode p) {
706     if (p != null) {
707     TreeNode l = p.left, pp, lr;
708     if ((lr = p.left = l.right) != null)
709     lr.parent = p;
710     if ((pp = l.parent = p.parent) == null)
711     root = l;
712     else if (pp.right == p)
713     pp.right = l;
714     else
715     pp.left = l;
716     l.right = p;
717     p.parent = l;
718     }
719     }
720    
721 dl 1.38 /**
722 jsr166 1.56 * Returns the TreeNode (or null if not found) for the given key
723 dl 1.38 * starting at given root.
724     */
725 dl 1.61 @SuppressWarnings("unchecked") final TreeNode getTreeNode
726     (int h, Object k, TreeNode p) {
727 dl 1.38 Class<?> c = k.getClass();
728     while (p != null) {
729 dl 1.41 int dir, ph; Object pk; Class<?> pc;
730     if ((ph = p.hash) == h) {
731     if ((pk = p.key) == k || k.equals(pk))
732     return p;
733     if (c != (pc = pk.getClass()) ||
734     !(k instanceof Comparable) ||
735     (dir = ((Comparable)k).compareTo((Comparable)pk)) == 0) {
736 jsr166 1.42 dir = (c == pc) ? 0 : c.getName().compareTo(pc.getName());
737 dl 1.41 TreeNode r = null, s = null, pl, pr;
738     if (dir >= 0) {
739     if ((pl = p.left) != null && h <= pl.hash)
740     s = pl;
741     }
742     else if ((pr = p.right) != null && h >= pr.hash)
743     s = pr;
744     if (s != null && (r = getTreeNode(h, k, s)) != null)
745     return r;
746     }
747     }
748 dl 1.38 else
749 dl 1.41 dir = (h < ph) ? -1 : 1;
750     p = (dir > 0) ? p.right : p.left;
751 dl 1.38 }
752     return null;
753     }
754    
755     /**
756     * Wrapper for getTreeNode used by CHM.get. Tries to obtain
757     * read-lock to call getTreeNode, but during failure to get
758     * lock, searches along next links.
759     */
760     final Object getValue(int h, Object k) {
761     Node r = null;
762     int c = getState(); // Must read lock state first
763     for (Node e = first; e != null; e = e.next) {
764     if (c <= 0 && compareAndSetState(c, c - 1)) {
765     try {
766     r = getTreeNode(h, k, root);
767     } finally {
768     releaseShared(0);
769     }
770     break;
771     }
772     else if ((e.hash & HASH_BITS) == h && k.equals(e.key)) {
773     r = e;
774     break;
775     }
776     else
777     c = getState();
778     }
779     return r == null ? null : r.val;
780     }
781    
782     /**
783 jsr166 1.45 * Finds or adds a node.
784 dl 1.38 * @return null if added
785     */
786 dl 1.61 @SuppressWarnings("unchecked") final TreeNode putTreeNode
787     (int h, Object k, Object v) {
788 dl 1.38 Class<?> c = k.getClass();
789 dl 1.41 TreeNode pp = root, p = null;
790 dl 1.38 int dir = 0;
791 dl 1.41 while (pp != null) { // find existing node or leaf to insert at
792     int ph; Object pk; Class<?> pc;
793     p = pp;
794     if ((ph = p.hash) == h) {
795     if ((pk = p.key) == k || k.equals(pk))
796 dl 1.38 return p;
797 dl 1.41 if (c != (pc = pk.getClass()) ||
798     !(k instanceof Comparable) ||
799     (dir = ((Comparable)k).compareTo((Comparable)pk)) == 0) {
800 jsr166 1.42 dir = (c == pc) ? 0 : c.getName().compareTo(pc.getName());
801 dl 1.41 TreeNode r = null, s = null, pl, pr;
802     if (dir >= 0) {
803     if ((pl = p.left) != null && h <= pl.hash)
804     s = pl;
805     }
806     else if ((pr = p.right) != null && h >= pr.hash)
807     s = pr;
808     if (s != null && (r = getTreeNode(h, k, s)) != null)
809     return r;
810 dl 1.38 }
811     }
812 dl 1.41 else
813     dir = (h < ph) ? -1 : 1;
814     pp = (dir > 0) ? p.right : p.left;
815 dl 1.38 }
816 dl 1.41
817 dl 1.38 TreeNode f = first;
818 dl 1.41 TreeNode x = first = new TreeNode(h, k, v, f, p);
819 dl 1.38 if (p == null)
820 dl 1.41 root = x;
821     else { // attach and rebalance; adapted from CLR
822     TreeNode xp, xpp;
823     if (f != null)
824     f.prev = x;
825 dl 1.38 if (dir <= 0)
826 dl 1.41 p.left = x;
827 dl 1.38 else
828 dl 1.41 p.right = x;
829     x.red = true;
830     while (x != null && (xp = x.parent) != null && xp.red &&
831     (xpp = xp.parent) != null) {
832     TreeNode xppl = xpp.left;
833     if (xp == xppl) {
834     TreeNode y = xpp.right;
835     if (y != null && y.red) {
836     y.red = false;
837     xp.red = false;
838     xpp.red = true;
839     x = xpp;
840     }
841     else {
842     if (x == xp.right) {
843     rotateLeft(x = xp);
844     xpp = (xp = x.parent) == null ? null : xp.parent;
845     }
846     if (xp != null) {
847     xp.red = false;
848     if (xpp != null) {
849     xpp.red = true;
850     rotateRight(xpp);
851     }
852     }
853     }
854     }
855     else {
856     TreeNode y = xppl;
857     if (y != null && y.red) {
858     y.red = false;
859     xp.red = false;
860     xpp.red = true;
861     x = xpp;
862     }
863     else {
864     if (x == xp.left) {
865     rotateRight(x = xp);
866     xpp = (xp = x.parent) == null ? null : xp.parent;
867     }
868     if (xp != null) {
869     xp.red = false;
870     if (xpp != null) {
871     xpp.red = true;
872     rotateLeft(xpp);
873     }
874     }
875     }
876     }
877     }
878     TreeNode r = root;
879     if (r != null && r.red)
880     r.red = false;
881 dl 1.38 }
882     return null;
883     }
884 dl 1.1
885 dl 1.38 /**
886     * Removes the given node, that must be present before this
887     * call. This is messier than typical red-black deletion code
888     * because we cannot swap the contents of an interior node
889     * with a leaf successor that is pinned by "next" pointers
890     * that are accessible independently of lock. So instead we
891     * swap the tree linkages.
892     */
893     final void deleteTreeNode(TreeNode p) {
894     TreeNode next = (TreeNode)p.next; // unlink traversal pointers
895     TreeNode pred = p.prev;
896     if (pred == null)
897     first = next;
898     else
899     pred.next = next;
900     if (next != null)
901     next.prev = pred;
902     TreeNode replacement;
903     TreeNode pl = p.left;
904     TreeNode pr = p.right;
905     if (pl != null && pr != null) {
906 dl 1.41 TreeNode s = pr, sl;
907     while ((sl = s.left) != null) // find successor
908     s = sl;
909 dl 1.38 boolean c = s.red; s.red = p.red; p.red = c; // swap colors
910     TreeNode sr = s.right;
911     TreeNode pp = p.parent;
912     if (s == pr) { // p was s's direct parent
913     p.parent = s;
914     s.right = p;
915     }
916     else {
917     TreeNode sp = s.parent;
918     if ((p.parent = sp) != null) {
919     if (s == sp.left)
920     sp.left = p;
921     else
922     sp.right = p;
923     }
924     if ((s.right = pr) != null)
925     pr.parent = s;
926     }
927     p.left = null;
928     if ((p.right = sr) != null)
929     sr.parent = p;
930     if ((s.left = pl) != null)
931     pl.parent = s;
932     if ((s.parent = pp) == null)
933     root = s;
934     else if (p == pp.left)
935     pp.left = s;
936     else
937     pp.right = s;
938     replacement = sr;
939     }
940     else
941     replacement = (pl != null) ? pl : pr;
942     TreeNode pp = p.parent;
943     if (replacement == null) {
944     if (pp == null) {
945     root = null;
946     return;
947     }
948     replacement = p;
949     }
950     else {
951     replacement.parent = pp;
952     if (pp == null)
953     root = replacement;
954     else if (p == pp.left)
955     pp.left = replacement;
956     else
957     pp.right = replacement;
958     p.left = p.right = p.parent = null;
959     }
960 dl 1.41 if (!p.red) { // rebalance, from CLR
961     TreeNode x = replacement;
962     while (x != null) {
963     TreeNode xp, xpl;
964     if (x.red || (xp = x.parent) == null) {
965     x.red = false;
966     break;
967 dl 1.38 }
968 dl 1.41 if (x == (xpl = xp.left)) {
969     TreeNode sib = xp.right;
970     if (sib != null && sib.red) {
971     sib.red = false;
972     xp.red = true;
973     rotateLeft(xp);
974     sib = (xp = x.parent) == null ? null : xp.right;
975 dl 1.38 }
976 dl 1.41 if (sib == null)
977 dl 1.38 x = xp;
978     else {
979 dl 1.41 TreeNode sl = sib.left, sr = sib.right;
980     if ((sr == null || !sr.red) &&
981     (sl == null || !sl.red)) {
982 dl 1.38 sib.red = true;
983 dl 1.41 x = xp;
984 dl 1.38 }
985 dl 1.41 else {
986     if (sr == null || !sr.red) {
987     if (sl != null)
988     sl.red = false;
989     sib.red = true;
990     rotateRight(sib);
991     sib = (xp = x.parent) == null ? null : xp.right;
992     }
993     if (sib != null) {
994 jsr166 1.42 sib.red = (xp == null) ? false : xp.red;
995 dl 1.41 if ((sr = sib.right) != null)
996     sr.red = false;
997     }
998     if (xp != null) {
999     xp.red = false;
1000     rotateLeft(xp);
1001     }
1002     x = root;
1003 dl 1.38 }
1004     }
1005     }
1006 dl 1.41 else { // symmetric
1007     TreeNode sib = xpl;
1008     if (sib != null && sib.red) {
1009     sib.red = false;
1010     xp.red = true;
1011     rotateRight(xp);
1012     sib = (xp = x.parent) == null ? null : xp.left;
1013     }
1014     if (sib == null)
1015 dl 1.38 x = xp;
1016     else {
1017 dl 1.41 TreeNode sl = sib.left, sr = sib.right;
1018     if ((sl == null || !sl.red) &&
1019     (sr == null || !sr.red)) {
1020 dl 1.38 sib.red = true;
1021 dl 1.41 x = xp;
1022 dl 1.38 }
1023 dl 1.41 else {
1024     if (sl == null || !sl.red) {
1025     if (sr != null)
1026     sr.red = false;
1027     sib.red = true;
1028     rotateLeft(sib);
1029     sib = (xp = x.parent) == null ? null : xp.left;
1030     }
1031     if (sib != null) {
1032 jsr166 1.42 sib.red = (xp == null) ? false : xp.red;
1033 dl 1.41 if ((sl = sib.left) != null)
1034     sl.red = false;
1035     }
1036     if (xp != null) {
1037     xp.red = false;
1038     rotateRight(xp);
1039     }
1040     x = root;
1041 dl 1.38 }
1042     }
1043     }
1044     }
1045     }
1046 dl 1.41 if (p == replacement && (pp = p.parent) != null) {
1047     if (p == pp.left) // detach pointers
1048     pp.left = null;
1049     else if (p == pp.right)
1050     pp.right = null;
1051     p.parent = null;
1052     }
1053 dl 1.38 }
1054 dl 1.1 }
1055    
1056 dl 1.38 /* ---------------- Collision reduction methods -------------- */
1057 dl 1.14
1058     /**
1059 dl 1.38 * Spreads higher bits to lower, and also forces top 2 bits to 0.
1060     * Because the table uses power-of-two masking, sets of hashes
1061     * that vary only in bits above the current mask will always
1062     * collide. (Among known examples are sets of Float keys holding
1063     * consecutive whole numbers in small tables.) To counter this,
1064     * we apply a transform that spreads the impact of higher bits
1065     * downward. There is a tradeoff between speed, utility, and
1066     * quality of bit-spreading. Because many common sets of hashes
1067 jsr166 1.40 * are already reasonably distributed across bits (so don't benefit
1068 dl 1.38 * from spreading), and because we use trees to handle large sets
1069     * of collisions in bins, we don't need excessively high quality.
1070 dl 1.14 */
1071     private static final int spread(int h) {
1072 dl 1.38 h ^= (h >>> 18) ^ (h >>> 12);
1073     return (h ^ (h >>> 10)) & HASH_BITS;
1074     }
1075    
1076     /**
1077     * Replaces a list bin with a tree bin. Call only when locked.
1078     * Fails to replace if the given key is non-comparable or table
1079     * is, or needs, resizing.
1080     */
1081     private final void replaceWithTreeBin(Node[] tab, int index, Object key) {
1082     if ((key instanceof Comparable) &&
1083     (tab.length >= MAXIMUM_CAPACITY || counter.sum() < (long)sizeCtl)) {
1084     TreeBin t = new TreeBin();
1085     for (Node e = tabAt(tab, index); e != null; e = e.next)
1086     t.putTreeNode(e.hash & HASH_BITS, e.key, e.val);
1087     setTabAt(tab, index, new Node(MOVED, t, null, null));
1088     }
1089 dl 1.14 }
1090 dl 1.1
1091 dl 1.38 /* ---------------- Internal access and update methods -------------- */
1092    
1093 dl 1.14 /** Implementation for get and containsKey */
1094 jsr166 1.4 private final Object internalGet(Object k) {
1095 dl 1.1 int h = spread(k.hashCode());
1096 dl 1.14 retry: for (Node[] tab = table; tab != null;) {
1097 dl 1.38 Node e, p; Object ek, ev; int eh; // locals to read fields once
1098 dl 1.14 for (e = tabAt(tab, (tab.length - 1) & h); e != null; e = e.next) {
1099 dl 1.24 if ((eh = e.hash) == MOVED) {
1100 dl 1.38 if ((ek = e.key) instanceof TreeBin) // search TreeBin
1101     return ((TreeBin)ek).getValue(h, k);
1102     else { // restart with new table
1103     tab = (Node[])ek;
1104     continue retry;
1105     }
1106 dl 1.1 }
1107 dl 1.38 else if ((eh & HASH_BITS) == h && (ev = e.val) != null &&
1108     ((ek = e.key) == k || k.equals(ek)))
1109 dl 1.24 return ev;
1110 dl 1.1 }
1111     break;
1112     }
1113     return null;
1114     }
1115    
1116 dl 1.27 /**
1117     * Implementation for the four public remove/replace methods:
1118     * Replaces node value with v, conditional upon match of cv if
1119     * non-null. If resulting value is null, delete.
1120     */
1121     private final Object internalReplace(Object k, Object v, Object cv) {
1122     int h = spread(k.hashCode());
1123     Object oldVal = null;
1124     for (Node[] tab = table;;) {
1125 dl 1.38 Node f; int i, fh; Object fk;
1126 dl 1.27 if (tab == null ||
1127     (f = tabAt(tab, i = (tab.length - 1) & h)) == null)
1128     break;
1129 dl 1.38 else if ((fh = f.hash) == MOVED) {
1130     if ((fk = f.key) instanceof TreeBin) {
1131     TreeBin t = (TreeBin)fk;
1132     boolean validated = false;
1133     boolean deleted = false;
1134     t.acquire(0);
1135     try {
1136     if (tabAt(tab, i) == f) {
1137     validated = true;
1138     TreeNode p = t.getTreeNode(h, k, t.root);
1139     if (p != null) {
1140     Object pv = p.val;
1141     if (cv == null || cv == pv || cv.equals(pv)) {
1142     oldVal = pv;
1143     if ((p.val = v) == null) {
1144     deleted = true;
1145     t.deleteTreeNode(p);
1146     }
1147     }
1148     }
1149     }
1150     } finally {
1151     t.release(0);
1152     }
1153     if (validated) {
1154     if (deleted)
1155     counter.add(-1L);
1156     break;
1157     }
1158     }
1159     else
1160     tab = (Node[])fk;
1161     }
1162 dl 1.27 else if ((fh & HASH_BITS) != h && f.next == null) // precheck
1163     break; // rules out possible existence
1164     else if ((fh & LOCKED) != 0) {
1165     checkForResize(); // try resizing if can't get lock
1166     f.tryAwaitLock(tab, i);
1167     }
1168     else if (f.casHash(fh, fh | LOCKED)) {
1169     boolean validated = false;
1170     boolean deleted = false;
1171     try {
1172     if (tabAt(tab, i) == f) {
1173     validated = true;
1174     for (Node e = f, pred = null;;) {
1175     Object ek, ev;
1176     if ((e.hash & HASH_BITS) == h &&
1177     ((ev = e.val) != null) &&
1178     ((ek = e.key) == k || k.equals(ek))) {
1179     if (cv == null || cv == ev || cv.equals(ev)) {
1180     oldVal = ev;
1181     if ((e.val = v) == null) {
1182     deleted = true;
1183     Node en = e.next;
1184     if (pred != null)
1185     pred.next = en;
1186     else
1187     setTabAt(tab, i, en);
1188     }
1189     }
1190     break;
1191     }
1192     pred = e;
1193     if ((e = e.next) == null)
1194     break;
1195     }
1196     }
1197     } finally {
1198     if (!f.casHash(fh | LOCKED, fh)) {
1199     f.hash = fh;
1200 jsr166 1.30 synchronized (f) { f.notifyAll(); };
1201 dl 1.27 }
1202     }
1203     if (validated) {
1204     if (deleted)
1205     counter.add(-1L);
1206     break;
1207     }
1208     }
1209     }
1210     return oldVal;
1211     }
1212    
1213     /*
1214 dl 1.59 * Internal versions of the six insertion methods, each a
1215 dl 1.27 * little more complicated than the last. All have
1216     * the same basic structure as the first (internalPut):
1217     * 1. If table uninitialized, create
1218     * 2. If bin empty, try to CAS new node
1219     * 3. If bin stale, use new table
1220 dl 1.38 * 4. if bin converted to TreeBin, validate and relay to TreeBin methods
1221     * 5. Lock and validate; if valid, scan and add or update
1222 dl 1.27 *
1223     * The others interweave other checks and/or alternative actions:
1224     * * Plain put checks for and performs resize after insertion.
1225     * * putIfAbsent prescans for mapping without lock (and fails to add
1226     * if present), which also makes pre-emptive resize checks worthwhile.
1227     * * computeIfAbsent extends form used in putIfAbsent with additional
1228     * mechanics to deal with, calls, potential exceptions and null
1229     * returns from function call.
1230     * * compute uses the same function-call mechanics, but without
1231     * the prescans
1232 dl 1.59 * * merge acts as putIfAbsent in the absent case, but invokes the
1233     * update function if present
1234 dl 1.27 * * putAll attempts to pre-allocate enough table space
1235     * and more lazily performs count updates and checks.
1236     *
1237     * Someday when details settle down a bit more, it might be worth
1238     * some factoring to reduce sprawl.
1239     */
1240    
1241     /** Implementation for put */
1242     private final Object internalPut(Object k, Object v) {
1243 dl 1.1 int h = spread(k.hashCode());
1244 dl 1.38 int count = 0;
1245 dl 1.14 for (Node[] tab = table;;) {
1246 dl 1.38 int i; Node f; int fh; Object fk;
1247 dl 1.1 if (tab == null)
1248 dl 1.24 tab = initTable();
1249     else if ((f = tabAt(tab, i = (tab.length - 1) & h)) == null) {
1250 dl 1.2 if (casTabAt(tab, i, null, new Node(h, k, v, null)))
1251 dl 1.14 break; // no lock when adding to empty bin
1252     }
1253 dl 1.38 else if ((fh = f.hash) == MOVED) {
1254     if ((fk = f.key) instanceof TreeBin) {
1255     TreeBin t = (TreeBin)fk;
1256     Object oldVal = null;
1257     t.acquire(0);
1258     try {
1259     if (tabAt(tab, i) == f) {
1260     count = 2;
1261     TreeNode p = t.putTreeNode(h, k, v);
1262     if (p != null) {
1263     oldVal = p.val;
1264     p.val = v;
1265     }
1266     }
1267     } finally {
1268     t.release(0);
1269     }
1270     if (count != 0) {
1271     if (oldVal != null)
1272     return oldVal;
1273     break;
1274     }
1275     }
1276     else
1277     tab = (Node[])fk;
1278     }
1279 dl 1.27 else if ((fh & LOCKED) != 0) {
1280     checkForResize();
1281     f.tryAwaitLock(tab, i);
1282 dl 1.1 }
1283 dl 1.24 else if (f.casHash(fh, fh | LOCKED)) {
1284 dl 1.27 Object oldVal = null;
1285     try { // needed in case equals() throws
1286 dl 1.24 if (tabAt(tab, i) == f) {
1287 dl 1.38 count = 1;
1288     for (Node e = f;; ++count) {
1289 dl 1.24 Object ek, ev;
1290     if ((e.hash & HASH_BITS) == h &&
1291     (ev = e.val) != null &&
1292     ((ek = e.key) == k || k.equals(ek))) {
1293 dl 1.1 oldVal = ev;
1294 dl 1.27 e.val = v;
1295 dl 1.10 break;
1296 dl 1.1 }
1297 dl 1.10 Node last = e;
1298     if ((e = e.next) == null) {
1299 dl 1.2 last.next = new Node(h, k, v, null);
1300 dl 1.38 if (count >= TREE_THRESHOLD)
1301     replaceWithTreeBin(tab, i, k);
1302 dl 1.10 break;
1303 dl 1.1 }
1304     }
1305     }
1306 dl 1.24 } finally { // unlock and signal if needed
1307     if (!f.casHash(fh | LOCKED, fh)) {
1308     f.hash = fh;
1309 jsr166 1.26 synchronized (f) { f.notifyAll(); };
1310 dl 1.24 }
1311 dl 1.1 }
1312 dl 1.38 if (count != 0) {
1313 dl 1.27 if (oldVal != null)
1314     return oldVal;
1315 dl 1.38 if (tab.length <= 64)
1316     count = 2;
1317 dl 1.1 break;
1318     }
1319     }
1320     }
1321 dl 1.27 counter.add(1L);
1322 dl 1.38 if (count > 1)
1323 dl 1.27 checkForResize();
1324     return null;
1325 dl 1.1 }
1326    
1327 dl 1.27 /** Implementation for putIfAbsent */
1328     private final Object internalPutIfAbsent(Object k, Object v) {
1329 dl 1.1 int h = spread(k.hashCode());
1330 dl 1.38 int count = 0;
1331 dl 1.14 for (Node[] tab = table;;) {
1332 dl 1.27 int i; Node f; int fh; Object fk, fv;
1333     if (tab == null)
1334     tab = initTable();
1335     else if ((f = tabAt(tab, i = (tab.length - 1) & h)) == null) {
1336     if (casTabAt(tab, i, null, new Node(h, k, v, null)))
1337     break;
1338     }
1339 dl 1.38 else if ((fh = f.hash) == MOVED) {
1340     if ((fk = f.key) instanceof TreeBin) {
1341     TreeBin t = (TreeBin)fk;
1342     Object oldVal = null;
1343     t.acquire(0);
1344     try {
1345     if (tabAt(tab, i) == f) {
1346     count = 2;
1347     TreeNode p = t.putTreeNode(h, k, v);
1348     if (p != null)
1349     oldVal = p.val;
1350     }
1351     } finally {
1352     t.release(0);
1353     }
1354     if (count != 0) {
1355     if (oldVal != null)
1356     return oldVal;
1357     break;
1358     }
1359     }
1360     else
1361     tab = (Node[])fk;
1362     }
1363 dl 1.27 else if ((fh & HASH_BITS) == h && (fv = f.val) != null &&
1364     ((fk = f.key) == k || k.equals(fk)))
1365     return fv;
1366     else {
1367     Node g = f.next;
1368     if (g != null) { // at least 2 nodes -- search and maybe resize
1369     for (Node e = g;;) {
1370     Object ek, ev;
1371     if ((e.hash & HASH_BITS) == h && (ev = e.val) != null &&
1372     ((ek = e.key) == k || k.equals(ek)))
1373     return ev;
1374     if ((e = e.next) == null) {
1375     checkForResize();
1376     break;
1377     }
1378     }
1379     }
1380     if (((fh = f.hash) & LOCKED) != 0) {
1381     checkForResize();
1382     f.tryAwaitLock(tab, i);
1383     }
1384     else if (tabAt(tab, i) == f && f.casHash(fh, fh | LOCKED)) {
1385     Object oldVal = null;
1386     try {
1387     if (tabAt(tab, i) == f) {
1388 dl 1.38 count = 1;
1389     for (Node e = f;; ++count) {
1390 dl 1.27 Object ek, ev;
1391     if ((e.hash & HASH_BITS) == h &&
1392     (ev = e.val) != null &&
1393     ((ek = e.key) == k || k.equals(ek))) {
1394 dl 1.1 oldVal = ev;
1395 dl 1.27 break;
1396     }
1397     Node last = e;
1398     if ((e = e.next) == null) {
1399     last.next = new Node(h, k, v, null);
1400 dl 1.38 if (count >= TREE_THRESHOLD)
1401     replaceWithTreeBin(tab, i, k);
1402 dl 1.27 break;
1403 dl 1.1 }
1404     }
1405 dl 1.27 }
1406     } finally {
1407     if (!f.casHash(fh | LOCKED, fh)) {
1408     f.hash = fh;
1409 jsr166 1.30 synchronized (f) { f.notifyAll(); };
1410 dl 1.24 }
1411     }
1412 dl 1.38 if (count != 0) {
1413 dl 1.27 if (oldVal != null)
1414     return oldVal;
1415 dl 1.38 if (tab.length <= 64)
1416     count = 2;
1417 dl 1.27 break;
1418     }
1419     }
1420     }
1421     }
1422     counter.add(1L);
1423 dl 1.38 if (count > 1)
1424     checkForResize();
1425 dl 1.27 return null;
1426     }
1427    
1428     /** Implementation for computeIfAbsent */
1429     private final Object internalComputeIfAbsent(K k,
1430 dl 1.52 Fun<? super K, ?> mf) {
1431 dl 1.27 int h = spread(k.hashCode());
1432     Object val = null;
1433 dl 1.38 int count = 0;
1434 dl 1.27 for (Node[] tab = table;;) {
1435     Node f; int i, fh; Object fk, fv;
1436     if (tab == null)
1437     tab = initTable();
1438     else if ((f = tabAt(tab, i = (tab.length - 1) & h)) == null) {
1439     Node node = new Node(fh = h | LOCKED, k, null, null);
1440     if (casTabAt(tab, i, null, node)) {
1441 dl 1.38 count = 1;
1442 dl 1.27 try {
1443 dl 1.52 if ((val = mf.apply(k)) != null)
1444 dl 1.27 node.val = val;
1445     } finally {
1446     if (val == null)
1447     setTabAt(tab, i, null);
1448     if (!node.casHash(fh, h)) {
1449     node.hash = h;
1450 jsr166 1.30 synchronized (node) { node.notifyAll(); };
1451 dl 1.27 }
1452 dl 1.1 }
1453     }
1454 dl 1.38 if (count != 0)
1455 dl 1.24 break;
1456 dl 1.27 }
1457 dl 1.38 else if ((fh = f.hash) == MOVED) {
1458     if ((fk = f.key) instanceof TreeBin) {
1459     TreeBin t = (TreeBin)fk;
1460     boolean added = false;
1461     t.acquire(0);
1462     try {
1463     if (tabAt(tab, i) == f) {
1464     count = 1;
1465     TreeNode p = t.getTreeNode(h, k, t.root);
1466     if (p != null)
1467     val = p.val;
1468 dl 1.52 else if ((val = mf.apply(k)) != null) {
1469 dl 1.38 added = true;
1470     count = 2;
1471     t.putTreeNode(h, k, val);
1472     }
1473     }
1474     } finally {
1475     t.release(0);
1476     }
1477     if (count != 0) {
1478     if (!added)
1479     return val;
1480     break;
1481     }
1482     }
1483     else
1484     tab = (Node[])fk;
1485     }
1486 dl 1.27 else if ((fh & HASH_BITS) == h && (fv = f.val) != null &&
1487     ((fk = f.key) == k || k.equals(fk)))
1488     return fv;
1489     else {
1490     Node g = f.next;
1491     if (g != null) {
1492     for (Node e = g;;) {
1493     Object ek, ev;
1494     if ((e.hash & HASH_BITS) == h && (ev = e.val) != null &&
1495     ((ek = e.key) == k || k.equals(ek)))
1496     return ev;
1497     if ((e = e.next) == null) {
1498     checkForResize();
1499     break;
1500     }
1501     }
1502     }
1503     if (((fh = f.hash) & LOCKED) != 0) {
1504     checkForResize();
1505     f.tryAwaitLock(tab, i);
1506     }
1507     else if (tabAt(tab, i) == f && f.casHash(fh, fh | LOCKED)) {
1508 dl 1.38 boolean added = false;
1509 dl 1.27 try {
1510     if (tabAt(tab, i) == f) {
1511 dl 1.38 count = 1;
1512     for (Node e = f;; ++count) {
1513 dl 1.27 Object ek, ev;
1514     if ((e.hash & HASH_BITS) == h &&
1515     (ev = e.val) != null &&
1516     ((ek = e.key) == k || k.equals(ek))) {
1517     val = ev;
1518     break;
1519     }
1520     Node last = e;
1521     if ((e = e.next) == null) {
1522 dl 1.52 if ((val = mf.apply(k)) != null) {
1523 dl 1.38 added = true;
1524 dl 1.27 last.next = new Node(h, k, val, null);
1525 dl 1.38 if (count >= TREE_THRESHOLD)
1526     replaceWithTreeBin(tab, i, k);
1527     }
1528 dl 1.27 break;
1529     }
1530     }
1531     }
1532     } finally {
1533     if (!f.casHash(fh | LOCKED, fh)) {
1534     f.hash = fh;
1535 jsr166 1.30 synchronized (f) { f.notifyAll(); };
1536 dl 1.27 }
1537     }
1538 dl 1.38 if (count != 0) {
1539     if (!added)
1540     return val;
1541     if (tab.length <= 64)
1542     count = 2;
1543 dl 1.27 break;
1544 dl 1.38 }
1545 dl 1.1 }
1546     }
1547     }
1548 dl 1.41 if (val != null) {
1549     counter.add(1L);
1550     if (count > 1)
1551     checkForResize();
1552     }
1553 dl 1.27 return val;
1554 dl 1.1 }
1555    
1556 dl 1.27 /** Implementation for compute */
1557 dl 1.61 @SuppressWarnings("unchecked") private final Object internalCompute
1558     (K k, boolean onlyIfPresent, BiFun<? super K, ? super V, ? extends V> mf) {
1559 dl 1.1 int h = spread(k.hashCode());
1560 dl 1.27 Object val = null;
1561 dl 1.41 int delta = 0;
1562 dl 1.38 int count = 0;
1563 dl 1.27 for (Node[] tab = table;;) {
1564 dl 1.38 Node f; int i, fh; Object fk;
1565 dl 1.1 if (tab == null)
1566 dl 1.24 tab = initTable();
1567     else if ((f = tabAt(tab, i = (tab.length - 1) & h)) == null) {
1568 dl 1.52 if (onlyIfPresent)
1569     break;
1570 dl 1.24 Node node = new Node(fh = h | LOCKED, k, null, null);
1571     if (casTabAt(tab, i, null, node)) {
1572     try {
1573 dl 1.38 count = 1;
1574 dl 1.52 if ((val = mf.apply(k, null)) != null) {
1575 dl 1.24 node.val = val;
1576 dl 1.41 delta = 1;
1577 dl 1.24 }
1578     } finally {
1579 dl 1.41 if (delta == 0)
1580 dl 1.24 setTabAt(tab, i, null);
1581     if (!node.casHash(fh, h)) {
1582 dl 1.25 node.hash = h;
1583 jsr166 1.26 synchronized (node) { node.notifyAll(); };
1584 dl 1.1 }
1585     }
1586     }
1587 dl 1.38 if (count != 0)
1588 dl 1.10 break;
1589 dl 1.1 }
1590 dl 1.38 else if ((fh = f.hash) == MOVED) {
1591     if ((fk = f.key) instanceof TreeBin) {
1592     TreeBin t = (TreeBin)fk;
1593     t.acquire(0);
1594     try {
1595     if (tabAt(tab, i) == f) {
1596     count = 1;
1597     TreeNode p = t.getTreeNode(h, k, t.root);
1598 jsr166 1.39 Object pv = (p == null) ? null : p.val;
1599 dl 1.52 if ((val = mf.apply(k, (V)pv)) != null) {
1600 dl 1.38 if (p != null)
1601     p.val = val;
1602     else {
1603     count = 2;
1604 dl 1.41 delta = 1;
1605 dl 1.38 t.putTreeNode(h, k, val);
1606     }
1607     }
1608 dl 1.41 else if (p != null) {
1609     delta = -1;
1610     t.deleteTreeNode(p);
1611     }
1612 dl 1.38 }
1613     } finally {
1614     t.release(0);
1615     }
1616     if (count != 0)
1617     break;
1618     }
1619     else
1620     tab = (Node[])fk;
1621     }
1622 dl 1.27 else if ((fh & LOCKED) != 0) {
1623     checkForResize();
1624     f.tryAwaitLock(tab, i);
1625 dl 1.14 }
1626 dl 1.24 else if (f.casHash(fh, fh | LOCKED)) {
1627     try {
1628     if (tabAt(tab, i) == f) {
1629 dl 1.38 count = 1;
1630 dl 1.41 for (Node e = f, pred = null;; ++count) {
1631 dl 1.27 Object ek, ev;
1632 dl 1.24 if ((e.hash & HASH_BITS) == h &&
1633     (ev = e.val) != null &&
1634     ((ek = e.key) == k || k.equals(ek))) {
1635 dl 1.52 val = mf.apply(k, (V)ev);
1636 dl 1.27 if (val != null)
1637     e.val = val;
1638 dl 1.41 else {
1639     delta = -1;
1640     Node en = e.next;
1641     if (pred != null)
1642     pred.next = en;
1643     else
1644     setTabAt(tab, i, en);
1645     }
1646 dl 1.10 break;
1647 dl 1.1 }
1648 dl 1.41 pred = e;
1649 dl 1.10 if ((e = e.next) == null) {
1650 dl 1.52 if (!onlyIfPresent && (val = mf.apply(k, null)) != null) {
1651 dl 1.41 pred.next = new Node(h, k, val, null);
1652     delta = 1;
1653 dl 1.38 if (count >= TREE_THRESHOLD)
1654     replaceWithTreeBin(tab, i, k);
1655 dl 1.1 }
1656 dl 1.10 break;
1657 dl 1.1 }
1658     }
1659     }
1660 dl 1.24 } finally {
1661     if (!f.casHash(fh | LOCKED, fh)) {
1662     f.hash = fh;
1663 jsr166 1.26 synchronized (f) { f.notifyAll(); };
1664 dl 1.24 }
1665 dl 1.1 }
1666 dl 1.38 if (count != 0) {
1667     if (tab.length <= 64)
1668     count = 2;
1669 dl 1.10 break;
1670 dl 1.38 }
1671 dl 1.1 }
1672 dl 1.10 }
1673 dl 1.41 if (delta != 0) {
1674     counter.add((long)delta);
1675 dl 1.38 if (count > 1)
1676 dl 1.27 checkForResize();
1677     }
1678 dl 1.1 return val;
1679     }
1680    
1681 dl 1.59 /** Implementation for merge */
1682 dl 1.61 @SuppressWarnings("unchecked") private final Object internalMerge
1683     (K k, V v, BiFun<? super V, ? super V, ? extends V> mf) {
1684 dl 1.52 int h = spread(k.hashCode());
1685     Object val = null;
1686     int delta = 0;
1687     int count = 0;
1688     for (Node[] tab = table;;) {
1689     int i; Node f; int fh; Object fk, fv;
1690     if (tab == null)
1691     tab = initTable();
1692     else if ((f = tabAt(tab, i = (tab.length - 1) & h)) == null) {
1693     if (casTabAt(tab, i, null, new Node(h, k, v, null))) {
1694     delta = 1;
1695     val = v;
1696     break;
1697     }
1698     }
1699     else if ((fh = f.hash) == MOVED) {
1700     if ((fk = f.key) instanceof TreeBin) {
1701     TreeBin t = (TreeBin)fk;
1702     t.acquire(0);
1703     try {
1704     if (tabAt(tab, i) == f) {
1705     count = 1;
1706     TreeNode p = t.getTreeNode(h, k, t.root);
1707     val = (p == null) ? v : mf.apply((V)p.val, v);
1708     if (val != null) {
1709     if (p != null)
1710     p.val = val;
1711     else {
1712     count = 2;
1713     delta = 1;
1714     t.putTreeNode(h, k, val);
1715     }
1716     }
1717     else if (p != null) {
1718     delta = -1;
1719     t.deleteTreeNode(p);
1720     }
1721     }
1722     } finally {
1723     t.release(0);
1724     }
1725     if (count != 0)
1726     break;
1727     }
1728     else
1729     tab = (Node[])fk;
1730     }
1731     else if ((fh & LOCKED) != 0) {
1732     checkForResize();
1733     f.tryAwaitLock(tab, i);
1734     }
1735     else if (f.casHash(fh, fh | LOCKED)) {
1736     try {
1737     if (tabAt(tab, i) == f) {
1738     count = 1;
1739     for (Node e = f, pred = null;; ++count) {
1740     Object ek, ev;
1741     if ((e.hash & HASH_BITS) == h &&
1742     (ev = e.val) != null &&
1743     ((ek = e.key) == k || k.equals(ek))) {
1744     val = mf.apply(v, (V)ev);
1745     if (val != null)
1746     e.val = val;
1747     else {
1748     delta = -1;
1749     Node en = e.next;
1750     if (pred != null)
1751     pred.next = en;
1752     else
1753     setTabAt(tab, i, en);
1754     }
1755     break;
1756     }
1757     pred = e;
1758     if ((e = e.next) == null) {
1759     val = v;
1760     pred.next = new Node(h, k, val, null);
1761     delta = 1;
1762     if (count >= TREE_THRESHOLD)
1763     replaceWithTreeBin(tab, i, k);
1764     break;
1765     }
1766     }
1767     }
1768     } finally {
1769     if (!f.casHash(fh | LOCKED, fh)) {
1770     f.hash = fh;
1771     synchronized (f) { f.notifyAll(); };
1772     }
1773     }
1774     if (count != 0) {
1775     if (tab.length <= 64)
1776     count = 2;
1777     break;
1778     }
1779     }
1780     }
1781     if (delta != 0) {
1782     counter.add((long)delta);
1783     if (count > 1)
1784     checkForResize();
1785     }
1786     return val;
1787     }
1788    
1789 dl 1.27 /** Implementation for putAll */
1790     private final void internalPutAll(Map<?, ?> m) {
1791     tryPresize(m.size());
1792     long delta = 0L; // number of uncommitted additions
1793     boolean npe = false; // to throw exception on exit for nulls
1794     try { // to clean up counts on other exceptions
1795     for (Map.Entry<?, ?> entry : m.entrySet()) {
1796     Object k, v;
1797     if (entry == null || (k = entry.getKey()) == null ||
1798     (v = entry.getValue()) == null) {
1799     npe = true;
1800     break;
1801     }
1802     int h = spread(k.hashCode());
1803     for (Node[] tab = table;;) {
1804 dl 1.38 int i; Node f; int fh; Object fk;
1805 dl 1.27 if (tab == null)
1806     tab = initTable();
1807     else if ((f = tabAt(tab, i = (tab.length - 1) & h)) == null){
1808     if (casTabAt(tab, i, null, new Node(h, k, v, null))) {
1809     ++delta;
1810     break;
1811     }
1812     }
1813 dl 1.38 else if ((fh = f.hash) == MOVED) {
1814     if ((fk = f.key) instanceof TreeBin) {
1815     TreeBin t = (TreeBin)fk;
1816     boolean validated = false;
1817     t.acquire(0);
1818     try {
1819     if (tabAt(tab, i) == f) {
1820     validated = true;
1821     TreeNode p = t.getTreeNode(h, k, t.root);
1822     if (p != null)
1823     p.val = v;
1824     else {
1825     t.putTreeNode(h, k, v);
1826     ++delta;
1827     }
1828     }
1829     } finally {
1830     t.release(0);
1831     }
1832     if (validated)
1833     break;
1834     }
1835     else
1836     tab = (Node[])fk;
1837     }
1838 dl 1.27 else if ((fh & LOCKED) != 0) {
1839     counter.add(delta);
1840     delta = 0L;
1841     checkForResize();
1842     f.tryAwaitLock(tab, i);
1843     }
1844     else if (f.casHash(fh, fh | LOCKED)) {
1845 dl 1.38 int count = 0;
1846 dl 1.27 try {
1847     if (tabAt(tab, i) == f) {
1848 dl 1.38 count = 1;
1849     for (Node e = f;; ++count) {
1850 dl 1.27 Object ek, ev;
1851     if ((e.hash & HASH_BITS) == h &&
1852     (ev = e.val) != null &&
1853     ((ek = e.key) == k || k.equals(ek))) {
1854     e.val = v;
1855     break;
1856     }
1857     Node last = e;
1858     if ((e = e.next) == null) {
1859     ++delta;
1860     last.next = new Node(h, k, v, null);
1861 dl 1.38 if (count >= TREE_THRESHOLD)
1862     replaceWithTreeBin(tab, i, k);
1863 dl 1.27 break;
1864     }
1865     }
1866     }
1867     } finally {
1868     if (!f.casHash(fh | LOCKED, fh)) {
1869     f.hash = fh;
1870 jsr166 1.30 synchronized (f) { f.notifyAll(); };
1871 dl 1.27 }
1872     }
1873 dl 1.38 if (count != 0) {
1874     if (count > 1) {
1875 dl 1.27 counter.add(delta);
1876     delta = 0L;
1877     checkForResize();
1878 dl 1.1 }
1879 dl 1.27 break;
1880 dl 1.24 }
1881     }
1882 dl 1.1 }
1883     }
1884 dl 1.27 } finally {
1885     if (delta != 0)
1886     counter.add(delta);
1887 dl 1.1 }
1888 dl 1.27 if (npe)
1889     throw new NullPointerException();
1890 dl 1.1 }
1891    
1892 dl 1.27 /* ---------------- Table Initialization and Resizing -------------- */
1893 dl 1.24
1894     /**
1895     * Returns a power of two table size for the given desired capacity.
1896     * See Hackers Delight, sec 3.2
1897     */
1898     private static final int tableSizeFor(int c) {
1899     int n = c - 1;
1900     n |= n >>> 1;
1901     n |= n >>> 2;
1902     n |= n >>> 4;
1903     n |= n >>> 8;
1904     n |= n >>> 16;
1905     return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
1906     }
1907    
1908     /**
1909     * Initializes table, using the size recorded in sizeCtl.
1910     */
1911     private final Node[] initTable() {
1912     Node[] tab; int sc;
1913     while ((tab = table) == null) {
1914     if ((sc = sizeCtl) < 0)
1915     Thread.yield(); // lost initialization race; just spin
1916     else if (UNSAFE.compareAndSwapInt(this, sizeCtlOffset, sc, -1)) {
1917     try {
1918     if ((tab = table) == null) {
1919     int n = (sc > 0) ? sc : DEFAULT_CAPACITY;
1920     tab = table = new Node[n];
1921 dl 1.27 sc = n - (n >>> 2);
1922 dl 1.24 }
1923     } finally {
1924     sizeCtl = sc;
1925     }
1926     break;
1927     }
1928     }
1929     return tab;
1930     }
1931    
1932     /**
1933 dl 1.27 * If table is too small and not already resizing, creates next
1934     * table and transfers bins. Rechecks occupancy after a transfer
1935     * to see if another resize is already needed because resizings
1936     * are lagging additions.
1937     */
1938     private final void checkForResize() {
1939     Node[] tab; int n, sc;
1940     while ((tab = table) != null &&
1941     (n = tab.length) < MAXIMUM_CAPACITY &&
1942     (sc = sizeCtl) >= 0 && counter.sum() >= (long)sc &&
1943     UNSAFE.compareAndSwapInt(this, sizeCtlOffset, sc, -1)) {
1944 dl 1.24 try {
1945 dl 1.27 if (tab == table) {
1946 dl 1.24 table = rebuild(tab);
1947 dl 1.27 sc = (n << 1) - (n >>> 1);
1948 dl 1.24 }
1949     } finally {
1950     sizeCtl = sc;
1951     }
1952     }
1953     }
1954    
1955 dl 1.27 /**
1956     * Tries to presize table to accommodate the given number of elements.
1957     *
1958     * @param size number of elements (doesn't need to be perfectly accurate)
1959     */
1960     private final void tryPresize(int size) {
1961     int c = (size >= (MAXIMUM_CAPACITY >>> 1)) ? MAXIMUM_CAPACITY :
1962     tableSizeFor(size + (size >>> 1) + 1);
1963     int sc;
1964     while ((sc = sizeCtl) >= 0) {
1965     Node[] tab = table; int n;
1966     if (tab == null || (n = tab.length) == 0) {
1967 jsr166 1.30 n = (sc > c) ? sc : c;
1968 dl 1.27 if (UNSAFE.compareAndSwapInt(this, sizeCtlOffset, sc, -1)) {
1969     try {
1970     if (table == tab) {
1971     table = new Node[n];
1972     sc = n - (n >>> 2);
1973     }
1974     } finally {
1975     sizeCtl = sc;
1976     }
1977     }
1978     }
1979     else if (c <= sc || n >= MAXIMUM_CAPACITY)
1980     break;
1981     else if (UNSAFE.compareAndSwapInt(this, sizeCtlOffset, sc, -1)) {
1982     try {
1983     if (table == tab) {
1984     table = rebuild(tab);
1985     sc = (n << 1) - (n >>> 1);
1986     }
1987     } finally {
1988     sizeCtl = sc;
1989     }
1990     }
1991     }
1992     }
1993    
1994 dl 1.24 /*
1995     * Moves and/or copies the nodes in each bin to new table. See
1996     * above for explanation.
1997     *
1998     * @return the new table
1999     */
2000     private static final Node[] rebuild(Node[] tab) {
2001     int n = tab.length;
2002     Node[] nextTab = new Node[n << 1];
2003     Node fwd = new Node(MOVED, nextTab, null, null);
2004     int[] buffer = null; // holds bins to revisit; null until needed
2005     Node rev = null; // reverse forwarder; null until needed
2006     int nbuffered = 0; // the number of bins in buffer list
2007     int bufferIndex = 0; // buffer index of current buffered bin
2008     int bin = n - 1; // current non-buffered bin or -1 if none
2009    
2010     for (int i = bin;;) { // start upwards sweep
2011     int fh; Node f;
2012     if ((f = tabAt(tab, i)) == null) {
2013 dl 1.61 if (bin >= 0) { // Unbuffered; no lock needed (or available)
2014 dl 1.24 if (!casTabAt(tab, i, f, fwd))
2015     continue;
2016     }
2017     else { // transiently use a locked forwarding node
2018 jsr166 1.33 Node g = new Node(MOVED|LOCKED, nextTab, null, null);
2019 dl 1.24 if (!casTabAt(tab, i, f, g))
2020     continue;
2021     setTabAt(nextTab, i, null);
2022     setTabAt(nextTab, i + n, null);
2023     setTabAt(tab, i, fwd);
2024     if (!g.casHash(MOVED|LOCKED, MOVED)) {
2025     g.hash = MOVED;
2026 jsr166 1.26 synchronized (g) { g.notifyAll(); }
2027 dl 1.24 }
2028     }
2029     }
2030 dl 1.38 else if ((fh = f.hash) == MOVED) {
2031     Object fk = f.key;
2032     if (fk instanceof TreeBin) {
2033     TreeBin t = (TreeBin)fk;
2034     boolean validated = false;
2035     t.acquire(0);
2036     try {
2037     if (tabAt(tab, i) == f) {
2038     validated = true;
2039     splitTreeBin(nextTab, i, t);
2040     setTabAt(tab, i, fwd);
2041     }
2042     } finally {
2043     t.release(0);
2044     }
2045     if (!validated)
2046     continue;
2047     }
2048     }
2049     else if ((fh & LOCKED) == 0 && f.casHash(fh, fh|LOCKED)) {
2050 dl 1.24 boolean validated = false;
2051     try { // split to lo and hi lists; copying as needed
2052     if (tabAt(tab, i) == f) {
2053     validated = true;
2054 dl 1.38 splitBin(nextTab, i, f);
2055 dl 1.24 setTabAt(tab, i, fwd);
2056     }
2057     } finally {
2058     if (!f.casHash(fh | LOCKED, fh)) {
2059     f.hash = fh;
2060 jsr166 1.26 synchronized (f) { f.notifyAll(); };
2061 dl 1.24 }
2062     }
2063     if (!validated)
2064     continue;
2065     }
2066     else {
2067     if (buffer == null) // initialize buffer for revisits
2068     buffer = new int[TRANSFER_BUFFER_SIZE];
2069     if (bin < 0 && bufferIndex > 0) {
2070     int j = buffer[--bufferIndex];
2071     buffer[bufferIndex] = i;
2072     i = j; // swap with another bin
2073     continue;
2074     }
2075     if (bin < 0 || nbuffered >= TRANSFER_BUFFER_SIZE) {
2076     f.tryAwaitLock(tab, i);
2077     continue; // no other options -- block
2078     }
2079     if (rev == null) // initialize reverse-forwarder
2080     rev = new Node(MOVED, tab, null, null);
2081     if (tabAt(tab, i) != f || (f.hash & LOCKED) == 0)
2082     continue; // recheck before adding to list
2083     buffer[nbuffered++] = i;
2084     setTabAt(nextTab, i, rev); // install place-holders
2085     setTabAt(nextTab, i + n, rev);
2086     }
2087    
2088     if (bin > 0)
2089     i = --bin;
2090     else if (buffer != null && nbuffered > 0) {
2091     bin = -1;
2092     i = buffer[bufferIndex = --nbuffered];
2093     }
2094     else
2095     return nextTab;
2096     }
2097     }
2098    
2099 dl 1.27 /**
2100 jsr166 1.45 * Splits a normal bin with list headed by e into lo and hi parts;
2101     * installs in given table.
2102 dl 1.38 */
2103     private static void splitBin(Node[] nextTab, int i, Node e) {
2104     int bit = nextTab.length >>> 1; // bit to split on
2105     int runBit = e.hash & bit;
2106     Node lastRun = e, lo = null, hi = null;
2107     for (Node p = e.next; p != null; p = p.next) {
2108     int b = p.hash & bit;
2109     if (b != runBit) {
2110     runBit = b;
2111     lastRun = p;
2112     }
2113     }
2114     if (runBit == 0)
2115     lo = lastRun;
2116     else
2117     hi = lastRun;
2118     for (Node p = e; p != lastRun; p = p.next) {
2119     int ph = p.hash & HASH_BITS;
2120     Object pk = p.key, pv = p.val;
2121     if ((ph & bit) == 0)
2122     lo = new Node(ph, pk, pv, lo);
2123     else
2124     hi = new Node(ph, pk, pv, hi);
2125     }
2126     setTabAt(nextTab, i, lo);
2127     setTabAt(nextTab, i + bit, hi);
2128     }
2129    
2130     /**
2131 jsr166 1.45 * Splits a tree bin into lo and hi parts; installs in given table.
2132 dl 1.38 */
2133     private static void splitTreeBin(Node[] nextTab, int i, TreeBin t) {
2134     int bit = nextTab.length >>> 1;
2135     TreeBin lt = new TreeBin();
2136     TreeBin ht = new TreeBin();
2137     int lc = 0, hc = 0;
2138     for (Node e = t.first; e != null; e = e.next) {
2139     int h = e.hash & HASH_BITS;
2140     Object k = e.key, v = e.val;
2141     if ((h & bit) == 0) {
2142     ++lc;
2143     lt.putTreeNode(h, k, v);
2144     }
2145     else {
2146     ++hc;
2147     ht.putTreeNode(h, k, v);
2148     }
2149     }
2150     Node ln, hn; // throw away trees if too small
2151     if (lc <= (TREE_THRESHOLD >>> 1)) {
2152     ln = null;
2153     for (Node p = lt.first; p != null; p = p.next)
2154     ln = new Node(p.hash, p.key, p.val, ln);
2155     }
2156     else
2157     ln = new Node(MOVED, lt, null, null);
2158     setTabAt(nextTab, i, ln);
2159     if (hc <= (TREE_THRESHOLD >>> 1)) {
2160     hn = null;
2161     for (Node p = ht.first; p != null; p = p.next)
2162     hn = new Node(p.hash, p.key, p.val, hn);
2163     }
2164     else
2165     hn = new Node(MOVED, ht, null, null);
2166     setTabAt(nextTab, i + bit, hn);
2167     }
2168    
2169     /**
2170 dl 1.27 * Implementation for clear. Steps through each bin, removing all
2171     * nodes.
2172     */
2173     private final void internalClear() {
2174     long delta = 0L; // negative number of deletions
2175     int i = 0;
2176     Node[] tab = table;
2177     while (tab != null && i < tab.length) {
2178 dl 1.38 int fh; Object fk;
2179 dl 1.27 Node f = tabAt(tab, i);
2180     if (f == null)
2181     ++i;
2182 dl 1.38 else if ((fh = f.hash) == MOVED) {
2183     if ((fk = f.key) instanceof TreeBin) {
2184     TreeBin t = (TreeBin)fk;
2185     t.acquire(0);
2186     try {
2187     if (tabAt(tab, i) == f) {
2188     for (Node p = t.first; p != null; p = p.next) {
2189 dl 1.61 if (p.val != null) { // (currently always true)
2190     p.val = null;
2191     --delta;
2192     }
2193 dl 1.38 }
2194     t.first = null;
2195     t.root = null;
2196     ++i;
2197     }
2198     } finally {
2199     t.release(0);
2200     }
2201     }
2202     else
2203     tab = (Node[])fk;
2204     }
2205 dl 1.27 else if ((fh & LOCKED) != 0) {
2206     counter.add(delta); // opportunistically update count
2207     delta = 0L;
2208     f.tryAwaitLock(tab, i);
2209     }
2210     else if (f.casHash(fh, fh | LOCKED)) {
2211     try {
2212     if (tabAt(tab, i) == f) {
2213     for (Node e = f; e != null; e = e.next) {
2214 dl 1.61 if (e.val != null) { // (currently always true)
2215     e.val = null;
2216     --delta;
2217     }
2218 dl 1.27 }
2219     setTabAt(tab, i, null);
2220 dl 1.38 ++i;
2221 dl 1.27 }
2222     } finally {
2223     if (!f.casHash(fh | LOCKED, fh)) {
2224     f.hash = fh;
2225 jsr166 1.30 synchronized (f) { f.notifyAll(); };
2226 dl 1.27 }
2227     }
2228     }
2229     }
2230     if (delta != 0)
2231     counter.add(delta);
2232     }
2233    
2234 dl 1.14 /* ----------------Table Traversal -------------- */
2235    
2236 dl 1.1 /**
2237 dl 1.14 * Encapsulates traversal for methods such as containsValue; also
2238 dl 1.59 * serves as a base class for other iterators and bulk tasks.
2239 dl 1.14 *
2240     * At each step, the iterator snapshots the key ("nextKey") and
2241     * value ("nextVal") of a valid node (i.e., one that, at point of
2242 jsr166 1.36 * snapshot, has a non-null user value). Because val fields can
2243 dl 1.14 * change (including to null, indicating deletion), field nextVal
2244     * might not be accurate at point of use, but still maintains the
2245     * weak consistency property of holding a value that was once
2246     * valid.
2247     *
2248     * Internal traversals directly access these fields, as in:
2249 dl 1.41 * {@code while (it.advance() != null) { process(it.nextKey); }}
2250 dl 1.14 *
2251 dl 1.41 * Exported iterators must track whether the iterator has advanced
2252     * (in hasNext vs next) (by setting/checking/nulling field
2253     * nextVal), and then extract key, value, or key-value pairs as
2254     * return values of next().
2255 dl 1.14 *
2256 dl 1.27 * The iterator visits once each still-valid node that was
2257     * reachable upon iterator construction. It might miss some that
2258     * were added to a bin after the bin was visited, which is OK wrt
2259     * consistency guarantees. Maintaining this property in the face
2260     * of possible ongoing resizes requires a fair amount of
2261     * bookkeeping state that is difficult to optimize away amidst
2262     * volatile accesses. Even so, traversal maintains reasonable
2263     * throughput.
2264 dl 1.14 *
2265     * Normally, iteration proceeds bin-by-bin traversing lists.
2266     * However, if the table has been resized, then all future steps
2267     * must traverse both the bin at the current index as well as at
2268     * (index + baseSize); and so on for further resizings. To
2269     * paranoically cope with potential sharing by users of iterators
2270     * across threads, iteration terminates if a bounds checks fails
2271     * for a table read.
2272 dl 1.52 *
2273     * This class extends ForkJoinTask to streamline parallel
2274     * iteration in bulk operations (see BulkTask). This adds only an
2275     * int of space overhead, which is close enough to negligible in
2276 dl 1.59 * cases where it is not needed to not worry about it. Because
2277     * ForkJoinTask is Serializable, but iterators need not be, we
2278     * need to add warning suppressions.
2279 dl 1.14 */
2280 dl 1.61 @SuppressWarnings("serial") static class Traverser<K,V,R> extends ForkJoinTask<R> {
2281 dl 1.41 final ConcurrentHashMapV8<K, V> map;
2282 dl 1.14 Node next; // the next entry to use
2283     Node last; // the last entry used
2284     Object nextKey; // cached key field of next
2285     Object nextVal; // cached val field of next
2286     Node[] tab; // current table; updated if resized
2287     int index; // index of bin to use next
2288     int baseIndex; // current index of initial table
2289 dl 1.41 int baseLimit; // index bound for initial table
2290 dl 1.63 int baseSize; // initial table size
2291 dl 1.14
2292     /** Creates iterator for all entries in the table. */
2293 dl 1.52 Traverser(ConcurrentHashMapV8<K, V> map) {
2294 dl 1.63 this.map = map;
2295 dl 1.14 }
2296    
2297 dl 1.52 /** Creates iterator for split() methods */
2298 dl 1.61 Traverser(Traverser<K,V,?> it) {
2299 dl 1.63 ConcurrentHashMapV8<K, V> m; Node[] t;
2300     if ((m = this.map = it.map) == null)
2301     t = null;
2302     else if ((t = it.tab) == null && // force parent tab initialization
2303     (t = it.tab = m.table) != null)
2304     it.baseLimit = it.baseSize = t.length;
2305     this.tab = t;
2306 dl 1.41 this.baseSize = it.baseSize;
2307 dl 1.61 it.baseLimit = this.index = this.baseIndex =
2308     ((this.baseLimit = it.baseLimit) + it.baseIndex + 1) >>> 1;
2309 dl 1.41 }
2310    
2311     /**
2312 jsr166 1.48 * Advances next; returns nextVal or null if terminated.
2313 dl 1.41 * See above for explanation.
2314     */
2315     final Object advance() {
2316 dl 1.14 Node e = last = next;
2317 dl 1.41 Object ev = null;
2318 dl 1.14 outer: do {
2319 dl 1.24 if (e != null) // advance past used/skipped node
2320 dl 1.1 e = e.next;
2321 dl 1.24 while (e == null) { // get to next non-null bin
2322 dl 1.63 ConcurrentHashMapV8<K, V> m;
2323 dl 1.38 Node[] t; int b, i, n; Object ek; // checks must use locals
2324 dl 1.63 if ((t = tab) != null)
2325     n = t.length;
2326     else if ((m = map) != null && (t = tab = m.table) != null)
2327     n = baseLimit = baseSize = t.length;
2328     else
2329 dl 1.14 break outer;
2330 dl 1.63 if ((b = baseIndex) >= baseLimit ||
2331     (i = index) < 0 || i >= n)
2332     break outer;
2333     if ((e = tabAt(t, i)) != null && e.hash == MOVED) {
2334 dl 1.38 if ((ek = e.key) instanceof TreeBin)
2335     e = ((TreeBin)ek).first;
2336     else {
2337     tab = (Node[])ek;
2338     continue; // restarts due to null val
2339     }
2340     } // visit upper slots if present
2341     index = (i += baseSize) < n ? i : (baseIndex = b + 1);
2342 dl 1.1 }
2343 dl 1.14 nextKey = e.key;
2344 dl 1.41 } while ((ev = e.val) == null); // skip deleted or special nodes
2345 dl 1.14 next = e;
2346 dl 1.41 return nextVal = ev;
2347 dl 1.1 }
2348 dl 1.41
2349     public final void remove() {
2350 dl 1.57 if (nextVal == null && last == null)
2351 dl 1.41 advance();
2352     Node e = last;
2353     if (e == null)
2354     throw new IllegalStateException();
2355     last = null;
2356     map.remove(e.key);
2357     }
2358    
2359     public final boolean hasNext() {
2360     return nextVal != null || advance() != null;
2361     }
2362    
2363     public final boolean hasMoreElements() { return hasNext(); }
2364 dl 1.52 public final void setRawResult(Object x) { }
2365     public R getRawResult() { return null; }
2366     public boolean exec() { return true; }
2367 dl 1.1 }
2368    
2369     /* ---------------- Public operations -------------- */
2370    
2371     /**
2372 jsr166 1.48 * Creates a new, empty map with the default initial table size (16).
2373 dl 1.1 */
2374 dl 1.16 public ConcurrentHashMapV8() {
2375 dl 1.14 this.counter = new LongAdder();
2376 dl 1.1 }
2377    
2378     /**
2379 dl 1.16 * Creates a new, empty map with an initial table size
2380     * accommodating the specified number of elements without the need
2381     * to dynamically resize.
2382 dl 1.1 *
2383     * @param initialCapacity The implementation performs internal
2384     * sizing to accommodate this many elements.
2385     * @throws IllegalArgumentException if the initial capacity of
2386 jsr166 1.18 * elements is negative
2387 dl 1.1 */
2388 dl 1.16 public ConcurrentHashMapV8(int initialCapacity) {
2389     if (initialCapacity < 0)
2390     throw new IllegalArgumentException();
2391     int cap = ((initialCapacity >= (MAXIMUM_CAPACITY >>> 1)) ?
2392     MAXIMUM_CAPACITY :
2393     tableSizeFor(initialCapacity + (initialCapacity >>> 1) + 1));
2394     this.counter = new LongAdder();
2395 dl 1.24 this.sizeCtl = cap;
2396 dl 1.1 }
2397    
2398     /**
2399 dl 1.16 * Creates a new map with the same mappings as the given map.
2400 dl 1.1 *
2401 dl 1.16 * @param m the map
2402 dl 1.1 */
2403 dl 1.16 public ConcurrentHashMapV8(Map<? extends K, ? extends V> m) {
2404     this.counter = new LongAdder();
2405 dl 1.24 this.sizeCtl = DEFAULT_CAPACITY;
2406 dl 1.27 internalPutAll(m);
2407 dl 1.1 }
2408    
2409     /**
2410 dl 1.16 * Creates a new, empty map with an initial table size based on
2411     * the given number of elements ({@code initialCapacity}) and
2412     * initial table density ({@code loadFactor}).
2413     *
2414     * @param initialCapacity the initial capacity. The implementation
2415     * performs internal sizing to accommodate this many elements,
2416     * given the specified load factor.
2417     * @param loadFactor the load factor (table density) for
2418 jsr166 1.18 * establishing the initial table size
2419 dl 1.16 * @throws IllegalArgumentException if the initial capacity of
2420     * elements is negative or the load factor is nonpositive
2421 jsr166 1.22 *
2422     * @since 1.6
2423 dl 1.1 */
2424 dl 1.16 public ConcurrentHashMapV8(int initialCapacity, float loadFactor) {
2425     this(initialCapacity, loadFactor, 1);
2426 dl 1.1 }
2427    
2428     /**
2429 dl 1.16 * Creates a new, empty map with an initial table size based on
2430     * the given number of elements ({@code initialCapacity}), table
2431     * density ({@code loadFactor}), and number of concurrently
2432     * updating threads ({@code concurrencyLevel}).
2433 dl 1.1 *
2434 dl 1.16 * @param initialCapacity the initial capacity. The implementation
2435     * performs internal sizing to accommodate this many elements,
2436     * given the specified load factor.
2437     * @param loadFactor the load factor (table density) for
2438 jsr166 1.18 * establishing the initial table size
2439 dl 1.16 * @param concurrencyLevel the estimated number of concurrently
2440     * updating threads. The implementation may use this value as
2441     * a sizing hint.
2442     * @throws IllegalArgumentException if the initial capacity is
2443     * negative or the load factor or concurrencyLevel are
2444 jsr166 1.18 * nonpositive
2445 dl 1.1 */
2446 dl 1.16 public ConcurrentHashMapV8(int initialCapacity,
2447     float loadFactor, int concurrencyLevel) {
2448     if (!(loadFactor > 0.0f) || initialCapacity < 0 || concurrencyLevel <= 0)
2449     throw new IllegalArgumentException();
2450     if (initialCapacity < concurrencyLevel) // Use at least as many bins
2451     initialCapacity = concurrencyLevel; // as estimated threads
2452     long size = (long)(1.0 + (long)initialCapacity / loadFactor);
2453 jsr166 1.49 int cap = (size >= (long)MAXIMUM_CAPACITY) ?
2454     MAXIMUM_CAPACITY : tableSizeFor((int)size);
2455 dl 1.16 this.counter = new LongAdder();
2456 dl 1.24 this.sizeCtl = cap;
2457 dl 1.1 }
2458    
2459     /**
2460 dl 1.14 * {@inheritDoc}
2461 dl 1.1 */
2462     public boolean isEmpty() {
2463 dl 1.2 return counter.sum() <= 0L; // ignore transient negative values
2464 dl 1.1 }
2465    
2466     /**
2467 dl 1.14 * {@inheritDoc}
2468 dl 1.1 */
2469     public int size() {
2470     long n = counter.sum();
2471 jsr166 1.15 return ((n < 0L) ? 0 :
2472     (n > (long)Integer.MAX_VALUE) ? Integer.MAX_VALUE :
2473 dl 1.14 (int)n);
2474 dl 1.1 }
2475    
2476 dl 1.52 /**
2477     * Returns the number of mappings. This method should be used
2478     * instead of {@link #size} because a ConcurrentHashMap may
2479     * contain more mappings than can be represented as an int. The
2480     * value returned is a snapshot; the actual count may differ if
2481 dl 1.60 * there are ongoing concurrent insertions or removals.
2482 dl 1.52 *
2483     * @return the number of mappings
2484     */
2485     public long mappingCount() {
2486 dl 1.24 long n = counter.sum();
2487 dl 1.59 return (n < 0L) ? 0L : n; // ignore transient negative values
2488 dl 1.24 }
2489    
2490 dl 1.1 /**
2491     * Returns the value to which the specified key is mapped,
2492     * or {@code null} if this map contains no mapping for the key.
2493     *
2494     * <p>More formally, if this map contains a mapping from a key
2495     * {@code k} to a value {@code v} such that {@code key.equals(k)},
2496     * then this method returns {@code v}; otherwise it returns
2497     * {@code null}. (There can be at most one such mapping.)
2498     *
2499     * @throws NullPointerException if the specified key is null
2500     */
2501 dl 1.61 @SuppressWarnings("unchecked") public V get(Object key) {
2502 dl 1.1 if (key == null)
2503     throw new NullPointerException();
2504     return (V)internalGet(key);
2505     }
2506    
2507     /**
2508 dl 1.62 * Returns the value to which the specified key is mapped,
2509 jsr166 1.66 * or the given defaultValue if this map contains no mapping for the key.
2510 dl 1.62 *
2511     * @param key the key
2512     * @param defaultValue the value to return if this map contains
2513 jsr166 1.67 * no mapping for the given key
2514 dl 1.62 * @return the mapping for the key, if present; else the defaultValue
2515     * @throws NullPointerException if the specified key is null
2516     */
2517     @SuppressWarnings("unchecked") public V getValueOrDefault(Object key, V defaultValue) {
2518     if (key == null)
2519     throw new NullPointerException();
2520     V v = (V) internalGet(key);
2521     return v == null ? defaultValue : v;
2522     }
2523    
2524     /**
2525 dl 1.1 * Tests if the specified object is a key in this table.
2526     *
2527     * @param key possible key
2528     * @return {@code true} if and only if the specified object
2529     * is a key in this table, as determined by the
2530 jsr166 1.18 * {@code equals} method; {@code false} otherwise
2531 dl 1.1 * @throws NullPointerException if the specified key is null
2532     */
2533     public boolean containsKey(Object key) {
2534     if (key == null)
2535     throw new NullPointerException();
2536     return internalGet(key) != null;
2537     }
2538    
2539     /**
2540     * Returns {@code true} if this map maps one or more keys to the
2541 dl 1.14 * specified value. Note: This method may require a full traversal
2542     * of the map, and is much slower than method {@code containsKey}.
2543 dl 1.1 *
2544     * @param value value whose presence in this map is to be tested
2545     * @return {@code true} if this map maps one or more keys to the
2546     * specified value
2547     * @throws NullPointerException if the specified value is null
2548     */
2549     public boolean containsValue(Object value) {
2550     if (value == null)
2551     throw new NullPointerException();
2552 dl 1.14 Object v;
2553 dl 1.52 Traverser<K,V,Object> it = new Traverser<K,V,Object>(this);
2554 dl 1.41 while ((v = it.advance()) != null) {
2555     if (v == value || value.equals(v))
2556 dl 1.14 return true;
2557     }
2558     return false;
2559 dl 1.1 }
2560    
2561     /**
2562     * Legacy method testing if some key maps into the specified value
2563     * in this table. This method is identical in functionality to
2564     * {@link #containsValue}, and exists solely to ensure
2565     * full compatibility with class {@link java.util.Hashtable},
2566     * which supported this method prior to introduction of the
2567     * Java Collections framework.
2568     *
2569     * @param value a value to search for
2570     * @return {@code true} if and only if some key maps to the
2571     * {@code value} argument in this table as
2572     * determined by the {@code equals} method;
2573     * {@code false} otherwise
2574     * @throws NullPointerException if the specified value is null
2575     */
2576     public boolean contains(Object value) {
2577     return containsValue(value);
2578     }
2579    
2580     /**
2581     * Maps the specified key to the specified value in this table.
2582     * Neither the key nor the value can be null.
2583     *
2584     * <p> The value can be retrieved by calling the {@code get} method
2585     * with a key that is equal to the original key.
2586     *
2587     * @param key key with which the specified value is to be associated
2588     * @param value value to be associated with the specified key
2589     * @return the previous value associated with {@code key}, or
2590     * {@code null} if there was no mapping for {@code key}
2591     * @throws NullPointerException if the specified key or value is null
2592     */
2593 dl 1.61 @SuppressWarnings("unchecked") public V put(K key, V value) {
2594 dl 1.1 if (key == null || value == null)
2595     throw new NullPointerException();
2596 dl 1.27 return (V)internalPut(key, value);
2597 dl 1.1 }
2598    
2599     /**
2600     * {@inheritDoc}
2601     *
2602     * @return the previous value associated with the specified key,
2603     * or {@code null} if there was no mapping for the key
2604     * @throws NullPointerException if the specified key or value is null
2605     */
2606 dl 1.61 @SuppressWarnings("unchecked") public V putIfAbsent(K key, V value) {
2607 dl 1.1 if (key == null || value == null)
2608     throw new NullPointerException();
2609 dl 1.27 return (V)internalPutIfAbsent(key, value);
2610 dl 1.1 }
2611    
2612     /**
2613     * Copies all of the mappings from the specified map to this one.
2614     * These mappings replace any mappings that this map had for any of the
2615     * keys currently in the specified map.
2616     *
2617     * @param m mappings to be stored in this map
2618     */
2619     public void putAll(Map<? extends K, ? extends V> m) {
2620 dl 1.27 internalPutAll(m);
2621 dl 1.1 }
2622    
2623     /**
2624     * If the specified key is not already associated with a value,
2625 dl 1.41 * computes its value using the given mappingFunction and enters
2626     * it into the map unless null. This is equivalent to
2627 dl 1.27 * <pre> {@code
2628 jsr166 1.13 * if (map.containsKey(key))
2629     * return map.get(key);
2630 dl 1.52 * value = mappingFunction.apply(key);
2631 dl 1.41 * if (value != null)
2632     * map.put(key, value);
2633 jsr166 1.13 * return value;}</pre>
2634 dl 1.1 *
2635 dl 1.27 * except that the action is performed atomically. If the
2636 dl 1.41 * function returns {@code null} no mapping is recorded. If the
2637     * function itself throws an (unchecked) exception, the exception
2638     * is rethrown to its caller, and no mapping is recorded. Some
2639     * attempted update operations on this map by other threads may be
2640     * blocked while computation is in progress, so the computation
2641     * should be short and simple, and must not attempt to update any
2642     * other mappings of this Map. The most appropriate usage is to
2643     * construct a new object serving as an initial mapped value, or
2644     * memoized result, as in:
2645 dl 1.27 *
2646 jsr166 1.13 * <pre> {@code
2647 dl 1.52 * map.computeIfAbsent(key, new Fun<K, V>() {
2648 jsr166 1.13 * public V map(K k) { return new Value(f(k)); }});}</pre>
2649 dl 1.1 *
2650     * @param key key with which the specified value is to be associated
2651     * @param mappingFunction the function to compute a value
2652     * @return the current (existing or computed) value associated with
2653 jsr166 1.67 * the specified key, or null if the computed value is null
2654 dl 1.41 * @throws NullPointerException if the specified key or mappingFunction
2655     * is null
2656 dl 1.5 * @throws IllegalStateException if the computation detectably
2657     * attempts a recursive update to this map that would
2658 jsr166 1.18 * otherwise never complete
2659 dl 1.1 * @throws RuntimeException or Error if the mappingFunction does so,
2660 jsr166 1.18 * in which case the mapping is left unestablished
2661 dl 1.1 */
2662 dl 1.61 @SuppressWarnings("unchecked") public V computeIfAbsent
2663     (K key, Fun<? super K, ? extends V> mappingFunction) {
2664 dl 1.1 if (key == null || mappingFunction == null)
2665     throw new NullPointerException();
2666 dl 1.27 return (V)internalComputeIfAbsent(key, mappingFunction);
2667 dl 1.2 }
2668    
2669     /**
2670 dl 1.52 * If the given key is present, computes a new mapping value given a key and
2671     * its current mapped value. This is equivalent to
2672     * <pre> {@code
2673     * if (map.containsKey(key)) {
2674     * value = remappingFunction.apply(key, map.get(key));
2675     * if (value != null)
2676     * map.put(key, value);
2677     * else
2678     * map.remove(key);
2679     * }
2680     * }</pre>
2681     *
2682     * except that the action is performed atomically. If the
2683     * function returns {@code null}, the mapping is removed. If the
2684     * function itself throws an (unchecked) exception, the exception
2685     * is rethrown to its caller, and the current mapping is left
2686     * unchanged. Some attempted update operations on this map by
2687     * other threads may be blocked while computation is in progress,
2688     * so the computation should be short and simple, and must not
2689     * attempt to update any other mappings of this Map. For example,
2690     * to either create or append new messages to a value mapping:
2691     *
2692     * @param key key with which the specified value is to be associated
2693     * @param remappingFunction the function to compute a value
2694 jsr166 1.56 * @return the new value associated with the specified key, or null if none
2695 dl 1.52 * @throws NullPointerException if the specified key or remappingFunction
2696     * is null
2697     * @throws IllegalStateException if the computation detectably
2698     * attempts a recursive update to this map that would
2699     * otherwise never complete
2700     * @throws RuntimeException or Error if the remappingFunction does so,
2701     * in which case the mapping is unchanged
2702     */
2703 dl 1.61 @SuppressWarnings("unchecked") public V computeIfPresent
2704     (K key, BiFun<? super K, ? super V, ? extends V> remappingFunction) {
2705 dl 1.52 if (key == null || remappingFunction == null)
2706     throw new NullPointerException();
2707     return (V)internalCompute(key, true, remappingFunction);
2708     }
2709    
2710     /**
2711 dl 1.41 * Computes a new mapping value given a key and
2712 dl 1.27 * its current mapped value (or {@code null} if there is no current
2713     * mapping). This is equivalent to
2714 jsr166 1.13 * <pre> {@code
2715 dl 1.52 * value = remappingFunction.apply(key, map.get(key));
2716 dl 1.41 * if (value != null)
2717     * map.put(key, value);
2718     * else
2719     * map.remove(key);
2720 dl 1.27 * }</pre>
2721 dl 1.2 *
2722 dl 1.27 * except that the action is performed atomically. If the
2723 dl 1.41 * function returns {@code null}, the mapping is removed. If the
2724     * function itself throws an (unchecked) exception, the exception
2725     * is rethrown to its caller, and the current mapping is left
2726     * unchanged. Some attempted update operations on this map by
2727     * other threads may be blocked while computation is in progress,
2728     * so the computation should be short and simple, and must not
2729     * attempt to update any other mappings of this Map. For example,
2730     * to either create or append new messages to a value mapping:
2731 dl 1.27 *
2732     * <pre> {@code
2733     * Map<Key, String> map = ...;
2734     * final String msg = ...;
2735 dl 1.52 * map.compute(key, new BiFun<Key, String, String>() {
2736     * public String apply(Key k, String v) {
2737 dl 1.28 * return (v == null) ? msg : v + msg;});}}</pre>
2738 dl 1.2 *
2739     * @param key key with which the specified value is to be associated
2740 dl 1.27 * @param remappingFunction the function to compute a value
2741 jsr166 1.56 * @return the new value associated with the specified key, or null if none
2742 dl 1.27 * @throws NullPointerException if the specified key or remappingFunction
2743 dl 1.41 * is null
2744 dl 1.5 * @throws IllegalStateException if the computation detectably
2745     * attempts a recursive update to this map that would
2746 jsr166 1.18 * otherwise never complete
2747 dl 1.29 * @throws RuntimeException or Error if the remappingFunction does so,
2748 jsr166 1.18 * in which case the mapping is unchanged
2749 dl 1.2 */
2750 dl 1.61 @SuppressWarnings("unchecked") public V compute
2751     (K key, BiFun<? super K, ? super V, ? extends V> remappingFunction) {
2752 dl 1.27 if (key == null || remappingFunction == null)
2753 dl 1.2 throw new NullPointerException();
2754 dl 1.52 return (V)internalCompute(key, false, remappingFunction);
2755     }
2756    
2757     /**
2758     * If the specified key is not already associated
2759     * with a value, associate it with the given value.
2760     * Otherwise, replace the value with the results of
2761     * the given remapping function. This is equivalent to:
2762     * <pre> {@code
2763     * if (!map.containsKey(key))
2764     * map.put(value);
2765     * else {
2766     * newValue = remappingFunction.apply(map.get(key), value);
2767     * if (value != null)
2768     * map.put(key, value);
2769     * else
2770     * map.remove(key);
2771     * }
2772     * }</pre>
2773     * except that the action is performed atomically. If the
2774     * function returns {@code null}, the mapping is removed. If the
2775     * function itself throws an (unchecked) exception, the exception
2776     * is rethrown to its caller, and the current mapping is left
2777     * unchanged. Some attempted update operations on this map by
2778     * other threads may be blocked while computation is in progress,
2779     * so the computation should be short and simple, and must not
2780     * attempt to update any other mappings of this Map.
2781     */
2782 dl 1.61 @SuppressWarnings("unchecked") public V merge
2783     (K key, V value, BiFun<? super V, ? super V, ? extends V> remappingFunction) {
2784 dl 1.52 if (key == null || value == null || remappingFunction == null)
2785     throw new NullPointerException();
2786     return (V)internalMerge(key, value, remappingFunction);
2787 dl 1.1 }
2788    
2789     /**
2790     * Removes the key (and its corresponding value) from this map.
2791     * This method does nothing if the key is not in the map.
2792     *
2793     * @param key the key that needs to be removed
2794     * @return the previous value associated with {@code key}, or
2795     * {@code null} if there was no mapping for {@code key}
2796     * @throws NullPointerException if the specified key is null
2797     */
2798 dl 1.61 @SuppressWarnings("unchecked") public V remove(Object key) {
2799 dl 1.1 if (key == null)
2800     throw new NullPointerException();
2801 jsr166 1.3 return (V)internalReplace(key, null, null);
2802 dl 1.1 }
2803    
2804     /**
2805     * {@inheritDoc}
2806     *
2807     * @throws NullPointerException if the specified key is null
2808     */
2809     public boolean remove(Object key, Object value) {
2810     if (key == null)
2811     throw new NullPointerException();
2812     if (value == null)
2813     return false;
2814     return internalReplace(key, null, value) != null;
2815     }
2816    
2817     /**
2818     * {@inheritDoc}
2819     *
2820     * @throws NullPointerException if any of the arguments are null
2821     */
2822     public boolean replace(K key, V oldValue, V newValue) {
2823     if (key == null || oldValue == null || newValue == null)
2824     throw new NullPointerException();
2825 jsr166 1.3 return internalReplace(key, newValue, oldValue) != null;
2826 dl 1.1 }
2827    
2828     /**
2829     * {@inheritDoc}
2830     *
2831     * @return the previous value associated with the specified key,
2832     * or {@code null} if there was no mapping for the key
2833     * @throws NullPointerException if the specified key or value is null
2834     */
2835 dl 1.61 @SuppressWarnings("unchecked") public V replace(K key, V value) {
2836 dl 1.1 if (key == null || value == null)
2837     throw new NullPointerException();
2838 jsr166 1.3 return (V)internalReplace(key, value, null);
2839 dl 1.1 }
2840    
2841     /**
2842     * Removes all of the mappings from this map.
2843     */
2844     public void clear() {
2845     internalClear();
2846     }
2847    
2848     /**
2849     * Returns a {@link Set} view of the keys contained in this map.
2850     * The set is backed by the map, so changes to the map are
2851     * reflected in the set, and vice-versa. The set supports element
2852     * removal, which removes the corresponding mapping from this map,
2853     * via the {@code Iterator.remove}, {@code Set.remove},
2854     * {@code removeAll}, {@code retainAll}, and {@code clear}
2855     * operations. It does not support the {@code add} or
2856     * {@code addAll} operations.
2857     *
2858     * <p>The view's {@code iterator} is a "weakly consistent" iterator
2859     * that will never throw {@link ConcurrentModificationException},
2860     * and guarantees to traverse elements as they existed upon
2861     * construction of the iterator, and may (but is not guaranteed to)
2862     * reflect any modifications subsequent to construction.
2863     */
2864     public Set<K> keySet() {
2865 dl 1.14 KeySet<K,V> ks = keySet;
2866     return (ks != null) ? ks : (keySet = new KeySet<K,V>(this));
2867 dl 1.1 }
2868    
2869     /**
2870     * Returns a {@link Collection} view of the values contained in this map.
2871     * The collection is backed by the map, so changes to the map are
2872     * reflected in the collection, and vice-versa. The collection
2873     * supports element removal, which removes the corresponding
2874     * mapping from this map, via the {@code Iterator.remove},
2875     * {@code Collection.remove}, {@code removeAll},
2876     * {@code retainAll}, and {@code clear} operations. It does not
2877     * support the {@code add} or {@code addAll} operations.
2878     *
2879     * <p>The view's {@code iterator} is a "weakly consistent" iterator
2880     * that will never throw {@link ConcurrentModificationException},
2881     * and guarantees to traverse elements as they existed upon
2882     * construction of the iterator, and may (but is not guaranteed to)
2883     * reflect any modifications subsequent to construction.
2884     */
2885     public Collection<V> values() {
2886 dl 1.14 Values<K,V> vs = values;
2887     return (vs != null) ? vs : (values = new Values<K,V>(this));
2888 dl 1.1 }
2889    
2890     /**
2891     * Returns a {@link Set} view of the mappings contained in this map.
2892     * The set is backed by the map, so changes to the map are
2893     * reflected in the set, and vice-versa. The set supports element
2894     * removal, which removes the corresponding mapping from the map,
2895     * via the {@code Iterator.remove}, {@code Set.remove},
2896     * {@code removeAll}, {@code retainAll}, and {@code clear}
2897     * operations. It does not support the {@code add} or
2898     * {@code addAll} operations.
2899     *
2900     * <p>The view's {@code iterator} is a "weakly consistent" iterator
2901     * that will never throw {@link ConcurrentModificationException},
2902     * and guarantees to traverse elements as they existed upon
2903     * construction of the iterator, and may (but is not guaranteed to)
2904     * reflect any modifications subsequent to construction.
2905     */
2906     public Set<Map.Entry<K,V>> entrySet() {
2907 dl 1.14 EntrySet<K,V> es = entrySet;
2908     return (es != null) ? es : (entrySet = new EntrySet<K,V>(this));
2909 dl 1.1 }
2910    
2911     /**
2912     * Returns an enumeration of the keys in this table.
2913     *
2914     * @return an enumeration of the keys in this table
2915     * @see #keySet()
2916     */
2917     public Enumeration<K> keys() {
2918 dl 1.14 return new KeyIterator<K,V>(this);
2919 dl 1.1 }
2920    
2921     /**
2922     * Returns an enumeration of the values in this table.
2923     *
2924     * @return an enumeration of the values in this table
2925     * @see #values()
2926     */
2927     public Enumeration<V> elements() {
2928 dl 1.14 return new ValueIterator<K,V>(this);
2929 dl 1.1 }
2930    
2931     /**
2932 jsr166 1.55 * Returns a partitionable iterator of the keys in this map.
2933 dl 1.41 *
2934 jsr166 1.55 * @return a partitionable iterator of the keys in this map
2935 dl 1.41 */
2936     public Spliterator<K> keySpliterator() {
2937     return new KeyIterator<K,V>(this);
2938     }
2939    
2940     /**
2941 jsr166 1.55 * Returns a partitionable iterator of the values in this map.
2942 dl 1.41 *
2943 jsr166 1.55 * @return a partitionable iterator of the values in this map
2944 dl 1.41 */
2945     public Spliterator<V> valueSpliterator() {
2946     return new ValueIterator<K,V>(this);
2947     }
2948    
2949     /**
2950 jsr166 1.55 * Returns a partitionable iterator of the entries in this map.
2951 dl 1.41 *
2952 jsr166 1.55 * @return a partitionable iterator of the entries in this map
2953 dl 1.41 */
2954     public Spliterator<Map.Entry<K,V>> entrySpliterator() {
2955     return new EntryIterator<K,V>(this);
2956     }
2957    
2958     /**
2959 dl 1.2 * Returns the hash code value for this {@link Map}, i.e.,
2960     * the sum of, for each key-value pair in the map,
2961     * {@code key.hashCode() ^ value.hashCode()}.
2962     *
2963     * @return the hash code value for this map
2964 dl 1.1 */
2965     public int hashCode() {
2966 dl 1.14 int h = 0;
2967 dl 1.52 Traverser<K,V,Object> it = new Traverser<K,V,Object>(this);
2968 dl 1.41 Object v;
2969     while ((v = it.advance()) != null) {
2970     h += it.nextKey.hashCode() ^ v.hashCode();
2971 dl 1.14 }
2972     return h;
2973 dl 1.1 }
2974    
2975     /**
2976 dl 1.2 * Returns a string representation of this map. The string
2977     * representation consists of a list of key-value mappings (in no
2978     * particular order) enclosed in braces ("{@code {}}"). Adjacent
2979     * mappings are separated by the characters {@code ", "} (comma
2980     * and space). Each key-value mapping is rendered as the key
2981     * followed by an equals sign ("{@code =}") followed by the
2982     * associated value.
2983     *
2984     * @return a string representation of this map
2985 dl 1.1 */
2986     public String toString() {
2987 dl 1.52 Traverser<K,V,Object> it = new Traverser<K,V,Object>(this);
2988 dl 1.14 StringBuilder sb = new StringBuilder();
2989     sb.append('{');
2990 dl 1.41 Object v;
2991     if ((v = it.advance()) != null) {
2992 dl 1.14 for (;;) {
2993 dl 1.41 Object k = it.nextKey;
2994 dl 1.14 sb.append(k == this ? "(this Map)" : k);
2995     sb.append('=');
2996     sb.append(v == this ? "(this Map)" : v);
2997 dl 1.41 if ((v = it.advance()) == null)
2998 dl 1.14 break;
2999     sb.append(',').append(' ');
3000     }
3001     }
3002     return sb.append('}').toString();
3003 dl 1.1 }
3004    
3005     /**
3006 dl 1.2 * Compares the specified object with this map for equality.
3007     * Returns {@code true} if the given object is a map with the same
3008     * mappings as this map. This operation may return misleading
3009     * results if either map is concurrently modified during execution
3010     * of this method.
3011     *
3012     * @param o object to be compared for equality with this map
3013     * @return {@code true} if the specified object is equal to this map
3014 dl 1.1 */
3015     public boolean equals(Object o) {
3016 dl 1.14 if (o != this) {
3017     if (!(o instanceof Map))
3018     return false;
3019     Map<?,?> m = (Map<?,?>) o;
3020 dl 1.52 Traverser<K,V,Object> it = new Traverser<K,V,Object>(this);
3021 dl 1.41 Object val;
3022     while ((val = it.advance()) != null) {
3023 dl 1.14 Object v = m.get(it.nextKey);
3024     if (v == null || (v != val && !v.equals(val)))
3025 dl 1.1 return false;
3026 dl 1.14 }
3027 dl 1.1 for (Map.Entry<?,?> e : m.entrySet()) {
3028 dl 1.14 Object mk, mv, v;
3029     if ((mk = e.getKey()) == null ||
3030     (mv = e.getValue()) == null ||
3031     (v = internalGet(mk)) == null ||
3032     (mv != v && !mv.equals(v)))
3033 dl 1.1 return false;
3034     }
3035 dl 1.14 }
3036     return true;
3037     }
3038    
3039     /* ----------------Iterators -------------- */
3040    
3041 dl 1.61 @SuppressWarnings("serial") static final class KeyIterator<K,V> extends Traverser<K,V,Object>
3042 dl 1.41 implements Spliterator<K>, Enumeration<K> {
3043     KeyIterator(ConcurrentHashMapV8<K, V> map) { super(map); }
3044 dl 1.61 KeyIterator(Traverser<K,V,Object> it) {
3045     super(it);
3046 dl 1.41 }
3047     public KeyIterator<K,V> split() {
3048     if (last != null || (next != null && nextVal == null))
3049     throw new IllegalStateException();
3050 dl 1.61 return new KeyIterator<K,V>(this);
3051 dl 1.14 }
3052 dl 1.61 @SuppressWarnings("unchecked") public final K next() {
3053 dl 1.41 if (nextVal == null && advance() == null)
3054 dl 1.14 throw new NoSuchElementException();
3055     Object k = nextKey;
3056 dl 1.41 nextVal = null;
3057     return (K) k;
3058 dl 1.14 }
3059    
3060     public final K nextElement() { return next(); }
3061     }
3062    
3063 dl 1.61 @SuppressWarnings("serial") static final class ValueIterator<K,V> extends Traverser<K,V,Object>
3064 dl 1.41 implements Spliterator<V>, Enumeration<V> {
3065 dl 1.14 ValueIterator(ConcurrentHashMapV8<K, V> map) { super(map); }
3066 dl 1.61 ValueIterator(Traverser<K,V,Object> it) {
3067     super(it);
3068 dl 1.41 }
3069     public ValueIterator<K,V> split() {
3070     if (last != null || (next != null && nextVal == null))
3071     throw new IllegalStateException();
3072 dl 1.61 return new ValueIterator<K,V>(this);
3073 dl 1.41 }
3074    
3075 dl 1.61 @SuppressWarnings("unchecked") public final V next() {
3076 dl 1.41 Object v;
3077     if ((v = nextVal) == null && (v = advance()) == null)
3078 dl 1.14 throw new NoSuchElementException();
3079 dl 1.41 nextVal = null;
3080     return (V) v;
3081 dl 1.14 }
3082    
3083     public final V nextElement() { return next(); }
3084     }
3085    
3086 dl 1.61 @SuppressWarnings("serial") static final class EntryIterator<K,V> extends Traverser<K,V,Object>
3087 dl 1.41 implements Spliterator<Map.Entry<K,V>> {
3088 dl 1.14 EntryIterator(ConcurrentHashMapV8<K, V> map) { super(map); }
3089 dl 1.61 EntryIterator(Traverser<K,V,Object> it) {
3090     super(it);
3091 dl 1.41 }
3092     public EntryIterator<K,V> split() {
3093     if (last != null || (next != null && nextVal == null))
3094     throw new IllegalStateException();
3095 dl 1.61 return new EntryIterator<K,V>(this);
3096 dl 1.41 }
3097 dl 1.24
3098 dl 1.61 @SuppressWarnings("unchecked") public final Map.Entry<K,V> next() {
3099 dl 1.41 Object v;
3100     if ((v = nextVal) == null && (v = advance()) == null)
3101 dl 1.24 throw new NoSuchElementException();
3102     Object k = nextKey;
3103 dl 1.41 nextVal = null;
3104     return new MapEntry<K,V>((K)k, (V)v, map);
3105 dl 1.1 }
3106     }
3107    
3108     /**
3109 dl 1.41 * Exported Entry for iterators
3110 dl 1.1 */
3111 dl 1.41 static final class MapEntry<K,V> implements Map.Entry<K, V> {
3112 dl 1.14 final K key; // non-null
3113     V val; // non-null
3114 dl 1.41 final ConcurrentHashMapV8<K, V> map;
3115     MapEntry(K key, V val, ConcurrentHashMapV8<K, V> map) {
3116     this.key = key;
3117     this.val = val;
3118     this.map = map;
3119     }
3120 dl 1.14 public final K getKey() { return key; }
3121     public final V getValue() { return val; }
3122     public final int hashCode() { return key.hashCode() ^ val.hashCode(); }
3123     public final String toString(){ return key + "=" + val; }
3124    
3125     public final boolean equals(Object o) {
3126     Object k, v; Map.Entry<?,?> e;
3127     return ((o instanceof Map.Entry) &&
3128     (k = (e = (Map.Entry<?,?>)o).getKey()) != null &&
3129     (v = e.getValue()) != null &&
3130     (k == key || k.equals(key)) &&
3131     (v == val || v.equals(val)));
3132 dl 1.1 }
3133    
3134     /**
3135     * Sets our entry's value and writes through to the map. The
3136 jsr166 1.50 * value to return is somewhat arbitrary here. Since we do not
3137     * necessarily track asynchronous changes, the most recent
3138 dl 1.41 * "previous" value could be different from what we return (or
3139     * could even have been removed in which case the put will
3140     * re-establish). We do not and cannot guarantee more.
3141 dl 1.1 */
3142 dl 1.14 public final V setValue(V value) {
3143 dl 1.1 if (value == null) throw new NullPointerException();
3144 dl 1.14 V v = val;
3145     val = value;
3146     map.put(key, value);
3147 dl 1.1 return v;
3148     }
3149     }
3150    
3151 dl 1.14 /* ----------------Views -------------- */
3152 dl 1.1
3153 dl 1.24 /**
3154 dl 1.41 * Base class for views.
3155 dl 1.14 */
3156 dl 1.52 static abstract class CHMView<K, V> {
3157 dl 1.14 final ConcurrentHashMapV8<K, V> map;
3158 dl 1.52 CHMView(ConcurrentHashMapV8<K, V> map) { this.map = map; }
3159 dl 1.14 public final int size() { return map.size(); }
3160     public final boolean isEmpty() { return map.isEmpty(); }
3161     public final void clear() { map.clear(); }
3162 dl 1.24
3163     // implementations below rely on concrete classes supplying these
3164 dl 1.41 abstract public Iterator<?> iterator();
3165 dl 1.24 abstract public boolean contains(Object o);
3166     abstract public boolean remove(Object o);
3167    
3168     private static final String oomeMsg = "Required array size too large";
3169    
3170     public final Object[] toArray() {
3171 dl 1.52 long sz = map.mappingCount();
3172 dl 1.24 if (sz > (long)(MAX_ARRAY_SIZE))
3173     throw new OutOfMemoryError(oomeMsg);
3174     int n = (int)sz;
3175     Object[] r = new Object[n];
3176     int i = 0;
3177 dl 1.41 Iterator<?> it = iterator();
3178 dl 1.24 while (it.hasNext()) {
3179     if (i == n) {
3180     if (n >= MAX_ARRAY_SIZE)
3181     throw new OutOfMemoryError(oomeMsg);
3182     if (n >= MAX_ARRAY_SIZE - (MAX_ARRAY_SIZE >>> 1) - 1)
3183     n = MAX_ARRAY_SIZE;
3184     else
3185     n += (n >>> 1) + 1;
3186     r = Arrays.copyOf(r, n);
3187     }
3188     r[i++] = it.next();
3189     }
3190     return (i == n) ? r : Arrays.copyOf(r, i);
3191     }
3192    
3193 dl 1.61 @SuppressWarnings("unchecked") public final <T> T[] toArray(T[] a) {
3194 dl 1.52 long sz = map.mappingCount();
3195 dl 1.24 if (sz > (long)(MAX_ARRAY_SIZE))
3196     throw new OutOfMemoryError(oomeMsg);
3197     int m = (int)sz;
3198     T[] r = (a.length >= m) ? a :
3199     (T[])java.lang.reflect.Array
3200     .newInstance(a.getClass().getComponentType(), m);
3201     int n = r.length;
3202     int i = 0;
3203 dl 1.41 Iterator<?> it = iterator();
3204 dl 1.24 while (it.hasNext()) {
3205     if (i == n) {
3206     if (n >= MAX_ARRAY_SIZE)
3207     throw new OutOfMemoryError(oomeMsg);
3208     if (n >= MAX_ARRAY_SIZE - (MAX_ARRAY_SIZE >>> 1) - 1)
3209     n = MAX_ARRAY_SIZE;
3210     else
3211     n += (n >>> 1) + 1;
3212     r = Arrays.copyOf(r, n);
3213     }
3214     r[i++] = (T)it.next();
3215     }
3216     if (a == r && i < n) {
3217     r[i] = null; // null-terminate
3218     return r;
3219     }
3220     return (i == n) ? r : Arrays.copyOf(r, i);
3221     }
3222    
3223     public final int hashCode() {
3224     int h = 0;
3225 dl 1.41 for (Iterator<?> it = iterator(); it.hasNext();)
3226 dl 1.24 h += it.next().hashCode();
3227     return h;
3228     }
3229    
3230     public final String toString() {
3231     StringBuilder sb = new StringBuilder();
3232     sb.append('[');
3233 dl 1.41 Iterator<?> it = iterator();
3234 dl 1.24 if (it.hasNext()) {
3235     for (;;) {
3236     Object e = it.next();
3237     sb.append(e == this ? "(this Collection)" : e);
3238     if (!it.hasNext())
3239     break;
3240     sb.append(',').append(' ');
3241     }
3242     }
3243     return sb.append(']').toString();
3244     }
3245    
3246     public final boolean containsAll(Collection<?> c) {
3247     if (c != this) {
3248     for (Iterator<?> it = c.iterator(); it.hasNext();) {
3249     Object e = it.next();
3250     if (e == null || !contains(e))
3251     return false;
3252     }
3253     }
3254     return true;
3255     }
3256    
3257 jsr166 1.32 public final boolean removeAll(Collection<?> c) {
3258 dl 1.24 boolean modified = false;
3259 dl 1.41 for (Iterator<?> it = iterator(); it.hasNext();) {
3260 dl 1.24 if (c.contains(it.next())) {
3261     it.remove();
3262     modified = true;
3263     }
3264     }
3265     return modified;
3266     }
3267    
3268     public final boolean retainAll(Collection<?> c) {
3269     boolean modified = false;
3270 dl 1.41 for (Iterator<?> it = iterator(); it.hasNext();) {
3271 dl 1.24 if (!c.contains(it.next())) {
3272     it.remove();
3273     modified = true;
3274     }
3275     }
3276     return modified;
3277     }
3278    
3279     }
3280    
3281 dl 1.52 static final class KeySet<K,V> extends CHMView<K,V> implements Set<K> {
3282     KeySet(ConcurrentHashMapV8<K, V> map) {
3283     super(map);
3284     }
3285 dl 1.14 public final boolean contains(Object o) { return map.containsKey(o); }
3286     public final boolean remove(Object o) { return map.remove(o) != null; }
3287     public final Iterator<K> iterator() {
3288     return new KeyIterator<K,V>(map);
3289 dl 1.1 }
3290 dl 1.24 public final boolean add(K e) {
3291     throw new UnsupportedOperationException();
3292     }
3293     public final boolean addAll(Collection<? extends K> c) {
3294     throw new UnsupportedOperationException();
3295     }
3296     public boolean equals(Object o) {
3297     Set<?> c;
3298     return ((o instanceof Set) &&
3299     ((c = (Set<?>)o) == this ||
3300     (containsAll(c) && c.containsAll(this))));
3301     }
3302 dl 1.1 }
3303    
3304 dl 1.52
3305     static final class Values<K,V> extends CHMView<K,V>
3306 jsr166 1.34 implements Collection<V> {
3307 dl 1.24 Values(ConcurrentHashMapV8<K, V> map) { super(map); }
3308     public final boolean contains(Object o) { return map.containsValue(o); }
3309     public final boolean remove(Object o) {
3310     if (o != null) {
3311     Iterator<V> it = new ValueIterator<K,V>(map);
3312     while (it.hasNext()) {
3313     if (o.equals(it.next())) {
3314     it.remove();
3315     return true;
3316     }
3317     }
3318     }
3319     return false;
3320     }
3321 dl 1.14 public final Iterator<V> iterator() {
3322     return new ValueIterator<K,V>(map);
3323 dl 1.1 }
3324 dl 1.24 public final boolean add(V e) {
3325     throw new UnsupportedOperationException();
3326     }
3327     public final boolean addAll(Collection<? extends V> c) {
3328     throw new UnsupportedOperationException();
3329     }
3330 dl 1.52
3331 dl 1.1 }
3332    
3333 dl 1.52 static final class EntrySet<K,V> extends CHMView<K,V>
3334 dl 1.24 implements Set<Map.Entry<K,V>> {
3335     EntrySet(ConcurrentHashMapV8<K, V> map) { super(map); }
3336 dl 1.14 public final boolean contains(Object o) {
3337     Object k, v, r; Map.Entry<?,?> e;
3338     return ((o instanceof Map.Entry) &&
3339     (k = (e = (Map.Entry<?,?>)o).getKey()) != null &&
3340     (r = map.get(k)) != null &&
3341     (v = e.getValue()) != null &&
3342     (v == r || v.equals(r)));
3343 dl 1.1 }
3344 dl 1.14 public final boolean remove(Object o) {
3345     Object k, v; Map.Entry<?,?> e;
3346     return ((o instanceof Map.Entry) &&
3347     (k = (e = (Map.Entry<?,?>)o).getKey()) != null &&
3348     (v = e.getValue()) != null &&
3349     map.remove(k, v));
3350 dl 1.1 }
3351 dl 1.24 public final Iterator<Map.Entry<K,V>> iterator() {
3352     return new EntryIterator<K,V>(map);
3353     }
3354     public final boolean add(Entry<K,V> e) {
3355     throw new UnsupportedOperationException();
3356     }
3357     public final boolean addAll(Collection<? extends Entry<K,V>> c) {
3358     throw new UnsupportedOperationException();
3359     }
3360     public boolean equals(Object o) {
3361     Set<?> c;
3362     return ((o instanceof Set) &&
3363     ((c = (Set<?>)o) == this ||
3364     (containsAll(c) && c.containsAll(this))));
3365     }
3366 dl 1.1 }
3367    
3368     /* ---------------- Serialization Support -------------- */
3369    
3370     /**
3371 dl 1.14 * Stripped-down version of helper class used in previous version,
3372     * declared for the sake of serialization compatibility
3373 dl 1.1 */
3374 dl 1.14 static class Segment<K,V> implements Serializable {
3375 dl 1.1 private static final long serialVersionUID = 2249069246763182397L;
3376     final float loadFactor;
3377     Segment(float lf) { this.loadFactor = lf; }
3378     }
3379    
3380     /**
3381     * Saves the state of the {@code ConcurrentHashMapV8} instance to a
3382     * stream (i.e., serializes it).
3383     * @param s the stream
3384     * @serialData
3385     * the key (Object) and value (Object)
3386     * for each key-value mapping, followed by a null pair.
3387     * The key-value mappings are emitted in no particular order.
3388     */
3389 dl 1.61 @SuppressWarnings("unchecked") private void writeObject(java.io.ObjectOutputStream s)
3390 dl 1.52 throws java.io.IOException {
3391 dl 1.1 if (segments == null) { // for serialization compatibility
3392     segments = (Segment<K,V>[])
3393     new Segment<?,?>[DEFAULT_CONCURRENCY_LEVEL];
3394     for (int i = 0; i < segments.length; ++i)
3395 dl 1.16 segments[i] = new Segment<K,V>(LOAD_FACTOR);
3396 dl 1.1 }
3397     s.defaultWriteObject();
3398 dl 1.52 Traverser<K,V,Object> it = new Traverser<K,V,Object>(this);
3399 dl 1.41 Object v;
3400     while ((v = it.advance()) != null) {
3401 dl 1.14 s.writeObject(it.nextKey);
3402 dl 1.41 s.writeObject(v);
3403 dl 1.14 }
3404 dl 1.1 s.writeObject(null);
3405     s.writeObject(null);
3406     segments = null; // throw away
3407     }
3408    
3409     /**
3410 jsr166 1.9 * Reconstitutes the instance from a stream (that is, deserializes it).
3411 dl 1.1 * @param s the stream
3412     */
3413 dl 1.61 @SuppressWarnings("unchecked") private void readObject(java.io.ObjectInputStream s)
3414 dl 1.52 throws java.io.IOException, ClassNotFoundException {
3415 dl 1.1 s.defaultReadObject();
3416     this.segments = null; // unneeded
3417 jsr166 1.21 // initialize transient final field
3418 dl 1.14 UNSAFE.putObjectVolatile(this, counterOffset, new LongAdder());
3419    
3420     // Create all nodes, then place in table once size is known
3421     long size = 0L;
3422     Node p = null;
3423 dl 1.1 for (;;) {
3424 dl 1.14 K k = (K) s.readObject();
3425     V v = (V) s.readObject();
3426     if (k != null && v != null) {
3427 dl 1.38 int h = spread(k.hashCode());
3428     p = new Node(h, k, v, p);
3429 dl 1.14 ++size;
3430     }
3431     else
3432 dl 1.1 break;
3433 dl 1.14 }
3434     if (p != null) {
3435     boolean init = false;
3436 dl 1.24 int n;
3437     if (size >= (long)(MAXIMUM_CAPACITY >>> 1))
3438     n = MAXIMUM_CAPACITY;
3439     else {
3440     int sz = (int)size;
3441     n = tableSizeFor(sz + (sz >>> 1) + 1);
3442     }
3443     int sc = sizeCtl;
3444 dl 1.38 boolean collide = false;
3445 dl 1.24 if (n > sc &&
3446     UNSAFE.compareAndSwapInt(this, sizeCtlOffset, sc, -1)) {
3447 dl 1.14 try {
3448     if (table == null) {
3449     init = true;
3450     Node[] tab = new Node[n];
3451     int mask = n - 1;
3452     while (p != null) {
3453     int j = p.hash & mask;
3454     Node next = p.next;
3455 dl 1.38 Node q = p.next = tabAt(tab, j);
3456 dl 1.14 setTabAt(tab, j, p);
3457 dl 1.38 if (!collide && q != null && q.hash == p.hash)
3458     collide = true;
3459 dl 1.14 p = next;
3460     }
3461     table = tab;
3462     counter.add(size);
3463 dl 1.29 sc = n - (n >>> 2);
3464 dl 1.14 }
3465     } finally {
3466 dl 1.24 sizeCtl = sc;
3467 dl 1.14 }
3468 dl 1.38 if (collide) { // rescan and convert to TreeBins
3469     Node[] tab = table;
3470     for (int i = 0; i < tab.length; ++i) {
3471     int c = 0;
3472     for (Node e = tabAt(tab, i); e != null; e = e.next) {
3473     if (++c > TREE_THRESHOLD &&
3474     (e.key instanceof Comparable)) {
3475     replaceWithTreeBin(tab, i, e.key);
3476     break;
3477     }
3478     }
3479     }
3480     }
3481 dl 1.14 }
3482     if (!init) { // Can only happen if unsafely published.
3483     while (p != null) {
3484 dl 1.27 internalPut(p.key, p.val);
3485 dl 1.14 p = p.next;
3486     }
3487     }
3488 dl 1.1 }
3489     }
3490    
3491    
3492 dl 1.52 // -------------------------------------------------------
3493    
3494     // Sams
3495     /** Interface describing a void action of one argument */
3496     public interface Action<A> { void apply(A a); }
3497     /** Interface describing a void action of two arguments */
3498     public interface BiAction<A,B> { void apply(A a, B b); }
3499     /** Interface describing a function of one argument */
3500     public interface Fun<A,T> { T apply(A a); }
3501     /** Interface describing a function of two arguments */
3502     public interface BiFun<A,B,T> { T apply(A a, B b); }
3503     /** Interface describing a function of no arguments */
3504     public interface Generator<T> { T apply(); }
3505     /** Interface describing a function mapping its argument to a double */
3506     public interface ObjectToDouble<A> { double apply(A a); }
3507     /** Interface describing a function mapping its argument to a long */
3508     public interface ObjectToLong<A> { long apply(A a); }
3509     /** Interface describing a function mapping its argument to an int */
3510     public interface ObjectToInt<A> {int apply(A a); }
3511     /** Interface describing a function mapping two arguments to a double */
3512     public interface ObjectByObjectToDouble<A,B> { double apply(A a, B b); }
3513     /** Interface describing a function mapping two arguments to a long */
3514     public interface ObjectByObjectToLong<A,B> { long apply(A a, B b); }
3515     /** Interface describing a function mapping two arguments to an int */
3516     public interface ObjectByObjectToInt<A,B> {int apply(A a, B b); }
3517     /** Interface describing a function mapping a double to a double */
3518     public interface DoubleToDouble { double apply(double a); }
3519     /** Interface describing a function mapping a long to a long */
3520     public interface LongToLong { long apply(long a); }
3521     /** Interface describing a function mapping an int to an int */
3522     public interface IntToInt { int apply(int a); }
3523     /** Interface describing a function mapping two doubles to a double */
3524     public interface DoubleByDoubleToDouble { double apply(double a, double b); }
3525     /** Interface describing a function mapping two longs to a long */
3526     public interface LongByLongToLong { long apply(long a, long b); }
3527     /** Interface describing a function mapping two ints to an int */
3528     public interface IntByIntToInt { int apply(int a, int b); }
3529    
3530    
3531     // -------------------------------------------------------
3532    
3533     /**
3534     * Returns an extended {@link Parallel} view of this map using the
3535     * given executor for bulk parallel operations.
3536     *
3537     * @param executor the executor
3538     * @return a parallel view
3539     */
3540     public Parallel parallel(ForkJoinPool executor) {
3541     return new Parallel(executor);
3542     }
3543    
3544     /**
3545     * An extended view of a ConcurrentHashMap supporting bulk
3546 jsr166 1.54 * parallel operations. These operations are designed to be
3547 dl 1.52 * safely, and often sensibly, applied even with maps that are
3548     * being concurrently updated by other threads; for example, when
3549     * computing a snapshot summary of the values in a shared
3550     * registry. There are three kinds of operation, each with four
3551     * forms, accepting functions with Keys, Values, Entries, and
3552     * (Key, Value) arguments and/or return values. Because the
3553     * elements of a ConcurrentHashMap are not ordered in any
3554     * particular way, and may be processed in different orders in
3555     * different parallel executions, the correctness of supplied
3556     * functions should not depend on any ordering, or on any other
3557     * objects or values that may transiently change while computation
3558     * is in progress; and except for forEach actions, should ideally
3559     * be side-effect-free.
3560     *
3561     * <ul>
3562     * <li> forEach: Perform a given action on each element.
3563     * A variant form applies a given transformation on each element
3564     * before performing the action.</li>
3565     *
3566     * <li> search: Return the first available non-null result of
3567     * applying a given function on each element; skipping further
3568     * search when a result is found.</li>
3569     *
3570     * <li> reduce: Accumulate each element. The supplied reduction
3571     * function cannot rely on ordering (more formally, it should be
3572     * both associative and commutative). There are five variants:
3573     *
3574     * <ul>
3575     *
3576     * <li> Plain reductions. (There is not a form of this method for
3577     * (key, value) function arguments since there is no corresponding
3578     * return type.)</li>
3579     *
3580     * <li> Mapped reductions that accumulate the results of a given
3581     * function applied to each element.</li>
3582     *
3583     * <li> Reductions to scalar doubles, longs, and ints, using a
3584     * given basis value.</li>
3585     *
3586     * </li>
3587     * </ul>
3588     * </ul>
3589     *
3590     * <p>The concurrency properties of the bulk operations follow
3591     * from those of ConcurrentHashMap: Any non-null result returned
3592     * from {@code get(key)} and related access methods bears a
3593     * happens-before relation with the associated insertion or
3594     * update. The result of any bulk operation reflects the
3595     * composition of these per-element relations (but is not
3596     * necessarily atomic with respect to the map as a whole unless it
3597     * is somehow known to be quiescent). Conversely, because keys
3598     * and values in the map are never null, null serves as a reliable
3599     * atomic indicator of the current lack of any result. To
3600     * maintain this property, null serves as an implicit basis for
3601     * all non-scalar reduction operations. For the double, long, and
3602     * int versions, the basis should be one that, when combined with
3603     * any other value, returns that other value (more formally, it
3604     * should be the identity element for the reduction). Most common
3605     * reductions have these properties; for example, computing a sum
3606     * with basis 0 or a minimum with basis MAX_VALUE.
3607     *
3608     * <p>Search and transformation functions provided as arguments
3609     * should similarly return null to indicate the lack of any result
3610     * (in which case it is not used). In the case of mapped
3611     * reductions, this also enables transformations to serve as
3612     * filters, returning null (or, in the case of primitive
3613     * specializations, the identity basis) if the element should not
3614     * be combined. You can create compound transformations and
3615     * filterings by composing them yourself under this "null means
3616     * there is nothing there now" rule before using them in search or
3617     * reduce operations.
3618     *
3619     * <p>Methods accepting and/or returning Entry arguments maintain
3620     * key-value associations. They may be useful for example when
3621     * finding the key for the greatest value. Note that "plain" Entry
3622     * arguments can be supplied using {@code new
3623     * AbstractMap.SimpleEntry(k,v)}.
3624     *
3625     * <p> Bulk operations may complete abruptly, throwing an
3626     * exception encountered in the application of a supplied
3627     * function. Bear in mind when handling such exceptions that other
3628     * concurrently executing functions could also have thrown
3629     * exceptions, or would have done so if the first exception had
3630     * not occurred.
3631     *
3632     * <p>Parallel speedups compared to sequential processing are
3633     * common but not guaranteed. Operations involving brief
3634     * functions on small maps may execute more slowly than sequential
3635     * loops if the underlying work to parallelize the computation is
3636     * more expensive than the computation itself. Similarly,
3637     * parallelization may not lead to much actual parallelism if all
3638     * processors are busy performing unrelated tasks.
3639     *
3640     * <p> All arguments to all task methods must be non-null.
3641     *
3642     * <p><em>jsr166e note: During transition, this class
3643     * uses nested functional interfaces with different names but the
3644     * same forms as those expected for JDK8.<em>
3645     */
3646     public class Parallel {
3647     final ForkJoinPool fjp;
3648    
3649     /**
3650     * Returns an extended view of this map using the given
3651     * executor for bulk parallel operations.
3652     *
3653     * @param executor the executor
3654     */
3655     public Parallel(ForkJoinPool executor) {
3656     this.fjp = executor;
3657     }
3658    
3659     /**
3660     * Performs the given action for each (key, value).
3661     *
3662     * @param action the action
3663     */
3664 jsr166 1.53 public void forEach(BiAction<K,V> action) {
3665 dl 1.52 fjp.invoke(ForkJoinTasks.forEach
3666     (ConcurrentHashMapV8.this, action));
3667     }
3668    
3669     /**
3670     * Performs the given action for each non-null transformation
3671     * of each (key, value).
3672     *
3673     * @param transformer a function returning the transformation
3674 jsr166 1.68 * for an element, or null if there is no transformation (in
3675 jsr166 1.67 * which case the action is not applied)
3676 dl 1.52 * @param action the action
3677     */
3678 jsr166 1.53 public <U> void forEach(BiFun<? super K, ? super V, ? extends U> transformer,
3679 dl 1.52 Action<U> action) {
3680     fjp.invoke(ForkJoinTasks.forEach
3681     (ConcurrentHashMapV8.this, transformer, action));
3682     }
3683    
3684     /**
3685     * Returns a non-null result from applying the given search
3686 dl 1.59 * function on each (key, value), or null if none. Upon
3687     * success, further element processing is suppressed and the
3688     * results of any other parallel invocations of the search
3689     * function are ignored.
3690 dl 1.52 *
3691     * @param searchFunction a function returning a non-null
3692     * result on success, else null
3693     * @return a non-null result from applying the given search
3694     * function on each (key, value), or null if none
3695     */
3696     public <U> U search(BiFun<? super K, ? super V, ? extends U> searchFunction) {
3697     return fjp.invoke(ForkJoinTasks.search
3698     (ConcurrentHashMapV8.this, searchFunction));
3699 dl 1.1 }
3700    
3701 dl 1.52 /**
3702     * Returns the result of accumulating the given transformation
3703     * of all (key, value) pairs using the given reducer to
3704     * combine values, or null if none.
3705     *
3706     * @param transformer a function returning the transformation
3707 jsr166 1.68 * for an element, or null if there is no transformation (in
3708 jsr166 1.67 * which case it is not combined)
3709 dl 1.52 * @param reducer a commutative associative combining function
3710     * @return the result of accumulating the given transformation
3711     * of all (key, value) pairs
3712     */
3713     public <U> U reduce(BiFun<? super K, ? super V, ? extends U> transformer,
3714     BiFun<? super U, ? super U, ? extends U> reducer) {
3715     return fjp.invoke(ForkJoinTasks.reduce
3716     (ConcurrentHashMapV8.this, transformer, reducer));
3717 dl 1.1 }
3718    
3719 dl 1.52 /**
3720     * Returns the result of accumulating the given transformation
3721     * of all (key, value) pairs using the given reducer to
3722     * combine values, and the given basis as an identity value.
3723     *
3724     * @param transformer a function returning the transformation
3725     * for an element
3726     * @param basis the identity (initial default value) for the reduction
3727     * @param reducer a commutative associative combining function
3728     * @return the result of accumulating the given transformation
3729     * of all (key, value) pairs
3730     */
3731     public double reduceToDouble(ObjectByObjectToDouble<? super K, ? super V> transformer,
3732     double basis,
3733     DoubleByDoubleToDouble reducer) {
3734     return fjp.invoke(ForkJoinTasks.reduceToDouble
3735     (ConcurrentHashMapV8.this, transformer, basis, reducer));
3736     }
3737    
3738     /**
3739     * Returns the result of accumulating the given transformation
3740     * of all (key, value) pairs using the given reducer to
3741     * combine values, and the given basis as an identity value.
3742     *
3743     * @param transformer a function returning the transformation
3744     * for an element
3745     * @param basis the identity (initial default value) for the reduction
3746     * @param reducer a commutative associative combining function
3747     * @return the result of accumulating the given transformation
3748 dl 1.59 * of all (key, value) pairs
3749 dl 1.52 */
3750     public long reduceToLong(ObjectByObjectToLong<? super K, ? super V> transformer,
3751     long basis,
3752     LongByLongToLong reducer) {
3753     return fjp.invoke(ForkJoinTasks.reduceToLong
3754     (ConcurrentHashMapV8.this, transformer, basis, reducer));
3755     }
3756    
3757     /**
3758     * Returns the result of accumulating the given transformation
3759     * of all (key, value) pairs using the given reducer to
3760     * combine values, and the given basis as an identity value.
3761     *
3762     * @param transformer a function returning the transformation
3763     * for an element
3764     * @param basis the identity (initial default value) for the reduction
3765     * @param reducer a commutative associative combining function
3766     * @return the result of accumulating the given transformation
3767     * of all (key, value) pairs
3768     */
3769     public int reduceToInt(ObjectByObjectToInt<? super K, ? super V> transformer,
3770     int basis,
3771     IntByIntToInt reducer) {
3772     return fjp.invoke(ForkJoinTasks.reduceToInt
3773     (ConcurrentHashMapV8.this, transformer, basis, reducer));
3774     }
3775    
3776     /**
3777 jsr166 1.56 * Performs the given action for each key.
3778 dl 1.52 *
3779     * @param action the action
3780     */
3781 jsr166 1.53 public void forEachKey(Action<K> action) {
3782 dl 1.52 fjp.invoke(ForkJoinTasks.forEachKey
3783     (ConcurrentHashMapV8.this, action));
3784     }
3785    
3786     /**
3787     * Performs the given action for each non-null transformation
3788 jsr166 1.56 * of each key.
3789 dl 1.52 *
3790     * @param transformer a function returning the transformation
3791 jsr166 1.68 * for an element, or null if there is no transformation (in
3792 jsr166 1.67 * which case the action is not applied)
3793 dl 1.52 * @param action the action
3794     */
3795 jsr166 1.53 public <U> void forEachKey(Fun<? super K, ? extends U> transformer,
3796 dl 1.52 Action<U> action) {
3797     fjp.invoke(ForkJoinTasks.forEachKey
3798     (ConcurrentHashMapV8.this, transformer, action));
3799     }
3800    
3801     /**
3802     * Returns a non-null result from applying the given search
3803 dl 1.59 * function on each key, or null if none. Upon success,
3804     * further element processing is suppressed and the results of
3805     * any other parallel invocations of the search function are
3806     * ignored.
3807 dl 1.52 *
3808     * @param searchFunction a function returning a non-null
3809     * result on success, else null
3810     * @return a non-null result from applying the given search
3811     * function on each key, or null if none
3812     */
3813     public <U> U searchKeys(Fun<? super K, ? extends U> searchFunction) {
3814     return fjp.invoke(ForkJoinTasks.searchKeys
3815     (ConcurrentHashMapV8.this, searchFunction));
3816     }
3817    
3818     /**
3819     * Returns the result of accumulating all keys using the given
3820     * reducer to combine values, or null if none.
3821     *
3822     * @param reducer a commutative associative combining function
3823     * @return the result of accumulating all keys using the given
3824     * reducer to combine values, or null if none
3825     */
3826     public K reduceKeys(BiFun<? super K, ? super K, ? extends K> reducer) {
3827     return fjp.invoke(ForkJoinTasks.reduceKeys
3828     (ConcurrentHashMapV8.this, reducer));
3829     }
3830    
3831     /**
3832     * Returns the result of accumulating the given transformation
3833     * of all keys using the given reducer to combine values, or
3834     * null if none.
3835     *
3836     * @param transformer a function returning the transformation
3837 jsr166 1.68 * for an element, or null if there is no transformation (in
3838 jsr166 1.67 * which case it is not combined)
3839 dl 1.52 * @param reducer a commutative associative combining function
3840     * @return the result of accumulating the given transformation
3841     * of all keys
3842     */
3843     public <U> U reduceKeys(Fun<? super K, ? extends U> transformer,
3844     BiFun<? super U, ? super U, ? extends U> reducer) {
3845     return fjp.invoke(ForkJoinTasks.reduceKeys
3846     (ConcurrentHashMapV8.this, transformer, reducer));
3847     }
3848    
3849     /**
3850     * Returns the result of accumulating the given transformation
3851     * of all keys using the given reducer to combine values, and
3852     * the given basis as an identity value.
3853     *
3854     * @param transformer a function returning the transformation
3855     * for an element
3856     * @param basis the identity (initial default value) for the reduction
3857     * @param reducer a commutative associative combining function
3858     * @return the result of accumulating the given transformation
3859     * of all keys
3860     */
3861     public double reduceKeysToDouble(ObjectToDouble<? super K> transformer,
3862     double basis,
3863     DoubleByDoubleToDouble reducer) {
3864     return fjp.invoke(ForkJoinTasks.reduceKeysToDouble
3865     (ConcurrentHashMapV8.this, transformer, basis, reducer));
3866     }
3867    
3868     /**
3869     * Returns the result of accumulating the given transformation
3870     * of all keys using the given reducer to combine values, and
3871     * the given basis as an identity value.
3872     *
3873     * @param transformer a function returning the transformation
3874     * for an element
3875     * @param basis the identity (initial default value) for the reduction
3876     * @param reducer a commutative associative combining function
3877     * @return the result of accumulating the given transformation
3878     * of all keys
3879     */
3880     public long reduceKeysToLong(ObjectToLong<? super K> transformer,
3881     long basis,
3882     LongByLongToLong reducer) {
3883     return fjp.invoke(ForkJoinTasks.reduceKeysToLong
3884     (ConcurrentHashMapV8.this, transformer, basis, reducer));
3885     }
3886    
3887     /**
3888     * Returns the result of accumulating the given transformation
3889     * of all keys using the given reducer to combine values, and
3890     * the given basis as an identity value.
3891     *
3892     * @param transformer a function returning the transformation
3893     * for an element
3894     * @param basis the identity (initial default value) for the reduction
3895     * @param reducer a commutative associative combining function
3896     * @return the result of accumulating the given transformation
3897     * of all keys
3898     */
3899     public int reduceKeysToInt(ObjectToInt<? super K> transformer,
3900     int basis,
3901     IntByIntToInt reducer) {
3902     return fjp.invoke(ForkJoinTasks.reduceKeysToInt
3903     (ConcurrentHashMapV8.this, transformer, basis, reducer));
3904     }
3905    
3906     /**
3907 jsr166 1.56 * Performs the given action for each value.
3908 dl 1.52 *
3909     * @param action the action
3910     */
3911 jsr166 1.53 public void forEachValue(Action<V> action) {
3912 dl 1.52 fjp.invoke(ForkJoinTasks.forEachValue
3913     (ConcurrentHashMapV8.this, action));
3914     }
3915    
3916     /**
3917     * Performs the given action for each non-null transformation
3918 jsr166 1.56 * of each value.
3919 dl 1.52 *
3920     * @param transformer a function returning the transformation
3921 jsr166 1.68 * for an element, or null if there is no transformation (in
3922 jsr166 1.67 * which case the action is not applied)
3923 dl 1.52 */
3924 jsr166 1.53 public <U> void forEachValue(Fun<? super V, ? extends U> transformer,
3925 dl 1.52 Action<U> action) {
3926     fjp.invoke(ForkJoinTasks.forEachValue
3927     (ConcurrentHashMapV8.this, transformer, action));
3928     }
3929    
3930     /**
3931     * Returns a non-null result from applying the given search
3932 dl 1.59 * function on each value, or null if none. Upon success,
3933     * further element processing is suppressed and the results of
3934     * any other parallel invocations of the search function are
3935     * ignored.
3936 dl 1.52 *
3937     * @param searchFunction a function returning a non-null
3938     * result on success, else null
3939     * @return a non-null result from applying the given search
3940     * function on each value, or null if none
3941     */
3942     public <U> U searchValues(Fun<? super V, ? extends U> searchFunction) {
3943     return fjp.invoke(ForkJoinTasks.searchValues
3944     (ConcurrentHashMapV8.this, searchFunction));
3945     }
3946    
3947     /**
3948     * Returns the result of accumulating all values using the
3949     * given reducer to combine values, or null if none.
3950     *
3951     * @param reducer a commutative associative combining function
3952     * @return the result of accumulating all values
3953     */
3954     public V reduceValues(BiFun<? super V, ? super V, ? extends V> reducer) {
3955     return fjp.invoke(ForkJoinTasks.reduceValues
3956     (ConcurrentHashMapV8.this, reducer));
3957     }
3958    
3959     /**
3960     * Returns the result of accumulating the given transformation
3961     * of all values using the given reducer to combine values, or
3962     * null if none.
3963     *
3964     * @param transformer a function returning the transformation
3965 jsr166 1.68 * for an element, or null if there is no transformation (in
3966 jsr166 1.67 * which case it is not combined)
3967 dl 1.52 * @param reducer a commutative associative combining function
3968     * @return the result of accumulating the given transformation
3969     * of all values
3970     */
3971     public <U> U reduceValues(Fun<? super V, ? extends U> transformer,
3972     BiFun<? super U, ? super U, ? extends U> reducer) {
3973     return fjp.invoke(ForkJoinTasks.reduceValues
3974     (ConcurrentHashMapV8.this, transformer, reducer));
3975     }
3976    
3977     /**
3978     * Returns the result of accumulating the given transformation
3979     * of all values using the given reducer to combine values,
3980     * and the given basis as an identity value.
3981     *
3982     * @param transformer a function returning the transformation
3983     * for an element
3984     * @param basis the identity (initial default value) for the reduction
3985     * @param reducer a commutative associative combining function
3986     * @return the result of accumulating the given transformation
3987     * of all values
3988     */
3989     public double reduceValuesToDouble(ObjectToDouble<? super V> transformer,
3990     double basis,
3991     DoubleByDoubleToDouble reducer) {
3992     return fjp.invoke(ForkJoinTasks.reduceValuesToDouble
3993     (ConcurrentHashMapV8.this, transformer, basis, reducer));
3994     }
3995    
3996     /**
3997     * Returns the result of accumulating the given transformation
3998     * of all values using the given reducer to combine values,
3999     * and the given basis as an identity value.
4000     *
4001     * @param transformer a function returning the transformation
4002     * for an element
4003     * @param basis the identity (initial default value) for the reduction
4004     * @param reducer a commutative associative combining function
4005     * @return the result of accumulating the given transformation
4006     * of all values
4007     */
4008     public long reduceValuesToLong(ObjectToLong<? super V> transformer,
4009     long basis,
4010     LongByLongToLong reducer) {
4011     return fjp.invoke(ForkJoinTasks.reduceValuesToLong
4012     (ConcurrentHashMapV8.this, transformer, basis, reducer));
4013     }
4014    
4015     /**
4016     * Returns the result of accumulating the given transformation
4017     * of all values using the given reducer to combine values,
4018     * and the given basis as an identity value.
4019     *
4020     * @param transformer a function returning the transformation
4021     * for an element
4022     * @param basis the identity (initial default value) for the reduction
4023     * @param reducer a commutative associative combining function
4024     * @return the result of accumulating the given transformation
4025     * of all values
4026     */
4027     public int reduceValuesToInt(ObjectToInt<? super V> transformer,
4028     int basis,
4029     IntByIntToInt reducer) {
4030     return fjp.invoke(ForkJoinTasks.reduceValuesToInt
4031     (ConcurrentHashMapV8.this, transformer, basis, reducer));
4032     }
4033    
4034     /**
4035 jsr166 1.56 * Performs the given action for each entry.
4036 dl 1.52 *
4037     * @param action the action
4038     */
4039 jsr166 1.53 public void forEachEntry(Action<Map.Entry<K,V>> action) {
4040 dl 1.52 fjp.invoke(ForkJoinTasks.forEachEntry
4041     (ConcurrentHashMapV8.this, action));
4042     }
4043    
4044     /**
4045 jsr166 1.56 * Performs the given action for each non-null transformation
4046     * of each entry.
4047 dl 1.52 *
4048     * @param transformer a function returning the transformation
4049 jsr166 1.68 * for an element, or null if there is no transformation (in
4050 jsr166 1.67 * which case the action is not applied)
4051 dl 1.52 * @param action the action
4052     */
4053 jsr166 1.53 public <U> void forEachEntry(Fun<Map.Entry<K,V>, ? extends U> transformer,
4054 dl 1.52 Action<U> action) {
4055     fjp.invoke(ForkJoinTasks.forEachEntry
4056     (ConcurrentHashMapV8.this, transformer, action));
4057     }
4058    
4059     /**
4060     * Returns a non-null result from applying the given search
4061 dl 1.59 * function on each entry, or null if none. Upon success,
4062     * further element processing is suppressed and the results of
4063     * any other parallel invocations of the search function are
4064     * ignored.
4065 dl 1.52 *
4066     * @param searchFunction a function returning a non-null
4067     * result on success, else null
4068     * @return a non-null result from applying the given search
4069     * function on each entry, or null if none
4070     */
4071     public <U> U searchEntries(Fun<Map.Entry<K,V>, ? extends U> searchFunction) {
4072     return fjp.invoke(ForkJoinTasks.searchEntries
4073     (ConcurrentHashMapV8.this, searchFunction));
4074     }
4075    
4076     /**
4077     * Returns the result of accumulating all entries using the
4078     * given reducer to combine values, or null if none.
4079     *
4080     * @param reducer a commutative associative combining function
4081     * @return the result of accumulating all entries
4082     */
4083     public Map.Entry<K,V> reduceEntries(BiFun<Map.Entry<K,V>, Map.Entry<K,V>, ? extends Map.Entry<K,V>> reducer) {
4084     return fjp.invoke(ForkJoinTasks.reduceEntries
4085     (ConcurrentHashMapV8.this, reducer));
4086     }
4087    
4088     /**
4089     * Returns the result of accumulating the given transformation
4090     * of all entries using the given reducer to combine values,
4091     * or null if none.
4092     *
4093     * @param transformer a function returning the transformation
4094 jsr166 1.68 * for an element, or null if there is no transformation (in
4095 dl 1.52 * which case it is not combined).
4096     * @param reducer a commutative associative combining function
4097     * @return the result of accumulating the given transformation
4098     * of all entries
4099     */
4100     public <U> U reduceEntries(Fun<Map.Entry<K,V>, ? extends U> transformer,
4101     BiFun<? super U, ? super U, ? extends U> reducer) {
4102     return fjp.invoke(ForkJoinTasks.reduceEntries
4103     (ConcurrentHashMapV8.this, transformer, reducer));
4104     }
4105    
4106     /**
4107     * Returns the result of accumulating the given transformation
4108     * of all entries using the given reducer to combine values,
4109     * and the given basis as an identity value.
4110     *
4111     * @param transformer a function returning the transformation
4112     * for an element
4113     * @param basis the identity (initial default value) for the reduction
4114     * @param reducer a commutative associative combining function
4115     * @return the result of accumulating the given transformation
4116     * of all entries
4117     */
4118     public double reduceEntriesToDouble(ObjectToDouble<Map.Entry<K,V>> transformer,
4119     double basis,
4120     DoubleByDoubleToDouble reducer) {
4121     return fjp.invoke(ForkJoinTasks.reduceEntriesToDouble
4122     (ConcurrentHashMapV8.this, transformer, basis, reducer));
4123     }
4124    
4125     /**
4126     * Returns the result of accumulating the given transformation
4127     * of all entries using the given reducer to combine values,
4128     * and the given basis as an identity value.
4129     *
4130     * @param transformer a function returning the transformation
4131     * for an element
4132     * @param basis the identity (initial default value) for the reduction
4133     * @param reducer a commutative associative combining function
4134     * @return the result of accumulating the given transformation
4135     * of all entries
4136     */
4137     public long reduceEntriesToLong(ObjectToLong<Map.Entry<K,V>> transformer,
4138     long basis,
4139     LongByLongToLong reducer) {
4140     return fjp.invoke(ForkJoinTasks.reduceEntriesToLong
4141     (ConcurrentHashMapV8.this, transformer, basis, reducer));
4142     }
4143    
4144     /**
4145     * Returns the result of accumulating the given transformation
4146     * of all entries using the given reducer to combine values,
4147     * and the given basis as an identity value.
4148     *
4149     * @param transformer a function returning the transformation
4150     * for an element
4151     * @param basis the identity (initial default value) for the reduction
4152     * @param reducer a commutative associative combining function
4153     * @return the result of accumulating the given transformation
4154     * of all entries
4155     */
4156     public int reduceEntriesToInt(ObjectToInt<Map.Entry<K,V>> transformer,
4157     int basis,
4158     IntByIntToInt reducer) {
4159     return fjp.invoke(ForkJoinTasks.reduceEntriesToInt
4160     (ConcurrentHashMapV8.this, transformer, basis, reducer));
4161     }
4162     }
4163    
4164     // ---------------------------------------------------------------------
4165    
4166     /**
4167     * Predefined tasks for performing bulk parallel operations on
4168     * ConcurrentHashMaps. These tasks follow the forms and rules used
4169     * in class {@link Parallel}. Each method has the same name, but
4170     * returns a task rather than invoking it. These methods may be
4171     * useful in custom applications such as submitting a task without
4172     * waiting for completion, or combining with other tasks.
4173     */
4174     public static class ForkJoinTasks {
4175     private ForkJoinTasks() {}
4176    
4177     /**
4178     * Returns a task that when invoked, performs the given
4179     * action for each (key, value)
4180     *
4181     * @param map the map
4182     * @param action the action
4183     * @return the task
4184     */
4185 jsr166 1.53 public static <K,V> ForkJoinTask<Void> forEach
4186 dl 1.52 (ConcurrentHashMapV8<K,V> map,
4187     BiAction<K,V> action) {
4188     if (action == null) throw new NullPointerException();
4189 dl 1.63 return new ForEachMappingTask<K,V>(map, null, -1, action);
4190 dl 1.52 }
4191    
4192     /**
4193     * Returns a task that when invoked, performs the given
4194     * action for each non-null transformation of each (key, value)
4195     *
4196     * @param map the map
4197     * @param transformer a function returning the transformation
4198 jsr166 1.68 * for an element, or null if there is no transformation (in
4199 jsr166 1.67 * which case the action is not applied)
4200 dl 1.52 * @param action the action
4201     * @return the task
4202     */
4203 jsr166 1.53 public static <K,V,U> ForkJoinTask<Void> forEach
4204 dl 1.52 (ConcurrentHashMapV8<K,V> map,
4205     BiFun<? super K, ? super V, ? extends U> transformer,
4206     Action<U> action) {
4207     if (transformer == null || action == null)
4208     throw new NullPointerException();
4209     return new ForEachTransformedMappingTask<K,V,U>
4210 dl 1.63 (map, null, -1, transformer, action);
4211 dl 1.52 }
4212    
4213     /**
4214 dl 1.59 * Returns a task that when invoked, returns a non-null result
4215     * from applying the given search function on each (key,
4216     * value), or null if none. Upon success, further element
4217     * processing is suppressed and the results of any other
4218     * parallel invocations of the search function are ignored.
4219 dl 1.52 *
4220     * @param map the map
4221     * @param searchFunction a function returning a non-null
4222     * result on success, else null
4223     * @return the task
4224     */
4225     public static <K,V,U> ForkJoinTask<U> search
4226     (ConcurrentHashMapV8<K,V> map,
4227     BiFun<? super K, ? super V, ? extends U> searchFunction) {
4228     if (searchFunction == null) throw new NullPointerException();
4229     return new SearchMappingsTask<K,V,U>
4230 dl 1.63 (map, null, -1, searchFunction,
4231 dl 1.52 new AtomicReference<U>());
4232     }
4233    
4234     /**
4235     * Returns a task that when invoked, returns the result of
4236     * accumulating the given transformation of all (key, value) pairs
4237     * using the given reducer to combine values, or null if none.
4238     *
4239     * @param map the map
4240     * @param transformer a function returning the transformation
4241 jsr166 1.68 * for an element, or null if there is no transformation (in
4242 dl 1.52 * which case it is not combined).
4243     * @param reducer a commutative associative combining function
4244     * @return the task
4245     */
4246     public static <K,V,U> ForkJoinTask<U> reduce
4247     (ConcurrentHashMapV8<K,V> map,
4248     BiFun<? super K, ? super V, ? extends U> transformer,
4249     BiFun<? super U, ? super U, ? extends U> reducer) {
4250     if (transformer == null || reducer == null)
4251     throw new NullPointerException();
4252     return new MapReduceMappingsTask<K,V,U>
4253 dl 1.63 (map, null, -1, null, transformer, reducer);
4254 dl 1.52 }
4255    
4256     /**
4257     * Returns a task that when invoked, returns the result of
4258     * accumulating the given transformation of all (key, value) pairs
4259     * using the given reducer to combine values, and the given
4260     * basis as an identity value.
4261     *
4262     * @param map the map
4263     * @param transformer a function returning the transformation
4264     * for an element
4265     * @param basis the identity (initial default value) for the reduction
4266     * @param reducer a commutative associative combining function
4267     * @return the task
4268     */
4269     public static <K,V> ForkJoinTask<Double> reduceToDouble
4270     (ConcurrentHashMapV8<K,V> map,
4271     ObjectByObjectToDouble<? super K, ? super V> transformer,
4272     double basis,
4273     DoubleByDoubleToDouble reducer) {
4274     if (transformer == null || reducer == null)
4275     throw new NullPointerException();
4276     return new MapReduceMappingsToDoubleTask<K,V>
4277 dl 1.63 (map, null, -1, null, transformer, basis, reducer);
4278 dl 1.52 }
4279    
4280     /**
4281     * Returns a task that when invoked, returns the result of
4282     * accumulating the given transformation of all (key, value) pairs
4283     * using the given reducer to combine values, and the given
4284     * basis as an identity value.
4285     *
4286     * @param map the map
4287     * @param transformer a function returning the transformation
4288     * for an element
4289     * @param basis the identity (initial default value) for the reduction
4290     * @param reducer a commutative associative combining function
4291     * @return the task
4292     */
4293     public static <K,V> ForkJoinTask<Long> reduceToLong
4294     (ConcurrentHashMapV8<K,V> map,
4295     ObjectByObjectToLong<? super K, ? super V> transformer,
4296     long basis,
4297     LongByLongToLong reducer) {
4298     if (transformer == null || reducer == null)
4299     throw new NullPointerException();
4300     return new MapReduceMappingsToLongTask<K,V>
4301 dl 1.63 (map, null, -1, null, transformer, basis, reducer);
4302 dl 1.52 }
4303    
4304     /**
4305     * Returns a task that when invoked, returns the result of
4306     * accumulating the given transformation of all (key, value) pairs
4307     * using the given reducer to combine values, and the given
4308     * basis as an identity value.
4309     *
4310     * @param transformer a function returning the transformation
4311     * for an element
4312     * @param basis the identity (initial default value) for the reduction
4313     * @param reducer a commutative associative combining function
4314     * @return the task
4315     */
4316     public static <K,V> ForkJoinTask<Integer> reduceToInt
4317     (ConcurrentHashMapV8<K,V> map,
4318     ObjectByObjectToInt<? super K, ? super V> transformer,
4319     int basis,
4320     IntByIntToInt reducer) {
4321     if (transformer == null || reducer == null)
4322     throw new NullPointerException();
4323     return new MapReduceMappingsToIntTask<K,V>
4324 dl 1.63 (map, null, -1, null, transformer, basis, reducer);
4325 dl 1.52 }
4326    
4327     /**
4328     * Returns a task that when invoked, performs the given action
4329 jsr166 1.56 * for each key.
4330 dl 1.52 *
4331     * @param map the map
4332     * @param action the action
4333     * @return the task
4334     */
4335 jsr166 1.53 public static <K,V> ForkJoinTask<Void> forEachKey
4336 dl 1.52 (ConcurrentHashMapV8<K,V> map,
4337     Action<K> action) {
4338     if (action == null) throw new NullPointerException();
4339 dl 1.63 return new ForEachKeyTask<K,V>(map, null, -1, action);
4340 dl 1.52 }
4341    
4342     /**
4343     * Returns a task that when invoked, performs the given action
4344 jsr166 1.56 * for each non-null transformation of each key.
4345 dl 1.52 *
4346     * @param map the map
4347     * @param transformer a function returning the transformation
4348 jsr166 1.68 * for an element, or null if there is no transformation (in
4349 jsr166 1.67 * which case the action is not applied)
4350 dl 1.52 * @param action the action
4351     * @return the task
4352     */
4353 jsr166 1.53 public static <K,V,U> ForkJoinTask<Void> forEachKey
4354 dl 1.52 (ConcurrentHashMapV8<K,V> map,
4355     Fun<? super K, ? extends U> transformer,
4356     Action<U> action) {
4357     if (transformer == null || action == null)
4358     throw new NullPointerException();
4359     return new ForEachTransformedKeyTask<K,V,U>
4360 dl 1.63 (map, null, -1, transformer, action);
4361 dl 1.52 }
4362    
4363     /**
4364     * Returns a task that when invoked, returns a non-null result
4365     * from applying the given search function on each key, or
4366 dl 1.59 * null if none. Upon success, further element processing is
4367     * suppressed and the results of any other parallel
4368     * invocations of the search function are ignored.
4369 dl 1.52 *
4370     * @param map the map
4371     * @param searchFunction a function returning a non-null
4372     * result on success, else null
4373     * @return the task
4374     */
4375     public static <K,V,U> ForkJoinTask<U> searchKeys
4376     (ConcurrentHashMapV8<K,V> map,
4377     Fun<? super K, ? extends U> searchFunction) {
4378     if (searchFunction == null) throw new NullPointerException();
4379     return new SearchKeysTask<K,V,U>
4380 dl 1.63 (map, null, -1, searchFunction,
4381 dl 1.52 new AtomicReference<U>());
4382     }
4383    
4384     /**
4385     * Returns a task that when invoked, returns the result of
4386     * accumulating all keys using the given reducer to combine
4387     * values, or null if none.
4388     *
4389     * @param map the map
4390     * @param reducer a commutative associative combining function
4391     * @return the task
4392     */
4393     public static <K,V> ForkJoinTask<K> reduceKeys
4394     (ConcurrentHashMapV8<K,V> map,
4395     BiFun<? super K, ? super K, ? extends K> reducer) {
4396     if (reducer == null) throw new NullPointerException();
4397     return new ReduceKeysTask<K,V>
4398 dl 1.63 (map, null, -1, null, reducer);
4399 dl 1.52 }
4400 jsr166 1.58
4401 dl 1.52 /**
4402     * Returns a task that when invoked, returns the result of
4403     * accumulating the given transformation of all keys using the given
4404     * reducer to combine values, or null if none.
4405     *
4406     * @param map the map
4407     * @param transformer a function returning the transformation
4408 jsr166 1.68 * for an element, or null if there is no transformation (in
4409 dl 1.52 * which case it is not combined).
4410     * @param reducer a commutative associative combining function
4411     * @return the task
4412     */
4413     public static <K,V,U> ForkJoinTask<U> reduceKeys
4414     (ConcurrentHashMapV8<K,V> map,
4415     Fun<? super K, ? extends U> transformer,
4416     BiFun<? super U, ? super U, ? extends U> reducer) {
4417     if (transformer == null || reducer == null)
4418     throw new NullPointerException();
4419     return new MapReduceKeysTask<K,V,U>
4420 dl 1.63 (map, null, -1, null, transformer, reducer);
4421 dl 1.52 }
4422    
4423     /**
4424     * Returns a task that when invoked, returns the result of
4425     * accumulating the given transformation of all keys using the given
4426     * reducer to combine values, and the given basis as an
4427     * identity value.
4428     *
4429     * @param map the map
4430     * @param transformer a function returning the transformation
4431     * for an element
4432     * @param basis the identity (initial default value) for the reduction
4433     * @param reducer a commutative associative combining function
4434     * @return the task
4435     */
4436     public static <K,V> ForkJoinTask<Double> reduceKeysToDouble
4437     (ConcurrentHashMapV8<K,V> map,
4438     ObjectToDouble<? super K> transformer,
4439     double basis,
4440     DoubleByDoubleToDouble reducer) {
4441     if (transformer == null || reducer == null)
4442     throw new NullPointerException();
4443     return new MapReduceKeysToDoubleTask<K,V>
4444 dl 1.63 (map, null, -1, null, transformer, basis, reducer);
4445 dl 1.52 }
4446    
4447     /**
4448     * Returns a task that when invoked, returns the result of
4449     * accumulating the given transformation of all keys using the given
4450     * reducer to combine values, and the given basis as an
4451     * identity value.
4452     *
4453     * @param map the map
4454     * @param transformer a function returning the transformation
4455     * for an element
4456     * @param basis the identity (initial default value) for the reduction
4457     * @param reducer a commutative associative combining function
4458     * @return the task
4459     */
4460     public static <K,V> ForkJoinTask<Long> reduceKeysToLong
4461     (ConcurrentHashMapV8<K,V> map,
4462     ObjectToLong<? super K> transformer,
4463     long basis,
4464     LongByLongToLong reducer) {
4465     if (transformer == null || reducer == null)
4466     throw new NullPointerException();
4467     return new MapReduceKeysToLongTask<K,V>
4468 dl 1.63 (map, null, -1, null, transformer, basis, reducer);
4469 dl 1.52 }
4470    
4471     /**
4472     * Returns a task that when invoked, returns the result of
4473     * accumulating the given transformation of all keys using the given
4474     * reducer to combine values, and the given basis as an
4475     * identity value.
4476     *
4477     * @param map the map
4478     * @param transformer a function returning the transformation
4479     * for an element
4480     * @param basis the identity (initial default value) for the reduction
4481     * @param reducer a commutative associative combining function
4482     * @return the task
4483     */
4484     public static <K,V> ForkJoinTask<Integer> reduceKeysToInt
4485     (ConcurrentHashMapV8<K,V> map,
4486     ObjectToInt<? super K> transformer,
4487     int basis,
4488     IntByIntToInt reducer) {
4489     if (transformer == null || reducer == null)
4490     throw new NullPointerException();
4491     return new MapReduceKeysToIntTask<K,V>
4492 dl 1.63 (map, null, -1, null, transformer, basis, reducer);
4493 dl 1.52 }
4494    
4495     /**
4496     * Returns a task that when invoked, performs the given action
4497 jsr166 1.56 * for each value.
4498 dl 1.52 *
4499     * @param map the map
4500     * @param action the action
4501     */
4502 jsr166 1.53 public static <K,V> ForkJoinTask<Void> forEachValue
4503 dl 1.52 (ConcurrentHashMapV8<K,V> map,
4504     Action<V> action) {
4505     if (action == null) throw new NullPointerException();
4506 dl 1.63 return new ForEachValueTask<K,V>(map, null, -1, action);
4507 dl 1.52 }
4508    
4509     /**
4510     * Returns a task that when invoked, performs the given action
4511 jsr166 1.56 * for each non-null transformation of each value.
4512 dl 1.52 *
4513     * @param map the map
4514     * @param transformer a function returning the transformation
4515 jsr166 1.68 * for an element, or null if there is no transformation (in
4516 jsr166 1.67 * which case the action is not applied)
4517 dl 1.52 * @param action the action
4518     */
4519 jsr166 1.53 public static <K,V,U> ForkJoinTask<Void> forEachValue
4520 dl 1.52 (ConcurrentHashMapV8<K,V> map,
4521     Fun<? super V, ? extends U> transformer,
4522     Action<U> action) {
4523     if (transformer == null || action == null)
4524     throw new NullPointerException();
4525     return new ForEachTransformedValueTask<K,V,U>
4526 dl 1.63 (map, null, -1, transformer, action);
4527 dl 1.52 }
4528    
4529     /**
4530     * Returns a task that when invoked, returns a non-null result
4531     * from applying the given search function on each value, or
4532 dl 1.59 * null if none. Upon success, further element processing is
4533     * suppressed and the results of any other parallel
4534     * invocations of the search function are ignored.
4535 dl 1.52 *
4536     * @param map the map
4537     * @param searchFunction a function returning a non-null
4538     * result on success, else null
4539     * @return the task
4540     */
4541     public static <K,V,U> ForkJoinTask<U> searchValues
4542     (ConcurrentHashMapV8<K,V> map,
4543     Fun<? super V, ? extends U> searchFunction) {
4544     if (searchFunction == null) throw new NullPointerException();
4545     return new SearchValuesTask<K,V,U>
4546 dl 1.63 (map, null, -1, searchFunction,
4547 dl 1.52 new AtomicReference<U>());
4548     }
4549    
4550     /**
4551     * Returns a task that when invoked, returns the result of
4552     * accumulating all values using the given reducer to combine
4553     * values, or null if none.
4554     *
4555     * @param map the map
4556     * @param reducer a commutative associative combining function
4557     * @return the task
4558     */
4559     public static <K,V> ForkJoinTask<V> reduceValues
4560     (ConcurrentHashMapV8<K,V> map,
4561     BiFun<? super V, ? super V, ? extends V> reducer) {
4562     if (reducer == null) throw new NullPointerException();
4563     return new ReduceValuesTask<K,V>
4564 dl 1.63 (map, null, -1, null, reducer);
4565 dl 1.52 }
4566    
4567     /**
4568     * Returns a task that when invoked, returns the result of
4569     * accumulating the given transformation of all values using the
4570     * given reducer to combine values, or null if none.
4571     *
4572     * @param map the map
4573     * @param transformer a function returning the transformation
4574 jsr166 1.68 * for an element, or null if there is no transformation (in
4575 dl 1.52 * which case it is not combined).
4576     * @param reducer a commutative associative combining function
4577     * @return the task
4578     */
4579     public static <K,V,U> ForkJoinTask<U> reduceValues
4580     (ConcurrentHashMapV8<K,V> map,
4581     Fun<? super V, ? extends U> transformer,
4582     BiFun<? super U, ? super U, ? extends U> reducer) {
4583     if (transformer == null || reducer == null)
4584     throw new NullPointerException();
4585     return new MapReduceValuesTask<K,V,U>
4586 dl 1.63 (map, null, -1, null, transformer, reducer);
4587 dl 1.52 }
4588    
4589     /**
4590     * Returns a task that when invoked, returns the result of
4591     * accumulating the given transformation of all values using the
4592     * given reducer to combine values, and the given basis as an
4593     * identity value.
4594     *
4595     * @param map the map
4596     * @param transformer a function returning the transformation
4597     * for an element
4598     * @param basis the identity (initial default value) for the reduction
4599     * @param reducer a commutative associative combining function
4600     * @return the task
4601     */
4602     public static <K,V> ForkJoinTask<Double> reduceValuesToDouble
4603     (ConcurrentHashMapV8<K,V> map,
4604     ObjectToDouble<? super V> transformer,
4605     double basis,
4606     DoubleByDoubleToDouble reducer) {
4607     if (transformer == null || reducer == null)
4608     throw new NullPointerException();
4609     return new MapReduceValuesToDoubleTask<K,V>
4610 dl 1.63 (map, null, -1, null, transformer, basis, reducer);
4611 dl 1.52 }
4612    
4613     /**
4614     * Returns a task that when invoked, returns the result of
4615     * accumulating the given transformation of all values using the
4616     * given reducer to combine values, and the given basis as an
4617     * identity value.
4618     *
4619     * @param map the map
4620     * @param transformer a function returning the transformation
4621     * for an element
4622     * @param basis the identity (initial default value) for the reduction
4623     * @param reducer a commutative associative combining function
4624     * @return the task
4625     */
4626     public static <K,V> ForkJoinTask<Long> reduceValuesToLong
4627     (ConcurrentHashMapV8<K,V> map,
4628     ObjectToLong<? super V> transformer,
4629     long basis,
4630     LongByLongToLong reducer) {
4631     if (transformer == null || reducer == null)
4632     throw new NullPointerException();
4633     return new MapReduceValuesToLongTask<K,V>
4634 dl 1.63 (map, null, -1, null, transformer, basis, reducer);
4635 dl 1.52 }
4636    
4637     /**
4638     * Returns a task that when invoked, returns the result of
4639     * accumulating the given transformation of all values using the
4640     * given reducer to combine values, and the given basis as an
4641     * identity value.
4642     *
4643     * @param map the map
4644     * @param transformer a function returning the transformation
4645     * for an element
4646     * @param basis the identity (initial default value) for the reduction
4647     * @param reducer a commutative associative combining function
4648     * @return the task
4649     */
4650     public static <K,V> ForkJoinTask<Integer> reduceValuesToInt
4651     (ConcurrentHashMapV8<K,V> map,
4652     ObjectToInt<? super V> transformer,
4653     int basis,
4654     IntByIntToInt reducer) {
4655     if (transformer == null || reducer == null)
4656     throw new NullPointerException();
4657     return new MapReduceValuesToIntTask<K,V>
4658 dl 1.63 (map, null, -1, null, transformer, basis, reducer);
4659 dl 1.52 }
4660    
4661     /**
4662     * Returns a task that when invoked, perform the given action
4663 jsr166 1.56 * for each entry.
4664 dl 1.52 *
4665     * @param map the map
4666     * @param action the action
4667     */
4668 jsr166 1.53 public static <K,V> ForkJoinTask<Void> forEachEntry
4669 dl 1.52 (ConcurrentHashMapV8<K,V> map,
4670     Action<Map.Entry<K,V>> action) {
4671     if (action == null) throw new NullPointerException();
4672 dl 1.63 return new ForEachEntryTask<K,V>(map, null, -1, action);
4673 dl 1.52 }
4674    
4675     /**
4676     * Returns a task that when invoked, perform the given action
4677 jsr166 1.56 * for each non-null transformation of each entry.
4678 dl 1.52 *
4679     * @param map the map
4680     * @param transformer a function returning the transformation
4681 jsr166 1.68 * for an element, or null if there is no transformation (in
4682 jsr166 1.67 * which case the action is not applied)
4683 dl 1.52 * @param action the action
4684     */
4685 jsr166 1.53 public static <K,V,U> ForkJoinTask<Void> forEachEntry
4686 dl 1.52 (ConcurrentHashMapV8<K,V> map,
4687     Fun<Map.Entry<K,V>, ? extends U> transformer,
4688     Action<U> action) {
4689     if (transformer == null || action == null)
4690     throw new NullPointerException();
4691     return new ForEachTransformedEntryTask<K,V,U>
4692 dl 1.63 (map, null, -1, transformer, action);
4693 dl 1.52 }
4694    
4695     /**
4696     * Returns a task that when invoked, returns a non-null result
4697     * from applying the given search function on each entry, or
4698 dl 1.59 * null if none. Upon success, further element processing is
4699     * suppressed and the results of any other parallel
4700     * invocations of the search function are ignored.
4701 dl 1.52 *
4702     * @param map the map
4703     * @param searchFunction a function returning a non-null
4704     * result on success, else null
4705     * @return the task
4706     */
4707     public static <K,V,U> ForkJoinTask<U> searchEntries
4708     (ConcurrentHashMapV8<K,V> map,
4709     Fun<Map.Entry<K,V>, ? extends U> searchFunction) {
4710     if (searchFunction == null) throw new NullPointerException();
4711     return new SearchEntriesTask<K,V,U>
4712 dl 1.63 (map, null, -1, searchFunction,
4713 dl 1.52 new AtomicReference<U>());
4714     }
4715    
4716     /**
4717     * Returns a task that when invoked, returns the result of
4718     * accumulating all entries using the given reducer to combine
4719     * values, or null if none.
4720     *
4721     * @param map the map
4722     * @param reducer a commutative associative combining function
4723     * @return the task
4724     */
4725     public static <K,V> ForkJoinTask<Map.Entry<K,V>> reduceEntries
4726     (ConcurrentHashMapV8<K,V> map,
4727     BiFun<Map.Entry<K,V>, Map.Entry<K,V>, ? extends Map.Entry<K,V>> reducer) {
4728     if (reducer == null) throw new NullPointerException();
4729     return new ReduceEntriesTask<K,V>
4730 dl 1.63 (map, null, -1, null, reducer);
4731 dl 1.52 }
4732    
4733     /**
4734     * Returns a task that when invoked, returns the result of
4735     * accumulating the given transformation of all entries using the
4736     * given reducer to combine values, or null if none.
4737     *
4738     * @param map the map
4739     * @param transformer a function returning the transformation
4740 jsr166 1.68 * for an element, or null if there is no transformation (in
4741 dl 1.52 * which case it is not combined).
4742     * @param reducer a commutative associative combining function
4743     * @return the task
4744     */
4745     public static <K,V,U> ForkJoinTask<U> reduceEntries
4746     (ConcurrentHashMapV8<K,V> map,
4747     Fun<Map.Entry<K,V>, ? extends U> transformer,
4748     BiFun<? super U, ? super U, ? extends U> reducer) {
4749     if (transformer == null || reducer == null)
4750     throw new NullPointerException();
4751     return new MapReduceEntriesTask<K,V,U>
4752 dl 1.63 (map, null, -1, null, transformer, reducer);
4753 dl 1.52 }
4754    
4755     /**
4756     * Returns a task that when invoked, returns the result of
4757     * accumulating the given transformation of all entries using the
4758     * given reducer to combine values, and the given basis as an
4759     * identity value.
4760     *
4761     * @param map the map
4762     * @param transformer a function returning the transformation
4763     * for an element
4764     * @param basis the identity (initial default value) for the reduction
4765     * @param reducer a commutative associative combining function
4766     * @return the task
4767     */
4768     public static <K,V> ForkJoinTask<Double> reduceEntriesToDouble
4769     (ConcurrentHashMapV8<K,V> map,
4770     ObjectToDouble<Map.Entry<K,V>> transformer,
4771     double basis,
4772     DoubleByDoubleToDouble reducer) {
4773     if (transformer == null || reducer == null)
4774     throw new NullPointerException();
4775     return new MapReduceEntriesToDoubleTask<K,V>
4776 dl 1.63 (map, null, -1, null, transformer, basis, reducer);
4777 dl 1.52 }
4778    
4779     /**
4780     * Returns a task that when invoked, returns the result of
4781     * accumulating the given transformation of all entries using the
4782     * given reducer to combine values, and the given basis as an
4783     * identity value.
4784     *
4785     * @param map the map
4786     * @param transformer a function returning the transformation
4787     * for an element
4788     * @param basis the identity (initial default value) for the reduction
4789     * @param reducer a commutative associative combining function
4790     * @return the task
4791     */
4792     public static <K,V> ForkJoinTask<Long> reduceEntriesToLong
4793     (ConcurrentHashMapV8<K,V> map,
4794     ObjectToLong<Map.Entry<K,V>> transformer,
4795     long basis,
4796     LongByLongToLong reducer) {
4797     if (transformer == null || reducer == null)
4798     throw new NullPointerException();
4799     return new MapReduceEntriesToLongTask<K,V>
4800 dl 1.63 (map, null, -1, null, transformer, basis, reducer);
4801 dl 1.52 }
4802    
4803     /**
4804     * Returns a task that when invoked, returns the result of
4805     * accumulating the given transformation of all entries using the
4806     * given reducer to combine values, and the given basis as an
4807     * identity value.
4808     *
4809     * @param map the map
4810     * @param transformer a function returning the transformation
4811     * for an element
4812     * @param basis the identity (initial default value) for the reduction
4813     * @param reducer a commutative associative combining function
4814     * @return the task
4815     */
4816     public static <K,V> ForkJoinTask<Integer> reduceEntriesToInt
4817     (ConcurrentHashMapV8<K,V> map,
4818     ObjectToInt<Map.Entry<K,V>> transformer,
4819     int basis,
4820     IntByIntToInt reducer) {
4821     if (transformer == null || reducer == null)
4822     throw new NullPointerException();
4823     return new MapReduceEntriesToIntTask<K,V>
4824 dl 1.63 (map, null, -1, null, transformer, basis, reducer);
4825 dl 1.52 }
4826     }
4827    
4828     // -------------------------------------------------------
4829    
4830     /**
4831     * Base for FJ tasks for bulk operations. This adds a variant of
4832 jsr166 1.55 * CountedCompleters and some split and merge bookkeeping to
4833 dl 1.52 * iterator functionality. The forEach and reduce methods are
4834     * similar to those illustrated in CountedCompleter documentation,
4835     * except that bottom-up reduction completions perform them within
4836     * their compute methods. The search methods are like forEach
4837     * except they continually poll for success and exit early. Also,
4838     * exceptions are handled in a simpler manner, by just trying to
4839     * complete root task exceptionally.
4840     */
4841 dl 1.61 @SuppressWarnings("serial") static abstract class BulkTask<K,V,R> extends Traverser<K,V,R> {
4842 dl 1.52 final BulkTask<K,V,?> parent; // completion target
4843 dl 1.63 int batch; // split control; -1 for unknown
4844 dl 1.52 int pending; // completion control
4845    
4846 jsr166 1.64 BulkTask(ConcurrentHashMapV8<K,V> map, BulkTask<K,V,?> parent,
4847 dl 1.63 int batch) {
4848 dl 1.52 super(map);
4849     this.parent = parent;
4850     this.batch = batch;
4851 dl 1.63 if (parent != null && map != null) { // split parent
4852     Node[] t;
4853     if ((t = parent.tab) == null &&
4854     (t = parent.tab = map.table) != null)
4855     parent.baseLimit = parent.baseSize = t.length;
4856     this.tab = t;
4857     this.baseSize = parent.baseSize;
4858     int hi = this.baseLimit = parent.baseLimit;
4859     parent.baseLimit = this.index = this.baseIndex =
4860     (hi + parent.baseIndex + 1) >>> 1;
4861     }
4862 dl 1.52 }
4863    
4864     // FJ methods
4865    
4866     /**
4867 jsr166 1.56 * Propagates completion. Note that all reduce actions
4868 dl 1.52 * bypass this method to combine while completing.
4869     */
4870     final void tryComplete() {
4871     BulkTask<K,V,?> a = this, s = a;
4872     for (int c;;) {
4873     if ((c = a.pending) == 0) {
4874     if ((a = (s = a).parent) == null) {
4875     s.quietlyComplete();
4876     break;
4877     }
4878     }
4879     else if (U.compareAndSwapInt(a, PENDING, c, c - 1))
4880     break;
4881     }
4882     }
4883    
4884     /**
4885 dl 1.61 * Forces root task to complete.
4886     * @param ex if null, complete normally, else exceptionally
4887     * @return false to simplify use
4888 dl 1.52 */
4889 dl 1.61 final boolean tryCompleteComputation(Throwable ex) {
4890 dl 1.52 for (BulkTask<K,V,?> a = this;;) {
4891     BulkTask<K,V,?> p = a.parent;
4892     if (p == null) {
4893 dl 1.61 if (ex != null)
4894     a.completeExceptionally(ex);
4895     else
4896     a.quietlyComplete();
4897     return false;
4898 dl 1.52 }
4899     a = p;
4900     }
4901     }
4902    
4903 dl 1.61 /**
4904     * Version of tryCompleteComputation for function screening checks
4905     */
4906     final boolean abortOnNullFunction() {
4907     return tryCompleteComputation(new Error("Unexpected null function"));
4908 dl 1.52 }
4909    
4910     // utilities
4911    
4912     /** CompareAndSet pending count */
4913     final boolean casPending(int cmp, int val) {
4914     return U.compareAndSwapInt(this, PENDING, cmp, val);
4915     }
4916    
4917     /**
4918 jsr166 1.56 * Returns approx exp2 of the number of times (minus one) to
4919 dl 1.52 * split task by two before executing leaf action. This value
4920     * is faster to compute and more convenient to use as a guide
4921     * to splitting than is the depth, since it is used while
4922     * dividing by two anyway.
4923     */
4924     final int batch() {
4925 dl 1.63 ConcurrentHashMapV8<K, V> m; int b; Node[] t;
4926     if ((b = batch) < 0 && (m = map) != null) { // force initialization
4927     if ((t = tab) == null && (t = tab = m.table) != null)
4928     baseLimit = baseSize = t.length;
4929     if (t != null) {
4930     long n = m.counter.sum();
4931     int sp = getPool().getParallelism() << 3; // slack of 8
4932     b = batch = (n <= 0L) ? 0 : (n < (long)sp) ? (int)n : sp;
4933     }
4934 dl 1.52 }
4935     return b;
4936     }
4937    
4938     /**
4939 jsr166 1.56 * Returns exportable snapshot entry.
4940 dl 1.52 */
4941     static <K,V> AbstractMap.SimpleEntry<K,V> entryFor(K k, V v) {
4942 dl 1.59 return new AbstractMap.SimpleEntry<K,V>(k, v);
4943 dl 1.52 }
4944    
4945     // Unsafe mechanics
4946     private static final sun.misc.Unsafe U;
4947     private static final long PENDING;
4948     static {
4949     try {
4950 dl 1.59 U = getUnsafe();
4951 dl 1.52 PENDING = U.objectFieldOffset
4952     (BulkTask.class.getDeclaredField("pending"));
4953     } catch (Exception e) {
4954     throw new Error(e);
4955     }
4956     }
4957     }
4958    
4959     /*
4960     * Task classes. Coded in a regular but ugly format/style to
4961     * simplify checks that each variant differs in the right way from
4962     * others.
4963     */
4964    
4965 dl 1.61 @SuppressWarnings("serial") static final class ForEachKeyTask<K,V>
4966 dl 1.52 extends BulkTask<K,V,Void> {
4967     final Action<K> action;
4968     ForEachKeyTask
4969 dl 1.63 (ConcurrentHashMapV8<K,V> m, BulkTask<K,V,?> p, int b,
4970 dl 1.52 Action<K> action) {
4971 dl 1.63 super(m, p, b);
4972 dl 1.52 this.action = action;
4973     }
4974 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
4975 dl 1.52 final Action<K> action = this.action;
4976     if (action == null)
4977 dl 1.61 return abortOnNullFunction();
4978     try {
4979     int b = batch(), c;
4980     while (b > 1 && baseIndex != baseLimit) {
4981     do {} while (!casPending(c = pending, c+1));
4982 dl 1.63 new ForEachKeyTask<K,V>(map, this, b >>>= 1, action).fork();
4983 dl 1.61 }
4984     while (advance() != null)
4985     action.apply((K)nextKey);
4986     tryComplete();
4987     } catch (Throwable ex) {
4988     return tryCompleteComputation(ex);
4989 dl 1.52 }
4990 dl 1.61 return false;
4991 dl 1.52 }
4992     }
4993    
4994 dl 1.61 @SuppressWarnings("serial") static final class ForEachValueTask<K,V>
4995 dl 1.52 extends BulkTask<K,V,Void> {
4996     final Action<V> action;
4997     ForEachValueTask
4998 dl 1.63 (ConcurrentHashMapV8<K,V> m, BulkTask<K,V,?> p, int b,
4999 dl 1.52 Action<V> action) {
5000 dl 1.63 super(m, p, b);
5001 dl 1.52 this.action = action;
5002     }
5003 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
5004 dl 1.52 final Action<V> action = this.action;
5005     if (action == null)
5006 dl 1.61 return abortOnNullFunction();
5007     try {
5008     int b = batch(), c;
5009     while (b > 1 && baseIndex != baseLimit) {
5010     do {} while (!casPending(c = pending, c+1));
5011 dl 1.63 new ForEachValueTask<K,V>(map, this, b >>>= 1, action).fork();
5012 dl 1.61 }
5013     Object v;
5014     while ((v = advance()) != null)
5015     action.apply((V)v);
5016     tryComplete();
5017     } catch (Throwable ex) {
5018     return tryCompleteComputation(ex);
5019 dl 1.52 }
5020 dl 1.61 return false;
5021 dl 1.52 }
5022     }
5023    
5024 dl 1.61 @SuppressWarnings("serial") static final class ForEachEntryTask<K,V>
5025 dl 1.52 extends BulkTask<K,V,Void> {
5026     final Action<Entry<K,V>> action;
5027     ForEachEntryTask
5028 dl 1.63 (ConcurrentHashMapV8<K,V> m, BulkTask<K,V,?> p, int b,
5029 dl 1.52 Action<Entry<K,V>> action) {
5030 dl 1.63 super(m, p, b);
5031 dl 1.52 this.action = action;
5032     }
5033 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
5034 dl 1.52 final Action<Entry<K,V>> action = this.action;
5035     if (action == null)
5036 dl 1.61 return abortOnNullFunction();
5037     try {
5038     int b = batch(), c;
5039     while (b > 1 && baseIndex != baseLimit) {
5040     do {} while (!casPending(c = pending, c+1));
5041 dl 1.63 new ForEachEntryTask<K,V>(map, this, b >>>= 1, action).fork();
5042 dl 1.61 }
5043     Object v;
5044     while ((v = advance()) != null)
5045     action.apply(entryFor((K)nextKey, (V)v));
5046     tryComplete();
5047     } catch (Throwable ex) {
5048     return tryCompleteComputation(ex);
5049 dl 1.52 }
5050 dl 1.61 return false;
5051 dl 1.52 }
5052     }
5053    
5054 dl 1.61 @SuppressWarnings("serial") static final class ForEachMappingTask<K,V>
5055 dl 1.52 extends BulkTask<K,V,Void> {
5056     final BiAction<K,V> action;
5057     ForEachMappingTask
5058 dl 1.63 (ConcurrentHashMapV8<K,V> m, BulkTask<K,V,?> p, int b,
5059 dl 1.52 BiAction<K,V> action) {
5060 dl 1.63 super(m, p, b);
5061 dl 1.52 this.action = action;
5062     }
5063 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
5064 dl 1.52 final BiAction<K,V> action = this.action;
5065     if (action == null)
5066 dl 1.61 return abortOnNullFunction();
5067     try {
5068     int b = batch(), c;
5069     while (b > 1 && baseIndex != baseLimit) {
5070     do {} while (!casPending(c = pending, c+1));
5071 dl 1.63 new ForEachMappingTask<K,V>(map, this, b >>>= 1,
5072 dl 1.61 action).fork();
5073     }
5074     Object v;
5075     while ((v = advance()) != null)
5076     action.apply((K)nextKey, (V)v);
5077     tryComplete();
5078     } catch (Throwable ex) {
5079     return tryCompleteComputation(ex);
5080 dl 1.52 }
5081 dl 1.61 return false;
5082 dl 1.52 }
5083     }
5084    
5085 dl 1.61 @SuppressWarnings("serial") static final class ForEachTransformedKeyTask<K,V,U>
5086 dl 1.52 extends BulkTask<K,V,Void> {
5087     final Fun<? super K, ? extends U> transformer;
5088     final Action<U> action;
5089     ForEachTransformedKeyTask
5090 dl 1.63 (ConcurrentHashMapV8<K,V> m, BulkTask<K,V,?> p, int b,
5091 dl 1.52 Fun<? super K, ? extends U> transformer,
5092     Action<U> action) {
5093 dl 1.63 super(m, p, b);
5094 dl 1.52 this.transformer = transformer;
5095     this.action = action;
5096    
5097     }
5098 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
5099 dl 1.52 final Fun<? super K, ? extends U> transformer =
5100     this.transformer;
5101     final Action<U> action = this.action;
5102     if (transformer == null || action == null)
5103 dl 1.61 return abortOnNullFunction();
5104     try {
5105     int b = batch(), c;
5106     while (b > 1 && baseIndex != baseLimit) {
5107     do {} while (!casPending(c = pending, c+1));
5108     new ForEachTransformedKeyTask<K,V,U>
5109 dl 1.63 (map, this, b >>>= 1, transformer, action).fork();
5110 dl 1.61 }
5111     U u;
5112     while (advance() != null) {
5113     if ((u = transformer.apply((K)nextKey)) != null)
5114     action.apply(u);
5115     }
5116     tryComplete();
5117     } catch (Throwable ex) {
5118     return tryCompleteComputation(ex);
5119 dl 1.52 }
5120 dl 1.61 return false;
5121 dl 1.52 }
5122     }
5123    
5124 dl 1.61 @SuppressWarnings("serial") static final class ForEachTransformedValueTask<K,V,U>
5125 dl 1.52 extends BulkTask<K,V,Void> {
5126     final Fun<? super V, ? extends U> transformer;
5127     final Action<U> action;
5128     ForEachTransformedValueTask
5129 dl 1.63 (ConcurrentHashMapV8<K,V> m, BulkTask<K,V,?> p, int b,
5130 dl 1.52 Fun<? super V, ? extends U> transformer,
5131     Action<U> action) {
5132 dl 1.63 super(m, p, b);
5133 dl 1.52 this.transformer = transformer;
5134     this.action = action;
5135    
5136     }
5137 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
5138 dl 1.52 final Fun<? super V, ? extends U> transformer =
5139     this.transformer;
5140     final Action<U> action = this.action;
5141     if (transformer == null || action == null)
5142 dl 1.61 return abortOnNullFunction();
5143     try {
5144     int b = batch(), c;
5145     while (b > 1 && baseIndex != baseLimit) {
5146     do {} while (!casPending(c = pending, c+1));
5147     new ForEachTransformedValueTask<K,V,U>
5148 dl 1.63 (map, this, b >>>= 1, transformer, action).fork();
5149 dl 1.61 }
5150     Object v; U u;
5151     while ((v = advance()) != null) {
5152     if ((u = transformer.apply((V)v)) != null)
5153     action.apply(u);
5154     }
5155     tryComplete();
5156     } catch (Throwable ex) {
5157     return tryCompleteComputation(ex);
5158 dl 1.52 }
5159 dl 1.61 return false;
5160 dl 1.52 }
5161     }
5162    
5163 dl 1.61 @SuppressWarnings("serial") static final class ForEachTransformedEntryTask<K,V,U>
5164 dl 1.52 extends BulkTask<K,V,Void> {
5165     final Fun<Map.Entry<K,V>, ? extends U> transformer;
5166     final Action<U> action;
5167     ForEachTransformedEntryTask
5168 dl 1.63 (ConcurrentHashMapV8<K,V> m, BulkTask<K,V,?> p, int b,
5169 dl 1.52 Fun<Map.Entry<K,V>, ? extends U> transformer,
5170     Action<U> action) {
5171 dl 1.63 super(m, p, b);
5172 dl 1.52 this.transformer = transformer;
5173     this.action = action;
5174    
5175     }
5176 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
5177 dl 1.52 final Fun<Map.Entry<K,V>, ? extends U> transformer =
5178     this.transformer;
5179     final Action<U> action = this.action;
5180     if (transformer == null || action == null)
5181 dl 1.61 return abortOnNullFunction();
5182     try {
5183     int b = batch(), c;
5184     while (b > 1 && baseIndex != baseLimit) {
5185     do {} while (!casPending(c = pending, c+1));
5186     new ForEachTransformedEntryTask<K,V,U>
5187 dl 1.63 (map, this, b >>>= 1, transformer, action).fork();
5188 dl 1.61 }
5189     Object v; U u;
5190     while ((v = advance()) != null) {
5191     if ((u = transformer.apply(entryFor((K)nextKey, (V)v))) != null)
5192     action.apply(u);
5193     }
5194     tryComplete();
5195     } catch (Throwable ex) {
5196     return tryCompleteComputation(ex);
5197 dl 1.52 }
5198 dl 1.61 return false;
5199 dl 1.52 }
5200     }
5201    
5202 dl 1.61 @SuppressWarnings("serial") static final class ForEachTransformedMappingTask<K,V,U>
5203 dl 1.52 extends BulkTask<K,V,Void> {
5204     final BiFun<? super K, ? super V, ? extends U> transformer;
5205     final Action<U> action;
5206     ForEachTransformedMappingTask
5207 dl 1.63 (ConcurrentHashMapV8<K,V> m, BulkTask<K,V,?> p, int b,
5208 dl 1.52 BiFun<? super K, ? super V, ? extends U> transformer,
5209     Action<U> action) {
5210 dl 1.63 super(m, p, b);
5211 dl 1.52 this.transformer = transformer;
5212     this.action = action;
5213    
5214     }
5215 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
5216 dl 1.52 final BiFun<? super K, ? super V, ? extends U> transformer =
5217     this.transformer;
5218     final Action<U> action = this.action;
5219     if (transformer == null || action == null)
5220 dl 1.61 return abortOnNullFunction();
5221     try {
5222     int b = batch(), c;
5223     while (b > 1 && baseIndex != baseLimit) {
5224     do {} while (!casPending(c = pending, c+1));
5225     new ForEachTransformedMappingTask<K,V,U>
5226 dl 1.63 (map, this, b >>>= 1, transformer, action).fork();
5227 dl 1.61 }
5228     Object v; U u;
5229     while ((v = advance()) != null) {
5230     if ((u = transformer.apply((K)nextKey, (V)v)) != null)
5231     action.apply(u);
5232     }
5233     tryComplete();
5234     } catch (Throwable ex) {
5235     return tryCompleteComputation(ex);
5236 dl 1.52 }
5237 dl 1.61 return false;
5238 dl 1.52 }
5239     }
5240    
5241 dl 1.61 @SuppressWarnings("serial") static final class SearchKeysTask<K,V,U>
5242 dl 1.52 extends BulkTask<K,V,U> {
5243     final Fun<? super K, ? extends U> searchFunction;
5244     final AtomicReference<U> result;
5245     SearchKeysTask
5246 dl 1.63 (ConcurrentHashMapV8<K,V> m, BulkTask<K,V,?> p, int b,
5247 dl 1.52 Fun<? super K, ? extends U> searchFunction,
5248     AtomicReference<U> result) {
5249 dl 1.63 super(m, p, b);
5250 dl 1.52 this.searchFunction = searchFunction; this.result = result;
5251     }
5252 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
5253 dl 1.52 AtomicReference<U> result = this.result;
5254     final Fun<? super K, ? extends U> searchFunction =
5255     this.searchFunction;
5256     if (searchFunction == null || result == null)
5257 dl 1.61 return abortOnNullFunction();
5258     try {
5259     int b = batch(), c;
5260     while (b > 1 && baseIndex != baseLimit && result.get() == null) {
5261     do {} while (!casPending(c = pending, c+1));
5262 dl 1.63 new SearchKeysTask<K,V,U>(map, this, b >>>= 1,
5263 dl 1.61 searchFunction, result).fork();
5264     }
5265     U u;
5266     while (result.get() == null && advance() != null) {
5267     if ((u = searchFunction.apply((K)nextKey)) != null) {
5268     if (result.compareAndSet(null, u))
5269     tryCompleteComputation(null);
5270     break;
5271 dl 1.59 }
5272 dl 1.52 }
5273 dl 1.61 tryComplete();
5274     } catch (Throwable ex) {
5275     return tryCompleteComputation(ex);
5276 dl 1.52 }
5277 dl 1.61 return false;
5278 dl 1.52 }
5279     public final U getRawResult() { return result.get(); }
5280     }
5281    
5282 dl 1.61 @SuppressWarnings("serial") static final class SearchValuesTask<K,V,U>
5283 dl 1.52 extends BulkTask<K,V,U> {
5284     final Fun<? super V, ? extends U> searchFunction;
5285     final AtomicReference<U> result;
5286     SearchValuesTask
5287 dl 1.63 (ConcurrentHashMapV8<K,V> m, BulkTask<K,V,?> p, int b,
5288 dl 1.52 Fun<? super V, ? extends U> searchFunction,
5289     AtomicReference<U> result) {
5290 dl 1.63 super(m, p, b);
5291 dl 1.52 this.searchFunction = searchFunction; this.result = result;
5292     }
5293 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
5294 dl 1.52 AtomicReference<U> result = this.result;
5295     final Fun<? super V, ? extends U> searchFunction =
5296     this.searchFunction;
5297     if (searchFunction == null || result == null)
5298 dl 1.61 return abortOnNullFunction();
5299     try {
5300     int b = batch(), c;
5301     while (b > 1 && baseIndex != baseLimit && result.get() == null) {
5302     do {} while (!casPending(c = pending, c+1));
5303 dl 1.63 new SearchValuesTask<K,V,U>(map, this, b >>>= 1,
5304 dl 1.61 searchFunction, result).fork();
5305     }
5306     Object v; U u;
5307     while (result.get() == null && (v = advance()) != null) {
5308     if ((u = searchFunction.apply((V)v)) != null) {
5309     if (result.compareAndSet(null, u))
5310     tryCompleteComputation(null);
5311     break;
5312 dl 1.59 }
5313 dl 1.52 }
5314 dl 1.61 tryComplete();
5315     } catch (Throwable ex) {
5316     return tryCompleteComputation(ex);
5317 dl 1.52 }
5318 dl 1.61 return false;
5319 dl 1.52 }
5320     public final U getRawResult() { return result.get(); }
5321     }
5322    
5323 dl 1.61 @SuppressWarnings("serial") static final class SearchEntriesTask<K,V,U>
5324 dl 1.52 extends BulkTask<K,V,U> {
5325     final Fun<Entry<K,V>, ? extends U> searchFunction;
5326     final AtomicReference<U> result;
5327     SearchEntriesTask
5328 dl 1.63 (ConcurrentHashMapV8<K,V> m, BulkTask<K,V,?> p, int b,
5329 dl 1.52 Fun<Entry<K,V>, ? extends U> searchFunction,
5330     AtomicReference<U> result) {
5331 dl 1.63 super(m, p, b);
5332 dl 1.52 this.searchFunction = searchFunction; this.result = result;
5333     }
5334 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
5335 dl 1.52 AtomicReference<U> result = this.result;
5336     final Fun<Entry<K,V>, ? extends U> searchFunction =
5337     this.searchFunction;
5338     if (searchFunction == null || result == null)
5339 dl 1.61 return abortOnNullFunction();
5340     try {
5341     int b = batch(), c;
5342     while (b > 1 && baseIndex != baseLimit && result.get() == null) {
5343     do {} while (!casPending(c = pending, c+1));
5344 dl 1.63 new SearchEntriesTask<K,V,U>(map, this, b >>>= 1,
5345 dl 1.61 searchFunction, result).fork();
5346     }
5347     Object v; U u;
5348     while (result.get() == null && (v = advance()) != null) {
5349     if ((u = searchFunction.apply(entryFor((K)nextKey, (V)v))) != null) {
5350     if (result.compareAndSet(null, u))
5351     tryCompleteComputation(null);
5352     break;
5353 dl 1.59 }
5354 dl 1.52 }
5355 dl 1.61 tryComplete();
5356     } catch (Throwable ex) {
5357     return tryCompleteComputation(ex);
5358 dl 1.52 }
5359 dl 1.61 return false;
5360 dl 1.52 }
5361     public final U getRawResult() { return result.get(); }
5362     }
5363    
5364 dl 1.61 @SuppressWarnings("serial") static final class SearchMappingsTask<K,V,U>
5365 dl 1.52 extends BulkTask<K,V,U> {
5366     final BiFun<? super K, ? super V, ? extends U> searchFunction;
5367     final AtomicReference<U> result;
5368     SearchMappingsTask
5369 dl 1.63 (ConcurrentHashMapV8<K,V> m, BulkTask<K,V,?> p, int b,
5370 dl 1.52 BiFun<? super K, ? super V, ? extends U> searchFunction,
5371     AtomicReference<U> result) {
5372 dl 1.63 super(m, p, b);
5373 dl 1.52 this.searchFunction = searchFunction; this.result = result;
5374     }
5375 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
5376 dl 1.52 AtomicReference<U> result = this.result;
5377     final BiFun<? super K, ? super V, ? extends U> searchFunction =
5378     this.searchFunction;
5379     if (searchFunction == null || result == null)
5380 dl 1.61 return abortOnNullFunction();
5381     try {
5382     int b = batch(), c;
5383     while (b > 1 && baseIndex != baseLimit && result.get() == null) {
5384     do {} while (!casPending(c = pending, c+1));
5385 dl 1.63 new SearchMappingsTask<K,V,U>(map, this, b >>>= 1,
5386 dl 1.61 searchFunction, result).fork();
5387     }
5388     Object v; U u;
5389     while (result.get() == null && (v = advance()) != null) {
5390     if ((u = searchFunction.apply((K)nextKey, (V)v)) != null) {
5391     if (result.compareAndSet(null, u))
5392     tryCompleteComputation(null);
5393     break;
5394 dl 1.59 }
5395 dl 1.52 }
5396 dl 1.61 tryComplete();
5397     } catch (Throwable ex) {
5398     return tryCompleteComputation(ex);
5399 dl 1.52 }
5400 dl 1.61 return false;
5401 dl 1.52 }
5402     public final U getRawResult() { return result.get(); }
5403     }
5404    
5405 dl 1.61 @SuppressWarnings("serial") static final class ReduceKeysTask<K,V>
5406 dl 1.52 extends BulkTask<K,V,K> {
5407     final BiFun<? super K, ? super K, ? extends K> reducer;
5408     K result;
5409 dl 1.61 ReduceKeysTask<K,V> rights, nextRight;
5410 dl 1.52 ReduceKeysTask
5411 dl 1.63 (ConcurrentHashMapV8<K,V> m, BulkTask<K,V,?> p, int b,
5412 dl 1.61 ReduceKeysTask<K,V> nextRight,
5413 dl 1.52 BiFun<? super K, ? super K, ? extends K> reducer) {
5414 dl 1.63 super(m, p, b); this.nextRight = nextRight;
5415 dl 1.52 this.reducer = reducer;
5416     }
5417 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
5418 dl 1.52 final BiFun<? super K, ? super K, ? extends K> reducer =
5419     this.reducer;
5420     if (reducer == null)
5421 dl 1.61 return abortOnNullFunction();
5422     try {
5423     for (int c, b = batch(); b > 1 && baseIndex != baseLimit;) {
5424     do {} while (!casPending(c = pending, c+1));
5425     (rights = new ReduceKeysTask<K,V>
5426 dl 1.63 (map, this, b >>>= 1, rights, reducer)).fork();
5427 dl 1.61 }
5428     K r = null;
5429     while (advance() != null) {
5430     K u = (K)nextKey;
5431     r = (r == null) ? u : reducer.apply(r, u);
5432 dl 1.52 }
5433 dl 1.61 result = r;
5434     for (ReduceKeysTask<K,V> t = this, s;;) {
5435     int c; BulkTask<K,V,?> par; K tr, sr;
5436     if ((c = t.pending) == 0) {
5437     for (s = t.rights; s != null; s = t.rights = s.nextRight) {
5438     if ((sr = s.result) != null)
5439 jsr166 1.65 t.result = ((tr = t.result) == null) ? sr : reducer.apply(tr, sr);
5440 dl 1.61 }
5441     if ((par = t.parent) == null ||
5442     !(par instanceof ReduceKeysTask)) {
5443     t.quietlyComplete();
5444     break;
5445     }
5446     t = (ReduceKeysTask<K,V>)par;
5447     }
5448     else if (t.casPending(c, c - 1))
5449     break;
5450 dl 1.52 }
5451 dl 1.61 } catch (Throwable ex) {
5452     return tryCompleteComputation(ex);
5453 dl 1.52 }
5454 dl 1.61 return false;
5455 dl 1.52 }
5456     public final K getRawResult() { return result; }
5457     }
5458    
5459 dl 1.61 @SuppressWarnings("serial") static final class ReduceValuesTask<K,V>
5460 dl 1.52 extends BulkTask<K,V,V> {
5461     final BiFun<? super V, ? super V, ? extends V> reducer;
5462     V result;
5463 dl 1.61 ReduceValuesTask<K,V> rights, nextRight;
5464 dl 1.52 ReduceValuesTask
5465 dl 1.63 (ConcurrentHashMapV8<K,V> m, BulkTask<K,V,?> p, int b,
5466 dl 1.61 ReduceValuesTask<K,V> nextRight,
5467 dl 1.52 BiFun<? super V, ? super V, ? extends V> reducer) {
5468 dl 1.63 super(m, p, b); this.nextRight = nextRight;
5469 dl 1.52 this.reducer = reducer;
5470     }
5471 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
5472 dl 1.52 final BiFun<? super V, ? super V, ? extends V> reducer =
5473     this.reducer;
5474     if (reducer == null)
5475 dl 1.61 return abortOnNullFunction();
5476     try {
5477     for (int c, b = batch(); b > 1 && baseIndex != baseLimit;) {
5478     do {} while (!casPending(c = pending, c+1));
5479     (rights = new ReduceValuesTask<K,V>
5480 dl 1.63 (map, this, b >>>= 1, rights, reducer)).fork();
5481 dl 1.61 }
5482     V r = null;
5483     Object v;
5484     while ((v = advance()) != null) {
5485     V u = (V)v;
5486     r = (r == null) ? u : reducer.apply(r, u);
5487 dl 1.52 }
5488 dl 1.61 result = r;
5489     for (ReduceValuesTask<K,V> t = this, s;;) {
5490     int c; BulkTask<K,V,?> par; V tr, sr;
5491     if ((c = t.pending) == 0) {
5492     for (s = t.rights; s != null; s = t.rights = s.nextRight) {
5493     if ((sr = s.result) != null)
5494 jsr166 1.65 t.result = ((tr = t.result) == null) ? sr : reducer.apply(tr, sr);
5495 dl 1.61 }
5496     if ((par = t.parent) == null ||
5497     !(par instanceof ReduceValuesTask)) {
5498     t.quietlyComplete();
5499     break;
5500     }
5501     t = (ReduceValuesTask<K,V>)par;
5502     }
5503     else if (t.casPending(c, c - 1))
5504     break;
5505 dl 1.52 }
5506 dl 1.61 } catch (Throwable ex) {
5507     return tryCompleteComputation(ex);
5508 dl 1.52 }
5509 dl 1.61 return false;
5510 dl 1.52 }
5511     public final V getRawResult() { return result; }
5512     }
5513    
5514 dl 1.61 @SuppressWarnings("serial") static final class ReduceEntriesTask<K,V>
5515 dl 1.52 extends BulkTask<K,V,Map.Entry<K,V>> {
5516     final BiFun<Map.Entry<K,V>, Map.Entry<K,V>, ? extends Map.Entry<K,V>> reducer;
5517     Map.Entry<K,V> result;
5518 dl 1.61 ReduceEntriesTask<K,V> rights, nextRight;
5519 dl 1.52 ReduceEntriesTask
5520 dl 1.63 (ConcurrentHashMapV8<K,V> m, BulkTask<K,V,?> p, int b,
5521     ReduceEntriesTask<K,V> nextRight,
5522 dl 1.52 BiFun<Entry<K,V>, Map.Entry<K,V>, ? extends Map.Entry<K,V>> reducer) {
5523 dl 1.63 super(m, p, b); this.nextRight = nextRight;
5524 dl 1.52 this.reducer = reducer;
5525     }
5526 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
5527 dl 1.52 final BiFun<Map.Entry<K,V>, Map.Entry<K,V>, ? extends Map.Entry<K,V>> reducer =
5528     this.reducer;
5529     if (reducer == null)
5530 dl 1.61 return abortOnNullFunction();
5531     try {
5532     for (int c, b = batch(); b > 1 && baseIndex != baseLimit;) {
5533     do {} while (!casPending(c = pending, c+1));
5534     (rights = new ReduceEntriesTask<K,V>
5535 dl 1.63 (map, this, b >>>= 1, rights, reducer)).fork();
5536 dl 1.61 }
5537     Map.Entry<K,V> r = null;
5538     Object v;
5539     while ((v = advance()) != null) {
5540     Map.Entry<K,V> u = entryFor((K)nextKey, (V)v);
5541     r = (r == null) ? u : reducer.apply(r, u);
5542 dl 1.52 }
5543 dl 1.61 result = r;
5544     for (ReduceEntriesTask<K,V> t = this, s;;) {
5545     int c; BulkTask<K,V,?> par; Map.Entry<K,V> tr, sr;
5546     if ((c = t.pending) == 0) {
5547     for (s = t.rights; s != null; s = t.rights = s.nextRight) {
5548     if ((sr = s.result) != null)
5549 jsr166 1.65 t.result = ((tr = t.result) == null) ? sr : reducer.apply(tr, sr);
5550 dl 1.61 }
5551     if ((par = t.parent) == null ||
5552     !(par instanceof ReduceEntriesTask)) {
5553     t.quietlyComplete();
5554     break;
5555     }
5556     t = (ReduceEntriesTask<K,V>)par;
5557     }
5558     else if (t.casPending(c, c - 1))
5559     break;
5560 dl 1.52 }
5561 dl 1.61 } catch (Throwable ex) {
5562     return tryCompleteComputation(ex);
5563 dl 1.52 }
5564 dl 1.61 return false;
5565 dl 1.52 }
5566     public final Map.Entry<K,V> getRawResult() { return result; }
5567     }
5568    
5569 dl 1.61 @SuppressWarnings("serial") static final class MapReduceKeysTask<K,V,U>
5570 dl 1.52 extends BulkTask<K,V,U> {
5571     final Fun<? super K, ? extends U> transformer;
5572     final BiFun<? super U, ? super U, ? extends U> reducer;
5573     U result;
5574 dl 1.61 MapReduceKeysTask<K,V,U> rights, nextRight;
5575 dl 1.52 MapReduceKeysTask
5576 dl 1.63 (ConcurrentHashMapV8<K,V> m, BulkTask<K,V,?> p, int b,
5577 dl 1.61 MapReduceKeysTask<K,V,U> nextRight,
5578 dl 1.52 Fun<? super K, ? extends U> transformer,
5579     BiFun<? super U, ? super U, ? extends U> reducer) {
5580 dl 1.63 super(m, p, b); this.nextRight = nextRight;
5581 dl 1.52 this.transformer = transformer;
5582     this.reducer = reducer;
5583     }
5584 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
5585 dl 1.52 final Fun<? super K, ? extends U> transformer =
5586     this.transformer;
5587     final BiFun<? super U, ? super U, ? extends U> reducer =
5588     this.reducer;
5589     if (transformer == null || reducer == null)
5590 dl 1.61 return abortOnNullFunction();
5591     try {
5592     for (int c, b = batch(); b > 1 && baseIndex != baseLimit;) {
5593     do {} while (!casPending(c = pending, c+1));
5594     (rights = new MapReduceKeysTask<K,V,U>
5595 dl 1.63 (map, this, b >>>= 1, rights, transformer, reducer)).fork();
5596 dl 1.61 }
5597     U r = null, u;
5598     while (advance() != null) {
5599     if ((u = transformer.apply((K)nextKey)) != null)
5600     r = (r == null) ? u : reducer.apply(r, u);
5601 dl 1.52 }
5602 dl 1.61 result = r;
5603     for (MapReduceKeysTask<K,V,U> t = this, s;;) {
5604     int c; BulkTask<K,V,?> par; U tr, sr;
5605     if ((c = t.pending) == 0) {
5606     for (s = t.rights; s != null; s = t.rights = s.nextRight) {
5607     if ((sr = s.result) != null)
5608 jsr166 1.65 t.result = ((tr = t.result) == null) ? sr : reducer.apply(tr, sr);
5609 dl 1.61 }
5610     if ((par = t.parent) == null ||
5611     !(par instanceof MapReduceKeysTask)) {
5612     t.quietlyComplete();
5613     break;
5614     }
5615     t = (MapReduceKeysTask<K,V,U>)par;
5616     }
5617     else if (t.casPending(c, c - 1))
5618     break;
5619 dl 1.52 }
5620 dl 1.61 } catch (Throwable ex) {
5621     return tryCompleteComputation(ex);
5622 dl 1.52 }
5623 dl 1.61 return false;
5624 dl 1.52 }
5625     public final U getRawResult() { return result; }
5626     }
5627    
5628 dl 1.61 @SuppressWarnings("serial") static final class MapReduceValuesTask<K,V,U>
5629 dl 1.52 extends BulkTask<K,V,U> {
5630     final Fun<? super V, ? extends U> transformer;
5631     final BiFun<? super U, ? super U, ? extends U> reducer;
5632     U result;
5633 dl 1.61 MapReduceValuesTask<K,V,U> rights, nextRight;
5634 dl 1.52 MapReduceValuesTask
5635 dl 1.63 (ConcurrentHashMapV8<K,V> m, BulkTask<K,V,?> p, int b,
5636 dl 1.61 MapReduceValuesTask<K,V,U> nextRight,
5637 dl 1.52 Fun<? super V, ? extends U> transformer,
5638     BiFun<? super U, ? super U, ? extends U> reducer) {
5639 dl 1.63 super(m, p, b); this.nextRight = nextRight;
5640 dl 1.52 this.transformer = transformer;
5641     this.reducer = reducer;
5642     }
5643 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
5644 dl 1.52 final Fun<? super V, ? extends U> transformer =
5645     this.transformer;
5646     final BiFun<? super U, ? super U, ? extends U> reducer =
5647     this.reducer;
5648     if (transformer == null || reducer == null)
5649 dl 1.61 return abortOnNullFunction();
5650     try {
5651     for (int c, b = batch(); b > 1 && baseIndex != baseLimit;) {
5652     do {} while (!casPending(c = pending, c+1));
5653     (rights = new MapReduceValuesTask<K,V,U>
5654 dl 1.63 (map, this, b >>>= 1, rights, transformer, reducer)).fork();
5655 dl 1.61 }
5656     U r = null, u;
5657     Object v;
5658     while ((v = advance()) != null) {
5659     if ((u = transformer.apply((V)v)) != null)
5660     r = (r == null) ? u : reducer.apply(r, u);
5661 dl 1.52 }
5662 dl 1.61 result = r;
5663     for (MapReduceValuesTask<K,V,U> t = this, s;;) {
5664     int c; BulkTask<K,V,?> par; U tr, sr;
5665     if ((c = t.pending) == 0) {
5666     for (s = t.rights; s != null; s = t.rights = s.nextRight) {
5667     if ((sr = s.result) != null)
5668 jsr166 1.65 t.result = ((tr = t.result) == null) ? sr : reducer.apply(tr, sr);
5669 dl 1.61 }
5670     if ((par = t.parent) == null ||
5671     !(par instanceof MapReduceValuesTask)) {
5672     t.quietlyComplete();
5673     break;
5674     }
5675     t = (MapReduceValuesTask<K,V,U>)par;
5676     }
5677     else if (t.casPending(c, c - 1))
5678     break;
5679 dl 1.52 }
5680 dl 1.61 } catch (Throwable ex) {
5681     return tryCompleteComputation(ex);
5682 dl 1.52 }
5683 dl 1.61 return false;
5684 dl 1.52 }
5685     public final U getRawResult() { return result; }
5686     }
5687    
5688 dl 1.61 @SuppressWarnings("serial") static final class MapReduceEntriesTask<K,V,U>
5689 dl 1.52 extends BulkTask<K,V,U> {
5690     final Fun<Map.Entry<K,V>, ? extends U> transformer;
5691     final BiFun<? super U, ? super U, ? extends U> reducer;
5692     U result;
5693 dl 1.61 MapReduceEntriesTask<K,V,U> rights, nextRight;
5694 dl 1.52 MapReduceEntriesTask
5695 dl 1.63 (ConcurrentHashMapV8<K,V> m, BulkTask<K,V,?> p, int b,
5696 dl 1.61 MapReduceEntriesTask<K,V,U> nextRight,
5697 dl 1.52 Fun<Map.Entry<K,V>, ? extends U> transformer,
5698     BiFun<? super U, ? super U, ? extends U> reducer) {
5699 dl 1.63 super(m, p, b); this.nextRight = nextRight;
5700 dl 1.52 this.transformer = transformer;
5701     this.reducer = reducer;
5702     }
5703 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
5704 dl 1.52 final Fun<Map.Entry<K,V>, ? extends U> transformer =
5705     this.transformer;
5706     final BiFun<? super U, ? super U, ? extends U> reducer =
5707     this.reducer;
5708     if (transformer == null || reducer == null)
5709 dl 1.61 return abortOnNullFunction();
5710     try {
5711     for (int c, b = batch(); b > 1 && baseIndex != baseLimit;) {
5712     do {} while (!casPending(c = pending, c+1));
5713     (rights = new MapReduceEntriesTask<K,V,U>
5714 dl 1.63 (map, this, b >>>= 1, rights, transformer, reducer)).fork();
5715 dl 1.61 }
5716     U r = null, u;
5717     Object v;
5718     while ((v = advance()) != null) {
5719     if ((u = transformer.apply(entryFor((K)nextKey, (V)v))) != null)
5720     r = (r == null) ? u : reducer.apply(r, u);
5721 dl 1.52 }
5722 dl 1.61 result = r;
5723     for (MapReduceEntriesTask<K,V,U> t = this, s;;) {
5724     int c; BulkTask<K,V,?> par; U tr, sr;
5725     if ((c = t.pending) == 0) {
5726     for (s = t.rights; s != null; s = t.rights = s.nextRight) {
5727     if ((sr = s.result) != null)
5728 jsr166 1.65 t.result = ((tr = t.result) == null) ? sr : reducer.apply(tr, sr);
5729 dl 1.61 }
5730     if ((par = t.parent) == null ||
5731     !(par instanceof MapReduceEntriesTask)) {
5732     t.quietlyComplete();
5733     break;
5734     }
5735     t = (MapReduceEntriesTask<K,V,U>)par;
5736     }
5737     else if (t.casPending(c, c - 1))
5738     break;
5739 dl 1.52 }
5740 dl 1.61 } catch (Throwable ex) {
5741     return tryCompleteComputation(ex);
5742 dl 1.52 }
5743 dl 1.61 return false;
5744 dl 1.52 }
5745     public final U getRawResult() { return result; }
5746     }
5747    
5748 dl 1.61 @SuppressWarnings("serial") static final class MapReduceMappingsTask<K,V,U>
5749 dl 1.52 extends BulkTask<K,V,U> {
5750     final BiFun<? super K, ? super V, ? extends U> transformer;
5751     final BiFun<? super U, ? super U, ? extends U> reducer;
5752     U result;
5753 dl 1.61 MapReduceMappingsTask<K,V,U> rights, nextRight;
5754 dl 1.52 MapReduceMappingsTask
5755 dl 1.63 (ConcurrentHashMapV8<K,V> m, BulkTask<K,V,?> p, int b,
5756 dl 1.61 MapReduceMappingsTask<K,V,U> nextRight,
5757 dl 1.52 BiFun<? super K, ? super V, ? extends U> transformer,
5758     BiFun<? super U, ? super U, ? extends U> reducer) {
5759 dl 1.63 super(m, p, b); this.nextRight = nextRight;
5760 dl 1.52 this.transformer = transformer;
5761     this.reducer = reducer;
5762     }
5763 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
5764 dl 1.52 final BiFun<? super K, ? super V, ? extends U> transformer =
5765     this.transformer;
5766     final BiFun<? super U, ? super U, ? extends U> reducer =
5767     this.reducer;
5768     if (transformer == null || reducer == null)
5769 dl 1.61 return abortOnNullFunction();
5770     try {
5771     for (int c, b = batch(); b > 1 && baseIndex != baseLimit;) {
5772     do {} while (!casPending(c = pending, c+1));
5773     (rights = new MapReduceMappingsTask<K,V,U>
5774 dl 1.63 (map, this, b >>>= 1, rights, transformer, reducer)).fork();
5775 dl 1.61 }
5776     U r = null, u;
5777     Object v;
5778     while ((v = advance()) != null) {
5779     if ((u = transformer.apply((K)nextKey, (V)v)) != null)
5780     r = (r == null) ? u : reducer.apply(r, u);
5781 dl 1.52 }
5782 dl 1.61 result = r;
5783     for (MapReduceMappingsTask<K,V,U> t = this, s;;) {
5784     int c; BulkTask<K,V,?> par; U tr, sr;
5785     if ((c = t.pending) == 0) {
5786     for (s = t.rights; s != null; s = t.rights = s.nextRight) {
5787     if ((sr = s.result) != null)
5788 jsr166 1.65 t.result = ((tr = t.result) == null) ? sr : reducer.apply(tr, sr);
5789 dl 1.61 }
5790     if ((par = t.parent) == null ||
5791     !(par instanceof MapReduceMappingsTask)) {
5792     t.quietlyComplete();
5793     break;
5794     }
5795     t = (MapReduceMappingsTask<K,V,U>)par;
5796     }
5797     else if (t.casPending(c, c - 1))
5798     break;
5799 dl 1.52 }
5800 dl 1.61 } catch (Throwable ex) {
5801     return tryCompleteComputation(ex);
5802 dl 1.52 }
5803 dl 1.61 return false;
5804 dl 1.52 }
5805     public final U getRawResult() { return result; }
5806     }
5807    
5808 dl 1.61 @SuppressWarnings("serial") static final class MapReduceKeysToDoubleTask<K,V>
5809 dl 1.52 extends BulkTask<K,V,Double> {
5810     final ObjectToDouble<? super K> transformer;
5811     final DoubleByDoubleToDouble reducer;
5812     final double basis;
5813     double result;
5814 dl 1.61 MapReduceKeysToDoubleTask<K,V> rights, nextRight;
5815 dl 1.52 MapReduceKeysToDoubleTask
5816 dl 1.63 (ConcurrentHashMapV8<K,V> m, BulkTask<K,V,?> p, int b,
5817 dl 1.61 MapReduceKeysToDoubleTask<K,V> nextRight,
5818 dl 1.52 ObjectToDouble<? super K> transformer,
5819     double basis,
5820     DoubleByDoubleToDouble reducer) {
5821 dl 1.63 super(m, p, b); this.nextRight = nextRight;
5822 dl 1.52 this.transformer = transformer;
5823     this.basis = basis; this.reducer = reducer;
5824     }
5825 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
5826 dl 1.52 final ObjectToDouble<? super K> transformer =
5827     this.transformer;
5828     final DoubleByDoubleToDouble reducer = this.reducer;
5829     if (transformer == null || reducer == null)
5830 dl 1.61 return abortOnNullFunction();
5831     try {
5832     final double id = this.basis;
5833     for (int c, b = batch(); b > 1 && baseIndex != baseLimit;) {
5834     do {} while (!casPending(c = pending, c+1));
5835     (rights = new MapReduceKeysToDoubleTask<K,V>
5836 dl 1.63 (map, this, b >>>= 1, rights, transformer, id, reducer)).fork();
5837 dl 1.61 }
5838     double r = id;
5839     while (advance() != null)
5840     r = reducer.apply(r, transformer.apply((K)nextKey));
5841     result = r;
5842     for (MapReduceKeysToDoubleTask<K,V> t = this, s;;) {
5843     int c; BulkTask<K,V,?> par;
5844     if ((c = t.pending) == 0) {
5845     for (s = t.rights; s != null; s = t.rights = s.nextRight) {
5846     t.result = reducer.apply(t.result, s.result);
5847     }
5848     if ((par = t.parent) == null ||
5849     !(par instanceof MapReduceKeysToDoubleTask)) {
5850     t.quietlyComplete();
5851     break;
5852     }
5853     t = (MapReduceKeysToDoubleTask<K,V>)par;
5854     }
5855     else if (t.casPending(c, c - 1))
5856     break;
5857 dl 1.52 }
5858 dl 1.61 } catch (Throwable ex) {
5859     return tryCompleteComputation(ex);
5860 dl 1.52 }
5861 dl 1.61 return false;
5862 dl 1.52 }
5863     public final Double getRawResult() { return result; }
5864     }
5865    
5866 dl 1.61 @SuppressWarnings("serial") static final class MapReduceValuesToDoubleTask<K,V>
5867 dl 1.52 extends BulkTask<K,V,Double> {
5868     final ObjectToDouble<? super V> transformer;
5869     final DoubleByDoubleToDouble reducer;
5870     final double basis;
5871     double result;
5872 dl 1.61 MapReduceValuesToDoubleTask<K,V> rights, nextRight;
5873 dl 1.52 MapReduceValuesToDoubleTask
5874 dl 1.63 (ConcurrentHashMapV8<K,V> m, BulkTask<K,V,?> p, int b,
5875 dl 1.61 MapReduceValuesToDoubleTask<K,V> nextRight,
5876 dl 1.52 ObjectToDouble<? super V> transformer,
5877     double basis,
5878     DoubleByDoubleToDouble reducer) {
5879 dl 1.63 super(m, p, b); this.nextRight = nextRight;
5880 dl 1.52 this.transformer = transformer;
5881     this.basis = basis; this.reducer = reducer;
5882     }
5883 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
5884 dl 1.52 final ObjectToDouble<? super V> transformer =
5885     this.transformer;
5886     final DoubleByDoubleToDouble reducer = this.reducer;
5887     if (transformer == null || reducer == null)
5888 dl 1.61 return abortOnNullFunction();
5889     try {
5890     final double id = this.basis;
5891     for (int c, b = batch(); b > 1 && baseIndex != baseLimit;) {
5892     do {} while (!casPending(c = pending, c+1));
5893     (rights = new MapReduceValuesToDoubleTask<K,V>
5894 dl 1.63 (map, this, b >>>= 1, rights, transformer, id, reducer)).fork();
5895 dl 1.61 }
5896     double r = id;
5897     Object v;
5898     while ((v = advance()) != null)
5899     r = reducer.apply(r, transformer.apply((V)v));
5900     result = r;
5901     for (MapReduceValuesToDoubleTask<K,V> t = this, s;;) {
5902     int c; BulkTask<K,V,?> par;
5903     if ((c = t.pending) == 0) {
5904     for (s = t.rights; s != null; s = t.rights = s.nextRight) {
5905     t.result = reducer.apply(t.result, s.result);
5906     }
5907     if ((par = t.parent) == null ||
5908     !(par instanceof MapReduceValuesToDoubleTask)) {
5909     t.quietlyComplete();
5910     break;
5911     }
5912     t = (MapReduceValuesToDoubleTask<K,V>)par;
5913     }
5914     else if (t.casPending(c, c - 1))
5915     break;
5916 dl 1.52 }
5917 dl 1.61 } catch (Throwable ex) {
5918     return tryCompleteComputation(ex);
5919 dl 1.52 }
5920 dl 1.61 return false;
5921 dl 1.52 }
5922     public final Double getRawResult() { return result; }
5923     }
5924    
5925 dl 1.61 @SuppressWarnings("serial") static final class MapReduceEntriesToDoubleTask<K,V>
5926 dl 1.52 extends BulkTask<K,V,Double> {
5927     final ObjectToDouble<Map.Entry<K,V>> transformer;
5928     final DoubleByDoubleToDouble reducer;
5929     final double basis;
5930     double result;
5931 dl 1.61 MapReduceEntriesToDoubleTask<K,V> rights, nextRight;
5932 dl 1.52 MapReduceEntriesToDoubleTask
5933 dl 1.63 (ConcurrentHashMapV8<K,V> m, BulkTask<K,V,?> p, int b,
5934 dl 1.61 MapReduceEntriesToDoubleTask<K,V> nextRight,
5935 dl 1.52 ObjectToDouble<Map.Entry<K,V>> transformer,
5936     double basis,
5937     DoubleByDoubleToDouble reducer) {
5938 dl 1.63 super(m, p, b); this.nextRight = nextRight;
5939 dl 1.52 this.transformer = transformer;
5940     this.basis = basis; this.reducer = reducer;
5941     }
5942 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
5943 dl 1.52 final ObjectToDouble<Map.Entry<K,V>> transformer =
5944     this.transformer;
5945     final DoubleByDoubleToDouble reducer = this.reducer;
5946     if (transformer == null || reducer == null)
5947 dl 1.61 return abortOnNullFunction();
5948     try {
5949     final double id = this.basis;
5950     for (int c, b = batch(); b > 1 && baseIndex != baseLimit;) {
5951     do {} while (!casPending(c = pending, c+1));
5952     (rights = new MapReduceEntriesToDoubleTask<K,V>
5953 dl 1.63 (map, this, b >>>= 1, rights, transformer, id, reducer)).fork();
5954 dl 1.61 }
5955     double r = id;
5956     Object v;
5957     while ((v = advance()) != null)
5958     r = reducer.apply(r, transformer.apply(entryFor((K)nextKey, (V)v)));
5959     result = r;
5960     for (MapReduceEntriesToDoubleTask<K,V> t = this, s;;) {
5961     int c; BulkTask<K,V,?> par;
5962     if ((c = t.pending) == 0) {
5963     for (s = t.rights; s != null; s = t.rights = s.nextRight) {
5964     t.result = reducer.apply(t.result, s.result);
5965     }
5966     if ((par = t.parent) == null ||
5967     !(par instanceof MapReduceEntriesToDoubleTask)) {
5968     t.quietlyComplete();
5969     break;
5970     }
5971     t = (MapReduceEntriesToDoubleTask<K,V>)par;
5972     }
5973     else if (t.casPending(c, c - 1))
5974     break;
5975 dl 1.52 }
5976 dl 1.61 } catch (Throwable ex) {
5977     return tryCompleteComputation(ex);
5978 dl 1.52 }
5979 dl 1.61 return false;
5980 dl 1.52 }
5981     public final Double getRawResult() { return result; }
5982     }
5983    
5984 dl 1.61 @SuppressWarnings("serial") static final class MapReduceMappingsToDoubleTask<K,V>
5985 dl 1.52 extends BulkTask<K,V,Double> {
5986     final ObjectByObjectToDouble<? super K, ? super V> transformer;
5987     final DoubleByDoubleToDouble reducer;
5988     final double basis;
5989     double result;
5990 dl 1.61 MapReduceMappingsToDoubleTask<K,V> rights, nextRight;
5991 dl 1.52 MapReduceMappingsToDoubleTask
5992 dl 1.63 (ConcurrentHashMapV8<K,V> m, BulkTask<K,V,?> p, int b,
5993 dl 1.61 MapReduceMappingsToDoubleTask<K,V> nextRight,
5994 dl 1.52 ObjectByObjectToDouble<? super K, ? super V> transformer,
5995     double basis,
5996     DoubleByDoubleToDouble reducer) {
5997 dl 1.63 super(m, p, b); this.nextRight = nextRight;
5998 dl 1.52 this.transformer = transformer;
5999     this.basis = basis; this.reducer = reducer;
6000     }
6001 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
6002 dl 1.52 final ObjectByObjectToDouble<? super K, ? super V> transformer =
6003     this.transformer;
6004     final DoubleByDoubleToDouble reducer = this.reducer;
6005     if (transformer == null || reducer == null)
6006 dl 1.61 return abortOnNullFunction();
6007     try {
6008     final double id = this.basis;
6009     for (int c, b = batch(); b > 1 && baseIndex != baseLimit;) {
6010     do {} while (!casPending(c = pending, c+1));
6011     (rights = new MapReduceMappingsToDoubleTask<K,V>
6012 dl 1.63 (map, this, b >>>= 1, rights, transformer, id, reducer)).fork();
6013 dl 1.61 }
6014     double r = id;
6015     Object v;
6016     while ((v = advance()) != null)
6017     r = reducer.apply(r, transformer.apply((K)nextKey, (V)v));
6018     result = r;
6019     for (MapReduceMappingsToDoubleTask<K,V> t = this, s;;) {
6020     int c; BulkTask<K,V,?> par;
6021     if ((c = t.pending) == 0) {
6022     for (s = t.rights; s != null; s = t.rights = s.nextRight) {
6023     t.result = reducer.apply(t.result, s.result);
6024     }
6025     if ((par = t.parent) == null ||
6026     !(par instanceof MapReduceMappingsToDoubleTask)) {
6027     t.quietlyComplete();
6028     break;
6029     }
6030     t = (MapReduceMappingsToDoubleTask<K,V>)par;
6031     }
6032     else if (t.casPending(c, c - 1))
6033     break;
6034 dl 1.52 }
6035 dl 1.61 } catch (Throwable ex) {
6036     return tryCompleteComputation(ex);
6037 dl 1.52 }
6038 dl 1.61 return false;
6039 dl 1.52 }
6040     public final Double getRawResult() { return result; }
6041     }
6042    
6043 dl 1.61 @SuppressWarnings("serial") static final class MapReduceKeysToLongTask<K,V>
6044 dl 1.52 extends BulkTask<K,V,Long> {
6045     final ObjectToLong<? super K> transformer;
6046     final LongByLongToLong reducer;
6047     final long basis;
6048     long result;
6049 dl 1.61 MapReduceKeysToLongTask<K,V> rights, nextRight;
6050 dl 1.52 MapReduceKeysToLongTask
6051 dl 1.63 (ConcurrentHashMapV8<K,V> m, BulkTask<K,V,?> p, int b,
6052 dl 1.61 MapReduceKeysToLongTask<K,V> nextRight,
6053 dl 1.52 ObjectToLong<? super K> transformer,
6054     long basis,
6055     LongByLongToLong reducer) {
6056 dl 1.63 super(m, p, b); this.nextRight = nextRight;
6057 dl 1.52 this.transformer = transformer;
6058     this.basis = basis; this.reducer = reducer;
6059     }
6060 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
6061 dl 1.52 final ObjectToLong<? super K> transformer =
6062     this.transformer;
6063     final LongByLongToLong reducer = this.reducer;
6064     if (transformer == null || reducer == null)
6065 dl 1.61 return abortOnNullFunction();
6066     try {
6067     final long id = this.basis;
6068     for (int c, b = batch(); b > 1 && baseIndex != baseLimit;) {
6069     do {} while (!casPending(c = pending, c+1));
6070     (rights = new MapReduceKeysToLongTask<K,V>
6071 dl 1.63 (map, this, b >>>= 1, rights, transformer, id, reducer)).fork();
6072 dl 1.61 }
6073     long r = id;
6074     while (advance() != null)
6075     r = reducer.apply(r, transformer.apply((K)nextKey));
6076     result = r;
6077     for (MapReduceKeysToLongTask<K,V> t = this, s;;) {
6078     int c; BulkTask<K,V,?> par;
6079     if ((c = t.pending) == 0) {
6080     for (s = t.rights; s != null; s = t.rights = s.nextRight) {
6081     t.result = reducer.apply(t.result, s.result);
6082     }
6083     if ((par = t.parent) == null ||
6084     !(par instanceof MapReduceKeysToLongTask)) {
6085     t.quietlyComplete();
6086     break;
6087     }
6088     t = (MapReduceKeysToLongTask<K,V>)par;
6089     }
6090     else if (t.casPending(c, c - 1))
6091     break;
6092 dl 1.52 }
6093 dl 1.61 } catch (Throwable ex) {
6094     return tryCompleteComputation(ex);
6095 dl 1.52 }
6096 dl 1.61 return false;
6097 dl 1.52 }
6098     public final Long getRawResult() { return result; }
6099     }
6100    
6101 dl 1.61 @SuppressWarnings("serial") static final class MapReduceValuesToLongTask<K,V>
6102 dl 1.52 extends BulkTask<K,V,Long> {
6103     final ObjectToLong<? super V> transformer;
6104     final LongByLongToLong reducer;
6105     final long basis;
6106     long result;
6107 dl 1.61 MapReduceValuesToLongTask<K,V> rights, nextRight;
6108 dl 1.52 MapReduceValuesToLongTask
6109 dl 1.63 (ConcurrentHashMapV8<K,V> m, BulkTask<K,V,?> p, int b,
6110 dl 1.61 MapReduceValuesToLongTask<K,V> nextRight,
6111 dl 1.52 ObjectToLong<? super V> transformer,
6112     long basis,
6113     LongByLongToLong reducer) {
6114 dl 1.63 super(m, p, b); this.nextRight = nextRight;
6115 dl 1.52 this.transformer = transformer;
6116     this.basis = basis; this.reducer = reducer;
6117     }
6118 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
6119 dl 1.52 final ObjectToLong<? super V> transformer =
6120     this.transformer;
6121     final LongByLongToLong reducer = this.reducer;
6122     if (transformer == null || reducer == null)
6123 dl 1.61 return abortOnNullFunction();
6124     try {
6125     final long id = this.basis;
6126     for (int c, b = batch(); b > 1 && baseIndex != baseLimit;) {
6127     do {} while (!casPending(c = pending, c+1));
6128     (rights = new MapReduceValuesToLongTask<K,V>
6129 dl 1.63 (map, this, b >>>= 1, rights, transformer, id, reducer)).fork();
6130 dl 1.61 }
6131     long r = id;
6132     Object v;
6133     while ((v = advance()) != null)
6134     r = reducer.apply(r, transformer.apply((V)v));
6135     result = r;
6136     for (MapReduceValuesToLongTask<K,V> t = this, s;;) {
6137     int c; BulkTask<K,V,?> par;
6138     if ((c = t.pending) == 0) {
6139     for (s = t.rights; s != null; s = t.rights = s.nextRight) {
6140     t.result = reducer.apply(t.result, s.result);
6141     }
6142     if ((par = t.parent) == null ||
6143     !(par instanceof MapReduceValuesToLongTask)) {
6144     t.quietlyComplete();
6145     break;
6146     }
6147     t = (MapReduceValuesToLongTask<K,V>)par;
6148     }
6149     else if (t.casPending(c, c - 1))
6150     break;
6151 dl 1.52 }
6152 dl 1.61 } catch (Throwable ex) {
6153     return tryCompleteComputation(ex);
6154 dl 1.52 }
6155 dl 1.61 return false;
6156 dl 1.52 }
6157     public final Long getRawResult() { return result; }
6158     }
6159    
6160 dl 1.61 @SuppressWarnings("serial") static final class MapReduceEntriesToLongTask<K,V>
6161 dl 1.52 extends BulkTask<K,V,Long> {
6162     final ObjectToLong<Map.Entry<K,V>> transformer;
6163     final LongByLongToLong reducer;
6164     final long basis;
6165     long result;
6166 dl 1.61 MapReduceEntriesToLongTask<K,V> rights, nextRight;
6167 dl 1.52 MapReduceEntriesToLongTask
6168 dl 1.63 (ConcurrentHashMapV8<K,V> m, BulkTask<K,V,?> p, int b,
6169 dl 1.61 MapReduceEntriesToLongTask<K,V> nextRight,
6170 dl 1.52 ObjectToLong<Map.Entry<K,V>> transformer,
6171     long basis,
6172     LongByLongToLong reducer) {
6173 dl 1.63 super(m, p, b); this.nextRight = nextRight;
6174 dl 1.52 this.transformer = transformer;
6175     this.basis = basis; this.reducer = reducer;
6176     }
6177 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
6178 dl 1.52 final ObjectToLong<Map.Entry<K,V>> transformer =
6179     this.transformer;
6180     final LongByLongToLong reducer = this.reducer;
6181     if (transformer == null || reducer == null)
6182 dl 1.61 return abortOnNullFunction();
6183     try {
6184     final long id = this.basis;
6185     for (int c, b = batch(); b > 1 && baseIndex != baseLimit;) {
6186     do {} while (!casPending(c = pending, c+1));
6187     (rights = new MapReduceEntriesToLongTask<K,V>
6188 dl 1.63 (map, this, b >>>= 1, rights, transformer, id, reducer)).fork();
6189 dl 1.61 }
6190     long r = id;
6191     Object v;
6192     while ((v = advance()) != null)
6193     r = reducer.apply(r, transformer.apply(entryFor((K)nextKey, (V)v)));
6194     result = r;
6195     for (MapReduceEntriesToLongTask<K,V> t = this, s;;) {
6196     int c; BulkTask<K,V,?> par;
6197     if ((c = t.pending) == 0) {
6198     for (s = t.rights; s != null; s = t.rights = s.nextRight) {
6199     t.result = reducer.apply(t.result, s.result);
6200     }
6201     if ((par = t.parent) == null ||
6202     !(par instanceof MapReduceEntriesToLongTask)) {
6203     t.quietlyComplete();
6204     break;
6205     }
6206     t = (MapReduceEntriesToLongTask<K,V>)par;
6207     }
6208     else if (t.casPending(c, c - 1))
6209     break;
6210 dl 1.52 }
6211 dl 1.61 } catch (Throwable ex) {
6212     return tryCompleteComputation(ex);
6213 dl 1.52 }
6214 dl 1.61 return false;
6215 dl 1.52 }
6216     public final Long getRawResult() { return result; }
6217     }
6218    
6219 dl 1.61 @SuppressWarnings("serial") static final class MapReduceMappingsToLongTask<K,V>
6220 dl 1.52 extends BulkTask<K,V,Long> {
6221     final ObjectByObjectToLong<? super K, ? super V> transformer;
6222     final LongByLongToLong reducer;
6223     final long basis;
6224     long result;
6225 dl 1.61 MapReduceMappingsToLongTask<K,V> rights, nextRight;
6226 dl 1.52 MapReduceMappingsToLongTask
6227 dl 1.63 (ConcurrentHashMapV8<K,V> m, BulkTask<K,V,?> p, int b,
6228 dl 1.61 MapReduceMappingsToLongTask<K,V> nextRight,
6229 dl 1.52 ObjectByObjectToLong<? super K, ? super V> transformer,
6230     long basis,
6231     LongByLongToLong reducer) {
6232 dl 1.63 super(m, p, b); this.nextRight = nextRight;
6233 dl 1.52 this.transformer = transformer;
6234     this.basis = basis; this.reducer = reducer;
6235     }
6236 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
6237 dl 1.52 final ObjectByObjectToLong<? super K, ? super V> transformer =
6238     this.transformer;
6239     final LongByLongToLong reducer = this.reducer;
6240     if (transformer == null || reducer == null)
6241 dl 1.61 return abortOnNullFunction();
6242     try {
6243     final long id = this.basis;
6244     for (int c, b = batch(); b > 1 && baseIndex != baseLimit;) {
6245     do {} while (!casPending(c = pending, c+1));
6246     (rights = new MapReduceMappingsToLongTask<K,V>
6247 dl 1.63 (map, this, b >>>= 1, rights, transformer, id, reducer)).fork();
6248 dl 1.61 }
6249     long r = id;
6250     Object v;
6251     while ((v = advance()) != null)
6252     r = reducer.apply(r, transformer.apply((K)nextKey, (V)v));
6253     result = r;
6254     for (MapReduceMappingsToLongTask<K,V> t = this, s;;) {
6255     int c; BulkTask<K,V,?> par;
6256     if ((c = t.pending) == 0) {
6257     for (s = t.rights; s != null; s = t.rights = s.nextRight) {
6258     t.result = reducer.apply(t.result, s.result);
6259     }
6260     if ((par = t.parent) == null ||
6261     !(par instanceof MapReduceMappingsToLongTask)) {
6262     t.quietlyComplete();
6263     break;
6264     }
6265     t = (MapReduceMappingsToLongTask<K,V>)par;
6266     }
6267     else if (t.casPending(c, c - 1))
6268     break;
6269 dl 1.52 }
6270 dl 1.61 } catch (Throwable ex) {
6271     return tryCompleteComputation(ex);
6272 dl 1.52 }
6273 dl 1.61 return false;
6274 dl 1.52 }
6275     public final Long getRawResult() { return result; }
6276     }
6277    
6278 dl 1.61 @SuppressWarnings("serial") static final class MapReduceKeysToIntTask<K,V>
6279 dl 1.52 extends BulkTask<K,V,Integer> {
6280     final ObjectToInt<? super K> transformer;
6281     final IntByIntToInt reducer;
6282     final int basis;
6283     int result;
6284 dl 1.61 MapReduceKeysToIntTask<K,V> rights, nextRight;
6285 dl 1.52 MapReduceKeysToIntTask
6286 dl 1.63 (ConcurrentHashMapV8<K,V> m, BulkTask<K,V,?> p, int b,
6287 dl 1.61 MapReduceKeysToIntTask<K,V> nextRight,
6288 dl 1.52 ObjectToInt<? super K> transformer,
6289     int basis,
6290     IntByIntToInt reducer) {
6291 dl 1.63 super(m, p, b); this.nextRight = nextRight;
6292 dl 1.52 this.transformer = transformer;
6293     this.basis = basis; this.reducer = reducer;
6294     }
6295 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
6296 dl 1.52 final ObjectToInt<? super K> transformer =
6297     this.transformer;
6298     final IntByIntToInt reducer = this.reducer;
6299     if (transformer == null || reducer == null)
6300 dl 1.61 return abortOnNullFunction();
6301     try {
6302     final int id = this.basis;
6303     for (int c, b = batch(); b > 1 && baseIndex != baseLimit;) {
6304     do {} while (!casPending(c = pending, c+1));
6305     (rights = new MapReduceKeysToIntTask<K,V>
6306 dl 1.63 (map, this, b >>>= 1, rights, transformer, id, reducer)).fork();
6307 dl 1.61 }
6308     int r = id;
6309     while (advance() != null)
6310     r = reducer.apply(r, transformer.apply((K)nextKey));
6311     result = r;
6312     for (MapReduceKeysToIntTask<K,V> t = this, s;;) {
6313     int c; BulkTask<K,V,?> par;
6314     if ((c = t.pending) == 0) {
6315     for (s = t.rights; s != null; s = t.rights = s.nextRight) {
6316     t.result = reducer.apply(t.result, s.result);
6317     }
6318     if ((par = t.parent) == null ||
6319     !(par instanceof MapReduceKeysToIntTask)) {
6320     t.quietlyComplete();
6321     break;
6322     }
6323     t = (MapReduceKeysToIntTask<K,V>)par;
6324     }
6325     else if (t.casPending(c, c - 1))
6326     break;
6327 dl 1.52 }
6328 dl 1.61 } catch (Throwable ex) {
6329     return tryCompleteComputation(ex);
6330 dl 1.52 }
6331 dl 1.61 return false;
6332 dl 1.52 }
6333     public final Integer getRawResult() { return result; }
6334     }
6335    
6336 dl 1.61 @SuppressWarnings("serial") static final class MapReduceValuesToIntTask<K,V>
6337 dl 1.52 extends BulkTask<K,V,Integer> {
6338     final ObjectToInt<? super V> transformer;
6339     final IntByIntToInt reducer;
6340     final int basis;
6341     int result;
6342 dl 1.61 MapReduceValuesToIntTask<K,V> rights, nextRight;
6343 dl 1.52 MapReduceValuesToIntTask
6344 dl 1.63 (ConcurrentHashMapV8<K,V> m, BulkTask<K,V,?> p, int b,
6345 dl 1.61 MapReduceValuesToIntTask<K,V> nextRight,
6346 dl 1.52 ObjectToInt<? super V> transformer,
6347     int basis,
6348     IntByIntToInt reducer) {
6349 dl 1.63 super(m, p, b); this.nextRight = nextRight;
6350 dl 1.52 this.transformer = transformer;
6351     this.basis = basis; this.reducer = reducer;
6352     }
6353 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
6354 dl 1.52 final ObjectToInt<? super V> transformer =
6355     this.transformer;
6356     final IntByIntToInt reducer = this.reducer;
6357     if (transformer == null || reducer == null)
6358 dl 1.61 return abortOnNullFunction();
6359     try {
6360     final int id = this.basis;
6361     for (int c, b = batch(); b > 1 && baseIndex != baseLimit;) {
6362     do {} while (!casPending(c = pending, c+1));
6363     (rights = new MapReduceValuesToIntTask<K,V>
6364 dl 1.63 (map, this, b >>>= 1, rights, transformer, id, reducer)).fork();
6365 dl 1.61 }
6366     int r = id;
6367     Object v;
6368     while ((v = advance()) != null)
6369     r = reducer.apply(r, transformer.apply((V)v));
6370     result = r;
6371     for (MapReduceValuesToIntTask<K,V> t = this, s;;) {
6372     int c; BulkTask<K,V,?> par;
6373     if ((c = t.pending) == 0) {
6374     for (s = t.rights; s != null; s = t.rights = s.nextRight) {
6375     t.result = reducer.apply(t.result, s.result);
6376     }
6377     if ((par = t.parent) == null ||
6378     !(par instanceof MapReduceValuesToIntTask)) {
6379     t.quietlyComplete();
6380     break;
6381     }
6382     t = (MapReduceValuesToIntTask<K,V>)par;
6383     }
6384     else if (t.casPending(c, c - 1))
6385     break;
6386 dl 1.52 }
6387 dl 1.61 } catch (Throwable ex) {
6388     return tryCompleteComputation(ex);
6389 dl 1.52 }
6390 dl 1.61 return false;
6391 dl 1.52 }
6392     public final Integer getRawResult() { return result; }
6393     }
6394    
6395 dl 1.61 @SuppressWarnings("serial") static final class MapReduceEntriesToIntTask<K,V>
6396 dl 1.52 extends BulkTask<K,V,Integer> {
6397     final ObjectToInt<Map.Entry<K,V>> transformer;
6398     final IntByIntToInt reducer;
6399     final int basis;
6400     int result;
6401 dl 1.61 MapReduceEntriesToIntTask<K,V> rights, nextRight;
6402 dl 1.52 MapReduceEntriesToIntTask
6403 dl 1.63 (ConcurrentHashMapV8<K,V> m, BulkTask<K,V,?> p, int b,
6404 dl 1.61 MapReduceEntriesToIntTask<K,V> nextRight,
6405 dl 1.52 ObjectToInt<Map.Entry<K,V>> transformer,
6406     int basis,
6407     IntByIntToInt reducer) {
6408 dl 1.63 super(m, p, b); this.nextRight = nextRight;
6409 dl 1.52 this.transformer = transformer;
6410     this.basis = basis; this.reducer = reducer;
6411     }
6412 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
6413 dl 1.52 final ObjectToInt<Map.Entry<K,V>> transformer =
6414     this.transformer;
6415     final IntByIntToInt reducer = this.reducer;
6416     if (transformer == null || reducer == null)
6417 dl 1.61 return abortOnNullFunction();
6418     try {
6419     final int id = this.basis;
6420     for (int c, b = batch(); b > 1 && baseIndex != baseLimit;) {
6421     do {} while (!casPending(c = pending, c+1));
6422     (rights = new MapReduceEntriesToIntTask<K,V>
6423 dl 1.63 (map, this, b >>>= 1, rights, transformer, id, reducer)).fork();
6424 dl 1.61 }
6425     int r = id;
6426     Object v;
6427     while ((v = advance()) != null)
6428     r = reducer.apply(r, transformer.apply(entryFor((K)nextKey, (V)v)));
6429     result = r;
6430     for (MapReduceEntriesToIntTask<K,V> t = this, s;;) {
6431     int c; BulkTask<K,V,?> par;
6432     if ((c = t.pending) == 0) {
6433     for (s = t.rights; s != null; s = t.rights = s.nextRight) {
6434     t.result = reducer.apply(t.result, s.result);
6435     }
6436     if ((par = t.parent) == null ||
6437     !(par instanceof MapReduceEntriesToIntTask)) {
6438     t.quietlyComplete();
6439     break;
6440     }
6441     t = (MapReduceEntriesToIntTask<K,V>)par;
6442     }
6443     else if (t.casPending(c, c - 1))
6444     break;
6445 dl 1.52 }
6446 dl 1.61 } catch (Throwable ex) {
6447     return tryCompleteComputation(ex);
6448 dl 1.52 }
6449 dl 1.61 return false;
6450 dl 1.52 }
6451     public final Integer getRawResult() { return result; }
6452     }
6453    
6454 dl 1.61 @SuppressWarnings("serial") static final class MapReduceMappingsToIntTask<K,V>
6455 dl 1.52 extends BulkTask<K,V,Integer> {
6456     final ObjectByObjectToInt<? super K, ? super V> transformer;
6457     final IntByIntToInt reducer;
6458     final int basis;
6459     int result;
6460 dl 1.61 MapReduceMappingsToIntTask<K,V> rights, nextRight;
6461 dl 1.52 MapReduceMappingsToIntTask
6462 dl 1.63 (ConcurrentHashMapV8<K,V> m, BulkTask<K,V,?> p, int b,
6463     MapReduceMappingsToIntTask<K,V> rights,
6464 dl 1.52 ObjectByObjectToInt<? super K, ? super V> transformer,
6465     int basis,
6466     IntByIntToInt reducer) {
6467 dl 1.63 super(m, p, b); this.nextRight = nextRight;
6468 dl 1.52 this.transformer = transformer;
6469     this.basis = basis; this.reducer = reducer;
6470     }
6471 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
6472 dl 1.52 final ObjectByObjectToInt<? super K, ? super V> transformer =
6473     this.transformer;
6474     final IntByIntToInt reducer = this.reducer;
6475     if (transformer == null || reducer == null)
6476 dl 1.61 return abortOnNullFunction();
6477     try {
6478     final int id = this.basis;
6479     for (int c, b = batch(); b > 1 && baseIndex != baseLimit;) {
6480     do {} while (!casPending(c = pending, c+1));
6481     (rights = new MapReduceMappingsToIntTask<K,V>
6482 dl 1.63 (map, this, b >>>= 1, rights, transformer, id, reducer)).fork();
6483 dl 1.61 }
6484     int r = id;
6485     Object v;
6486     while ((v = advance()) != null)
6487     r = reducer.apply(r, transformer.apply((K)nextKey, (V)v));
6488     result = r;
6489     for (MapReduceMappingsToIntTask<K,V> t = this, s;;) {
6490     int c; BulkTask<K,V,?> par;
6491     if ((c = t.pending) == 0) {
6492     for (s = t.rights; s != null; s = t.rights = s.nextRight) {
6493     t.result = reducer.apply(t.result, s.result);
6494     }
6495     if ((par = t.parent) == null ||
6496     !(par instanceof MapReduceMappingsToIntTask)) {
6497     t.quietlyComplete();
6498     break;
6499     }
6500     t = (MapReduceMappingsToIntTask<K,V>)par;
6501     }
6502     else if (t.casPending(c, c - 1))
6503     break;
6504 dl 1.52 }
6505 dl 1.61 } catch (Throwable ex) {
6506     return tryCompleteComputation(ex);
6507 dl 1.52 }
6508 dl 1.61 return false;
6509 dl 1.52 }
6510     public final Integer getRawResult() { return result; }
6511     }
6512    
6513    
6514     // Unsafe mechanics
6515     private static final sun.misc.Unsafe UNSAFE;
6516     private static final long counterOffset;
6517     private static final long sizeCtlOffset;
6518     private static final long ABASE;
6519     private static final int ASHIFT;
6520    
6521     static {
6522     int ss;
6523     try {
6524     UNSAFE = getUnsafe();
6525     Class<?> k = ConcurrentHashMapV8.class;
6526     counterOffset = UNSAFE.objectFieldOffset
6527     (k.getDeclaredField("counter"));
6528     sizeCtlOffset = UNSAFE.objectFieldOffset
6529     (k.getDeclaredField("sizeCtl"));
6530     Class<?> sc = Node[].class;
6531     ABASE = UNSAFE.arrayBaseOffset(sc);
6532     ss = UNSAFE.arrayIndexScale(sc);
6533     } catch (Exception e) {
6534     throw new Error(e);
6535     }
6536     if ((ss & (ss-1)) != 0)
6537     throw new Error("data type scale not a power of two");
6538     ASHIFT = 31 - Integer.numberOfLeadingZeros(ss);
6539     }
6540    
6541     /**
6542     * Returns a sun.misc.Unsafe. Suitable for use in a 3rd party package.
6543     * Replace with a simple call to Unsafe.getUnsafe when integrating
6544     * into a jdk.
6545     *
6546     * @return a sun.misc.Unsafe
6547     */
6548     private static sun.misc.Unsafe getUnsafe() {
6549     try {
6550     return sun.misc.Unsafe.getUnsafe();
6551     } catch (SecurityException se) {
6552     try {
6553     return java.security.AccessController.doPrivileged
6554     (new java.security
6555     .PrivilegedExceptionAction<sun.misc.Unsafe>() {
6556     public sun.misc.Unsafe run() throws Exception {
6557     java.lang.reflect.Field f = sun.misc
6558     .Unsafe.class.getDeclaredField("theUnsafe");
6559     f.setAccessible(true);
6560     return (sun.misc.Unsafe) f.get(null);
6561     }});
6562     } catch (java.security.PrivilegedActionException e) {
6563     throw new RuntimeException("Could not initialize intrinsics",
6564     e.getCause());
6565     }
6566     }
6567     }
6568 dl 1.1 }