ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jsr166e/ConcurrentHashMapV8.java
Revision: 1.64
Committed: Tue Oct 2 05:07:19 2012 UTC (11 years, 7 months ago) by jsr166
Branch: MAIN
Changes since 1.63: +1 -1 lines
Log Message:
whitespace

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     * or the gieven defaultValue if this map contains no mapping for the key.
2510     *
2511     * @param key the key
2512     * @param defaultValue the value to return if this map contains
2513     * no mapping for the given key.
2514     * @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 dl 1.41 * the specified key, or null if the computed value is null.
2654     * @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     * for an element, or null of there is no transformation (in
3675     * which case the action is not applied).
3676     * @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     * for an element, or null of there is no transformation (in
3708     * which case it is not combined).
3709     * @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     * for an element, or null of there is no transformation (in
3792     * which case the action is not applied).
3793     * @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     * for an element, or null of there is no transformation (in
3838     * which case it is not combined).
3839     * @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     * for an element, or null of there is no transformation (in
3922     * which case the action is not applied).
3923     */
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     */
3943     public <U> U searchValues(Fun<? super V, ? extends U> searchFunction) {
3944     return fjp.invoke(ForkJoinTasks.searchValues
3945     (ConcurrentHashMapV8.this, searchFunction));
3946     }
3947    
3948     /**
3949     * Returns the result of accumulating all values using the
3950     * given reducer to combine values, or null if none.
3951     *
3952     * @param reducer a commutative associative combining function
3953     * @return the result of accumulating all values
3954     */
3955     public V reduceValues(BiFun<? super V, ? super V, ? extends V> reducer) {
3956     return fjp.invoke(ForkJoinTasks.reduceValues
3957     (ConcurrentHashMapV8.this, reducer));
3958     }
3959    
3960     /**
3961     * Returns the result of accumulating the given transformation
3962     * of all values using the given reducer to combine values, or
3963     * null if none.
3964     *
3965     * @param transformer a function returning the transformation
3966     * for an element, or null of there is no transformation (in
3967     * which case it is not combined).
3968     * @param reducer a commutative associative combining function
3969     * @return the result of accumulating the given transformation
3970     * of all values
3971     */
3972     public <U> U reduceValues(Fun<? super V, ? extends U> transformer,
3973     BiFun<? super U, ? super U, ? extends U> reducer) {
3974     return fjp.invoke(ForkJoinTasks.reduceValues
3975     (ConcurrentHashMapV8.this, transformer, reducer));
3976     }
3977    
3978     /**
3979     * Returns the result of accumulating the given transformation
3980     * of all values using the given reducer to combine values,
3981     * and the given basis as an identity value.
3982     *
3983     * @param transformer a function returning the transformation
3984     * for an element
3985     * @param basis the identity (initial default value) for the reduction
3986     * @param reducer a commutative associative combining function
3987     * @return the result of accumulating the given transformation
3988     * of all values
3989     */
3990     public double reduceValuesToDouble(ObjectToDouble<? super V> transformer,
3991     double basis,
3992     DoubleByDoubleToDouble reducer) {
3993     return fjp.invoke(ForkJoinTasks.reduceValuesToDouble
3994     (ConcurrentHashMapV8.this, transformer, basis, reducer));
3995     }
3996    
3997     /**
3998     * Returns the result of accumulating the given transformation
3999     * of all values using the given reducer to combine values,
4000     * and the given basis as an identity value.
4001     *
4002     * @param transformer a function returning the transformation
4003     * for an element
4004     * @param basis the identity (initial default value) for the reduction
4005     * @param reducer a commutative associative combining function
4006     * @return the result of accumulating the given transformation
4007     * of all values
4008     */
4009     public long reduceValuesToLong(ObjectToLong<? super V> transformer,
4010     long basis,
4011     LongByLongToLong reducer) {
4012     return fjp.invoke(ForkJoinTasks.reduceValuesToLong
4013     (ConcurrentHashMapV8.this, transformer, basis, reducer));
4014     }
4015    
4016     /**
4017     * Returns the result of accumulating the given transformation
4018     * of all values using the given reducer to combine values,
4019     * and the given basis as an identity value.
4020     *
4021     * @param transformer a function returning the transformation
4022     * for an element
4023     * @param basis the identity (initial default value) for the reduction
4024     * @param reducer a commutative associative combining function
4025     * @return the result of accumulating the given transformation
4026     * of all values
4027     */
4028     public int reduceValuesToInt(ObjectToInt<? super V> transformer,
4029     int basis,
4030     IntByIntToInt reducer) {
4031     return fjp.invoke(ForkJoinTasks.reduceValuesToInt
4032     (ConcurrentHashMapV8.this, transformer, basis, reducer));
4033     }
4034    
4035     /**
4036 jsr166 1.56 * Performs the given action for each entry.
4037 dl 1.52 *
4038     * @param action the action
4039     */
4040 jsr166 1.53 public void forEachEntry(Action<Map.Entry<K,V>> action) {
4041 dl 1.52 fjp.invoke(ForkJoinTasks.forEachEntry
4042     (ConcurrentHashMapV8.this, action));
4043     }
4044    
4045     /**
4046 jsr166 1.56 * Performs the given action for each non-null transformation
4047     * of each entry.
4048 dl 1.52 *
4049     * @param transformer a function returning the transformation
4050     * for an element, or null of there is no transformation (in
4051     * which case the action is not applied).
4052     * @param action the action
4053     */
4054 jsr166 1.53 public <U> void forEachEntry(Fun<Map.Entry<K,V>, ? extends U> transformer,
4055 dl 1.52 Action<U> action) {
4056     fjp.invoke(ForkJoinTasks.forEachEntry
4057     (ConcurrentHashMapV8.this, transformer, action));
4058     }
4059    
4060     /**
4061     * Returns a non-null result from applying the given search
4062 dl 1.59 * function on each entry, or null if none. Upon success,
4063     * further element processing is suppressed and the results of
4064     * any other parallel invocations of the search function are
4065     * ignored.
4066 dl 1.52 *
4067     * @param searchFunction a function returning a non-null
4068     * result on success, else null
4069     * @return a non-null result from applying the given search
4070     * function on each entry, or null if none
4071     */
4072     public <U> U searchEntries(Fun<Map.Entry<K,V>, ? extends U> searchFunction) {
4073     return fjp.invoke(ForkJoinTasks.searchEntries
4074     (ConcurrentHashMapV8.this, searchFunction));
4075     }
4076    
4077     /**
4078     * Returns the result of accumulating all entries using the
4079     * given reducer to combine values, or null if none.
4080     *
4081     * @param reducer a commutative associative combining function
4082     * @return the result of accumulating all entries
4083     */
4084     public Map.Entry<K,V> reduceEntries(BiFun<Map.Entry<K,V>, Map.Entry<K,V>, ? extends Map.Entry<K,V>> reducer) {
4085     return fjp.invoke(ForkJoinTasks.reduceEntries
4086     (ConcurrentHashMapV8.this, reducer));
4087     }
4088    
4089     /**
4090     * Returns the result of accumulating the given transformation
4091     * of all entries using the given reducer to combine values,
4092     * or null if none.
4093     *
4094     * @param transformer a function returning the transformation
4095     * for an element, or null of there is no transformation (in
4096     * which case it is not combined).
4097     * @param reducer a commutative associative combining function
4098     * @return the result of accumulating the given transformation
4099     * of all entries
4100     */
4101     public <U> U reduceEntries(Fun<Map.Entry<K,V>, ? extends U> transformer,
4102     BiFun<? super U, ? super U, ? extends U> reducer) {
4103     return fjp.invoke(ForkJoinTasks.reduceEntries
4104     (ConcurrentHashMapV8.this, transformer, reducer));
4105     }
4106    
4107     /**
4108     * Returns the result of accumulating the given transformation
4109     * of all entries using the given reducer to combine values,
4110     * and the given basis as an identity value.
4111     *
4112     * @param transformer a function returning the transformation
4113     * for an element
4114     * @param basis the identity (initial default value) for the reduction
4115     * @param reducer a commutative associative combining function
4116     * @return the result of accumulating the given transformation
4117     * of all entries
4118     */
4119     public double reduceEntriesToDouble(ObjectToDouble<Map.Entry<K,V>> transformer,
4120     double basis,
4121     DoubleByDoubleToDouble reducer) {
4122     return fjp.invoke(ForkJoinTasks.reduceEntriesToDouble
4123     (ConcurrentHashMapV8.this, transformer, basis, reducer));
4124     }
4125    
4126     /**
4127     * Returns the result of accumulating the given transformation
4128     * of all entries using the given reducer to combine values,
4129     * and the given basis as an identity value.
4130     *
4131     * @param transformer a function returning the transformation
4132     * for an element
4133     * @param basis the identity (initial default value) for the reduction
4134     * @param reducer a commutative associative combining function
4135     * @return the result of accumulating the given transformation
4136     * of all entries
4137     */
4138     public long reduceEntriesToLong(ObjectToLong<Map.Entry<K,V>> transformer,
4139     long basis,
4140     LongByLongToLong reducer) {
4141     return fjp.invoke(ForkJoinTasks.reduceEntriesToLong
4142     (ConcurrentHashMapV8.this, transformer, basis, reducer));
4143     }
4144    
4145     /**
4146     * Returns the result of accumulating the given transformation
4147     * of all entries using the given reducer to combine values,
4148     * and the given basis as an identity value.
4149     *
4150     * @param transformer a function returning the transformation
4151     * for an element
4152     * @param basis the identity (initial default value) for the reduction
4153     * @param reducer a commutative associative combining function
4154     * @return the result of accumulating the given transformation
4155     * of all entries
4156     */
4157     public int reduceEntriesToInt(ObjectToInt<Map.Entry<K,V>> transformer,
4158     int basis,
4159     IntByIntToInt reducer) {
4160     return fjp.invoke(ForkJoinTasks.reduceEntriesToInt
4161     (ConcurrentHashMapV8.this, transformer, basis, reducer));
4162     }
4163     }
4164    
4165     // ---------------------------------------------------------------------
4166    
4167     /**
4168     * Predefined tasks for performing bulk parallel operations on
4169     * ConcurrentHashMaps. These tasks follow the forms and rules used
4170     * in class {@link Parallel}. Each method has the same name, but
4171     * returns a task rather than invoking it. These methods may be
4172     * useful in custom applications such as submitting a task without
4173     * waiting for completion, or combining with other tasks.
4174     */
4175     public static class ForkJoinTasks {
4176     private ForkJoinTasks() {}
4177    
4178     /**
4179     * Returns a task that when invoked, performs the given
4180     * action for each (key, value)
4181     *
4182     * @param map the map
4183     * @param action the action
4184     * @return the task
4185     */
4186 jsr166 1.53 public static <K,V> ForkJoinTask<Void> forEach
4187 dl 1.52 (ConcurrentHashMapV8<K,V> map,
4188     BiAction<K,V> action) {
4189     if (action == null) throw new NullPointerException();
4190 dl 1.63 return new ForEachMappingTask<K,V>(map, null, -1, action);
4191 dl 1.52 }
4192    
4193     /**
4194     * Returns a task that when invoked, performs the given
4195     * action for each non-null transformation of each (key, value)
4196     *
4197     * @param map the map
4198     * @param transformer a function returning the transformation
4199     * for an element, or null of there is no transformation (in
4200     * which case the action is not applied).
4201     * @param action the action
4202     * @return the task
4203     */
4204 jsr166 1.53 public static <K,V,U> ForkJoinTask<Void> forEach
4205 dl 1.52 (ConcurrentHashMapV8<K,V> map,
4206     BiFun<? super K, ? super V, ? extends U> transformer,
4207     Action<U> action) {
4208     if (transformer == null || action == null)
4209     throw new NullPointerException();
4210     return new ForEachTransformedMappingTask<K,V,U>
4211 dl 1.63 (map, null, -1, transformer, action);
4212 dl 1.52 }
4213    
4214     /**
4215 dl 1.59 * Returns a task that when invoked, returns a non-null result
4216     * from applying the given search function on each (key,
4217     * value), or null if none. Upon success, further element
4218     * processing is suppressed and the results of any other
4219     * parallel invocations of the search function are ignored.
4220 dl 1.52 *
4221     * @param map the map
4222     * @param searchFunction a function returning a non-null
4223     * result on success, else null
4224     * @return the task
4225     */
4226     public static <K,V,U> ForkJoinTask<U> search
4227     (ConcurrentHashMapV8<K,V> map,
4228     BiFun<? super K, ? super V, ? extends U> searchFunction) {
4229     if (searchFunction == null) throw new NullPointerException();
4230     return new SearchMappingsTask<K,V,U>
4231 dl 1.63 (map, null, -1, searchFunction,
4232 dl 1.52 new AtomicReference<U>());
4233     }
4234    
4235     /**
4236     * Returns a task that when invoked, returns the result of
4237     * accumulating the given transformation of all (key, value) pairs
4238     * using the given reducer to combine values, or null if none.
4239     *
4240     * @param map the map
4241     * @param transformer a function returning the transformation
4242     * for an element, or null of there is no transformation (in
4243     * which case it is not combined).
4244     * @param reducer a commutative associative combining function
4245     * @return the task
4246     */
4247     public static <K,V,U> ForkJoinTask<U> reduce
4248     (ConcurrentHashMapV8<K,V> map,
4249     BiFun<? super K, ? super V, ? extends U> transformer,
4250     BiFun<? super U, ? super U, ? extends U> reducer) {
4251     if (transformer == null || reducer == null)
4252     throw new NullPointerException();
4253     return new MapReduceMappingsTask<K,V,U>
4254 dl 1.63 (map, null, -1, null, transformer, reducer);
4255 dl 1.52 }
4256    
4257     /**
4258     * Returns a task that when invoked, returns the result of
4259     * accumulating the given transformation of all (key, value) pairs
4260     * using the given reducer to combine values, and the given
4261     * basis as an identity value.
4262     *
4263     * @param map the map
4264     * @param transformer a function returning the transformation
4265     * for an element
4266     * @param basis the identity (initial default value) for the reduction
4267     * @param reducer a commutative associative combining function
4268     * @return the task
4269     */
4270     public static <K,V> ForkJoinTask<Double> reduceToDouble
4271     (ConcurrentHashMapV8<K,V> map,
4272     ObjectByObjectToDouble<? super K, ? super V> transformer,
4273     double basis,
4274     DoubleByDoubleToDouble reducer) {
4275     if (transformer == null || reducer == null)
4276     throw new NullPointerException();
4277     return new MapReduceMappingsToDoubleTask<K,V>
4278 dl 1.63 (map, null, -1, null, transformer, basis, reducer);
4279 dl 1.52 }
4280    
4281     /**
4282     * Returns a task that when invoked, returns the result of
4283     * accumulating the given transformation of all (key, value) pairs
4284     * using the given reducer to combine values, and the given
4285     * basis as an identity value.
4286     *
4287     * @param map the map
4288     * @param transformer a function returning the transformation
4289     * for an element
4290     * @param basis the identity (initial default value) for the reduction
4291     * @param reducer a commutative associative combining function
4292     * @return the task
4293     */
4294     public static <K,V> ForkJoinTask<Long> reduceToLong
4295     (ConcurrentHashMapV8<K,V> map,
4296     ObjectByObjectToLong<? super K, ? super V> transformer,
4297     long basis,
4298     LongByLongToLong reducer) {
4299     if (transformer == null || reducer == null)
4300     throw new NullPointerException();
4301     return new MapReduceMappingsToLongTask<K,V>
4302 dl 1.63 (map, null, -1, null, transformer, basis, reducer);
4303 dl 1.52 }
4304    
4305     /**
4306     * Returns a task that when invoked, returns the result of
4307     * accumulating the given transformation of all (key, value) pairs
4308     * using the given reducer to combine values, and the given
4309     * basis as an identity value.
4310     *
4311     * @param transformer a function returning the transformation
4312     * for an element
4313     * @param basis the identity (initial default value) for the reduction
4314     * @param reducer a commutative associative combining function
4315     * @return the task
4316     */
4317     public static <K,V> ForkJoinTask<Integer> reduceToInt
4318     (ConcurrentHashMapV8<K,V> map,
4319     ObjectByObjectToInt<? super K, ? super V> transformer,
4320     int basis,
4321     IntByIntToInt reducer) {
4322     if (transformer == null || reducer == null)
4323     throw new NullPointerException();
4324     return new MapReduceMappingsToIntTask<K,V>
4325 dl 1.63 (map, null, -1, null, transformer, basis, reducer);
4326 dl 1.52 }
4327    
4328     /**
4329     * Returns a task that when invoked, performs the given action
4330 jsr166 1.56 * for each key.
4331 dl 1.52 *
4332     * @param map the map
4333     * @param action the action
4334     * @return the task
4335     */
4336 jsr166 1.53 public static <K,V> ForkJoinTask<Void> forEachKey
4337 dl 1.52 (ConcurrentHashMapV8<K,V> map,
4338     Action<K> action) {
4339     if (action == null) throw new NullPointerException();
4340 dl 1.63 return new ForEachKeyTask<K,V>(map, null, -1, action);
4341 dl 1.52 }
4342    
4343     /**
4344     * Returns a task that when invoked, performs the given action
4345 jsr166 1.56 * for each non-null transformation of each key.
4346 dl 1.52 *
4347     * @param map the map
4348     * @param transformer a function returning the transformation
4349     * for an element, or null of there is no transformation (in
4350     * which case the action is not applied).
4351     * @param action the action
4352     * @return the task
4353     */
4354 jsr166 1.53 public static <K,V,U> ForkJoinTask<Void> forEachKey
4355 dl 1.52 (ConcurrentHashMapV8<K,V> map,
4356     Fun<? super K, ? extends U> transformer,
4357     Action<U> action) {
4358     if (transformer == null || action == null)
4359     throw new NullPointerException();
4360     return new ForEachTransformedKeyTask<K,V,U>
4361 dl 1.63 (map, null, -1, transformer, action);
4362 dl 1.52 }
4363    
4364     /**
4365     * Returns a task that when invoked, returns a non-null result
4366     * from applying the given search function on each key, or
4367 dl 1.59 * null if none. Upon success, further element processing is
4368     * suppressed and the results of any other parallel
4369     * invocations of the search function are ignored.
4370 dl 1.52 *
4371     * @param map the map
4372     * @param searchFunction a function returning a non-null
4373     * result on success, else null
4374     * @return the task
4375     */
4376     public static <K,V,U> ForkJoinTask<U> searchKeys
4377     (ConcurrentHashMapV8<K,V> map,
4378     Fun<? super K, ? extends U> searchFunction) {
4379     if (searchFunction == null) throw new NullPointerException();
4380     return new SearchKeysTask<K,V,U>
4381 dl 1.63 (map, null, -1, searchFunction,
4382 dl 1.52 new AtomicReference<U>());
4383     }
4384    
4385     /**
4386     * Returns a task that when invoked, returns the result of
4387     * accumulating all keys using the given reducer to combine
4388     * values, or null if none.
4389     *
4390     * @param map the map
4391     * @param reducer a commutative associative combining function
4392     * @return the task
4393     */
4394     public static <K,V> ForkJoinTask<K> reduceKeys
4395     (ConcurrentHashMapV8<K,V> map,
4396     BiFun<? super K, ? super K, ? extends K> reducer) {
4397     if (reducer == null) throw new NullPointerException();
4398     return new ReduceKeysTask<K,V>
4399 dl 1.63 (map, null, -1, null, reducer);
4400 dl 1.52 }
4401 jsr166 1.58
4402 dl 1.52 /**
4403     * Returns a task that when invoked, returns the result of
4404     * accumulating the given transformation of all keys using the given
4405     * reducer to combine values, or null if none.
4406     *
4407     * @param map the map
4408     * @param transformer a function returning the transformation
4409     * for an element, or null of there is no transformation (in
4410     * which case it is not combined).
4411     * @param reducer a commutative associative combining function
4412     * @return the task
4413     */
4414     public static <K,V,U> ForkJoinTask<U> reduceKeys
4415     (ConcurrentHashMapV8<K,V> map,
4416     Fun<? super K, ? extends U> transformer,
4417     BiFun<? super U, ? super U, ? extends U> reducer) {
4418     if (transformer == null || reducer == null)
4419     throw new NullPointerException();
4420     return new MapReduceKeysTask<K,V,U>
4421 dl 1.63 (map, null, -1, null, transformer, reducer);
4422 dl 1.52 }
4423    
4424     /**
4425     * Returns a task that when invoked, returns the result of
4426     * accumulating the given transformation of all keys using the given
4427     * reducer to combine values, and the given basis as an
4428     * identity value.
4429     *
4430     * @param map the map
4431     * @param transformer a function returning the transformation
4432     * for an element
4433     * @param basis the identity (initial default value) for the reduction
4434     * @param reducer a commutative associative combining function
4435     * @return the task
4436     */
4437     public static <K,V> ForkJoinTask<Double> reduceKeysToDouble
4438     (ConcurrentHashMapV8<K,V> map,
4439     ObjectToDouble<? super K> transformer,
4440     double basis,
4441     DoubleByDoubleToDouble reducer) {
4442     if (transformer == null || reducer == null)
4443     throw new NullPointerException();
4444     return new MapReduceKeysToDoubleTask<K,V>
4445 dl 1.63 (map, null, -1, null, transformer, basis, reducer);
4446 dl 1.52 }
4447    
4448     /**
4449     * Returns a task that when invoked, returns the result of
4450     * accumulating the given transformation of all keys using the given
4451     * reducer to combine values, and the given basis as an
4452     * identity value.
4453     *
4454     * @param map the map
4455     * @param transformer a function returning the transformation
4456     * for an element
4457     * @param basis the identity (initial default value) for the reduction
4458     * @param reducer a commutative associative combining function
4459     * @return the task
4460     */
4461     public static <K,V> ForkJoinTask<Long> reduceKeysToLong
4462     (ConcurrentHashMapV8<K,V> map,
4463     ObjectToLong<? super K> transformer,
4464     long basis,
4465     LongByLongToLong reducer) {
4466     if (transformer == null || reducer == null)
4467     throw new NullPointerException();
4468     return new MapReduceKeysToLongTask<K,V>
4469 dl 1.63 (map, null, -1, null, transformer, basis, reducer);
4470 dl 1.52 }
4471    
4472     /**
4473     * Returns a task that when invoked, returns the result of
4474     * accumulating the given transformation of all keys using the given
4475     * reducer to combine values, and the given basis as an
4476     * identity value.
4477     *
4478     * @param map the map
4479     * @param transformer a function returning the transformation
4480     * for an element
4481     * @param basis the identity (initial default value) for the reduction
4482     * @param reducer a commutative associative combining function
4483     * @return the task
4484     */
4485     public static <K,V> ForkJoinTask<Integer> reduceKeysToInt
4486     (ConcurrentHashMapV8<K,V> map,
4487     ObjectToInt<? super K> transformer,
4488     int basis,
4489     IntByIntToInt reducer) {
4490     if (transformer == null || reducer == null)
4491     throw new NullPointerException();
4492     return new MapReduceKeysToIntTask<K,V>
4493 dl 1.63 (map, null, -1, null, transformer, basis, reducer);
4494 dl 1.52 }
4495    
4496     /**
4497     * Returns a task that when invoked, performs the given action
4498 jsr166 1.56 * for each value.
4499 dl 1.52 *
4500     * @param map the map
4501     * @param action the action
4502     */
4503 jsr166 1.53 public static <K,V> ForkJoinTask<Void> forEachValue
4504 dl 1.52 (ConcurrentHashMapV8<K,V> map,
4505     Action<V> action) {
4506     if (action == null) throw new NullPointerException();
4507 dl 1.63 return new ForEachValueTask<K,V>(map, null, -1, action);
4508 dl 1.52 }
4509    
4510     /**
4511     * Returns a task that when invoked, performs the given action
4512 jsr166 1.56 * for each non-null transformation of each value.
4513 dl 1.52 *
4514     * @param map the map
4515     * @param transformer a function returning the transformation
4516     * for an element, or null of there is no transformation (in
4517     * which case the action is not applied).
4518     * @param action the action
4519     */
4520 jsr166 1.53 public static <K,V,U> ForkJoinTask<Void> forEachValue
4521 dl 1.52 (ConcurrentHashMapV8<K,V> map,
4522     Fun<? super V, ? extends U> transformer,
4523     Action<U> action) {
4524     if (transformer == null || action == null)
4525     throw new NullPointerException();
4526     return new ForEachTransformedValueTask<K,V,U>
4527 dl 1.63 (map, null, -1, transformer, action);
4528 dl 1.52 }
4529    
4530     /**
4531     * Returns a task that when invoked, returns a non-null result
4532     * from applying the given search function on each value, or
4533 dl 1.59 * null if none. Upon success, further element processing is
4534     * suppressed and the results of any other parallel
4535     * invocations of the search function are ignored.
4536 dl 1.52 *
4537     * @param map the map
4538     * @param searchFunction a function returning a non-null
4539     * result on success, else null
4540     * @return the task
4541     *
4542     */
4543     public static <K,V,U> ForkJoinTask<U> searchValues
4544     (ConcurrentHashMapV8<K,V> map,
4545     Fun<? super V, ? extends U> searchFunction) {
4546     if (searchFunction == null) throw new NullPointerException();
4547     return new SearchValuesTask<K,V,U>
4548 dl 1.63 (map, null, -1, searchFunction,
4549 dl 1.52 new AtomicReference<U>());
4550     }
4551    
4552     /**
4553     * Returns a task that when invoked, returns the result of
4554     * accumulating all values using the given reducer to combine
4555     * values, or null if none.
4556     *
4557     * @param map the map
4558     * @param reducer a commutative associative combining function
4559     * @return the task
4560     */
4561     public static <K,V> ForkJoinTask<V> reduceValues
4562     (ConcurrentHashMapV8<K,V> map,
4563     BiFun<? super V, ? super V, ? extends V> reducer) {
4564     if (reducer == null) throw new NullPointerException();
4565     return new ReduceValuesTask<K,V>
4566 dl 1.63 (map, null, -1, null, reducer);
4567 dl 1.52 }
4568    
4569     /**
4570     * Returns a task that when invoked, returns the result of
4571     * accumulating the given transformation of all values using the
4572     * given reducer to combine values, or null if none.
4573     *
4574     * @param map the map
4575     * @param transformer a function returning the transformation
4576     * for an element, or null of there is no transformation (in
4577     * which case it is not combined).
4578     * @param reducer a commutative associative combining function
4579     * @return the task
4580     */
4581     public static <K,V,U> ForkJoinTask<U> reduceValues
4582     (ConcurrentHashMapV8<K,V> map,
4583     Fun<? super V, ? extends U> transformer,
4584     BiFun<? super U, ? super U, ? extends U> reducer) {
4585     if (transformer == null || reducer == null)
4586     throw new NullPointerException();
4587     return new MapReduceValuesTask<K,V,U>
4588 dl 1.63 (map, null, -1, null, transformer, reducer);
4589 dl 1.52 }
4590    
4591     /**
4592     * Returns a task that when invoked, returns the result of
4593     * accumulating the given transformation of all values using the
4594     * given reducer to combine values, and the given basis as an
4595     * identity value.
4596     *
4597     * @param map the map
4598     * @param transformer a function returning the transformation
4599     * for an element
4600     * @param basis the identity (initial default value) for the reduction
4601     * @param reducer a commutative associative combining function
4602     * @return the task
4603     */
4604     public static <K,V> ForkJoinTask<Double> reduceValuesToDouble
4605     (ConcurrentHashMapV8<K,V> map,
4606     ObjectToDouble<? super V> transformer,
4607     double basis,
4608     DoubleByDoubleToDouble reducer) {
4609     if (transformer == null || reducer == null)
4610     throw new NullPointerException();
4611     return new MapReduceValuesToDoubleTask<K,V>
4612 dl 1.63 (map, null, -1, null, transformer, basis, reducer);
4613 dl 1.52 }
4614    
4615     /**
4616     * Returns a task that when invoked, returns the result of
4617     * accumulating the given transformation of all values using the
4618     * given reducer to combine values, and the given basis as an
4619     * identity value.
4620     *
4621     * @param map the map
4622     * @param transformer a function returning the transformation
4623     * for an element
4624     * @param basis the identity (initial default value) for the reduction
4625     * @param reducer a commutative associative combining function
4626     * @return the task
4627     */
4628     public static <K,V> ForkJoinTask<Long> reduceValuesToLong
4629     (ConcurrentHashMapV8<K,V> map,
4630     ObjectToLong<? super V> transformer,
4631     long basis,
4632     LongByLongToLong reducer) {
4633     if (transformer == null || reducer == null)
4634     throw new NullPointerException();
4635     return new MapReduceValuesToLongTask<K,V>
4636 dl 1.63 (map, null, -1, null, transformer, basis, reducer);
4637 dl 1.52 }
4638    
4639     /**
4640     * Returns a task that when invoked, returns the result of
4641     * accumulating the given transformation of all values using the
4642     * given reducer to combine values, and the given basis as an
4643     * identity value.
4644     *
4645     * @param map the map
4646     * @param transformer a function returning the transformation
4647     * for an element
4648     * @param basis the identity (initial default value) for the reduction
4649     * @param reducer a commutative associative combining function
4650     * @return the task
4651     */
4652     public static <K,V> ForkJoinTask<Integer> reduceValuesToInt
4653     (ConcurrentHashMapV8<K,V> map,
4654     ObjectToInt<? super V> transformer,
4655     int basis,
4656     IntByIntToInt reducer) {
4657     if (transformer == null || reducer == null)
4658     throw new NullPointerException();
4659     return new MapReduceValuesToIntTask<K,V>
4660 dl 1.63 (map, null, -1, null, transformer, basis, reducer);
4661 dl 1.52 }
4662    
4663     /**
4664     * Returns a task that when invoked, perform the given action
4665 jsr166 1.56 * for each entry.
4666 dl 1.52 *
4667     * @param map the map
4668     * @param action the action
4669     */
4670 jsr166 1.53 public static <K,V> ForkJoinTask<Void> forEachEntry
4671 dl 1.52 (ConcurrentHashMapV8<K,V> map,
4672     Action<Map.Entry<K,V>> action) {
4673     if (action == null) throw new NullPointerException();
4674 dl 1.63 return new ForEachEntryTask<K,V>(map, null, -1, action);
4675 dl 1.52 }
4676    
4677     /**
4678     * Returns a task that when invoked, perform the given action
4679 jsr166 1.56 * for each non-null transformation of each entry.
4680 dl 1.52 *
4681     * @param map the map
4682     * @param transformer a function returning the transformation
4683     * for an element, or null of there is no transformation (in
4684     * which case the action is not applied).
4685     * @param action the action
4686     */
4687 jsr166 1.53 public static <K,V,U> ForkJoinTask<Void> forEachEntry
4688 dl 1.52 (ConcurrentHashMapV8<K,V> map,
4689     Fun<Map.Entry<K,V>, ? extends U> transformer,
4690     Action<U> action) {
4691     if (transformer == null || action == null)
4692     throw new NullPointerException();
4693     return new ForEachTransformedEntryTask<K,V,U>
4694 dl 1.63 (map, null, -1, transformer, action);
4695 dl 1.52 }
4696    
4697     /**
4698     * Returns a task that when invoked, returns a non-null result
4699     * from applying the given search function on each entry, or
4700 dl 1.59 * null if none. Upon success, further element processing is
4701     * suppressed and the results of any other parallel
4702     * invocations of the search function are ignored.
4703 dl 1.52 *
4704     * @param map the map
4705     * @param searchFunction a function returning a non-null
4706     * result on success, else null
4707     * @return the task
4708     *
4709     */
4710     public static <K,V,U> ForkJoinTask<U> searchEntries
4711     (ConcurrentHashMapV8<K,V> map,
4712     Fun<Map.Entry<K,V>, ? extends U> searchFunction) {
4713     if (searchFunction == null) throw new NullPointerException();
4714     return new SearchEntriesTask<K,V,U>
4715 dl 1.63 (map, null, -1, searchFunction,
4716 dl 1.52 new AtomicReference<U>());
4717     }
4718    
4719     /**
4720     * Returns a task that when invoked, returns the result of
4721     * accumulating all entries using the given reducer to combine
4722     * values, or null if none.
4723     *
4724     * @param map the map
4725     * @param reducer a commutative associative combining function
4726     * @return the task
4727     */
4728     public static <K,V> ForkJoinTask<Map.Entry<K,V>> reduceEntries
4729     (ConcurrentHashMapV8<K,V> map,
4730     BiFun<Map.Entry<K,V>, Map.Entry<K,V>, ? extends Map.Entry<K,V>> reducer) {
4731     if (reducer == null) throw new NullPointerException();
4732     return new ReduceEntriesTask<K,V>
4733 dl 1.63 (map, null, -1, null, reducer);
4734 dl 1.52 }
4735    
4736     /**
4737     * Returns a task that when invoked, returns the result of
4738     * accumulating the given transformation of all entries using the
4739     * given reducer to combine values, or null if none.
4740     *
4741     * @param map the map
4742     * @param transformer a function returning the transformation
4743     * for an element, or null of there is no transformation (in
4744     * which case it is not combined).
4745     * @param reducer a commutative associative combining function
4746     * @return the task
4747     */
4748     public static <K,V,U> ForkJoinTask<U> reduceEntries
4749     (ConcurrentHashMapV8<K,V> map,
4750     Fun<Map.Entry<K,V>, ? extends U> transformer,
4751     BiFun<? super U, ? super U, ? extends U> reducer) {
4752     if (transformer == null || reducer == null)
4753     throw new NullPointerException();
4754     return new MapReduceEntriesTask<K,V,U>
4755 dl 1.63 (map, null, -1, null, transformer, reducer);
4756 dl 1.52 }
4757    
4758     /**
4759     * Returns a task that when invoked, returns the result of
4760     * accumulating the given transformation of all entries using the
4761     * given reducer to combine values, and the given basis as an
4762     * identity value.
4763     *
4764     * @param map the map
4765     * @param transformer a function returning the transformation
4766     * for an element
4767     * @param basis the identity (initial default value) for the reduction
4768     * @param reducer a commutative associative combining function
4769     * @return the task
4770     */
4771     public static <K,V> ForkJoinTask<Double> reduceEntriesToDouble
4772     (ConcurrentHashMapV8<K,V> map,
4773     ObjectToDouble<Map.Entry<K,V>> transformer,
4774     double basis,
4775     DoubleByDoubleToDouble reducer) {
4776     if (transformer == null || reducer == null)
4777     throw new NullPointerException();
4778     return new MapReduceEntriesToDoubleTask<K,V>
4779 dl 1.63 (map, null, -1, null, transformer, basis, reducer);
4780 dl 1.52 }
4781    
4782     /**
4783     * Returns a task that when invoked, returns the result of
4784     * accumulating the given transformation of all entries using the
4785     * given reducer to combine values, and the given basis as an
4786     * identity value.
4787     *
4788     * @param map the map
4789     * @param transformer a function returning the transformation
4790     * for an element
4791     * @param basis the identity (initial default value) for the reduction
4792     * @param reducer a commutative associative combining function
4793     * @return the task
4794     */
4795     public static <K,V> ForkJoinTask<Long> reduceEntriesToLong
4796     (ConcurrentHashMapV8<K,V> map,
4797     ObjectToLong<Map.Entry<K,V>> transformer,
4798     long basis,
4799     LongByLongToLong reducer) {
4800     if (transformer == null || reducer == null)
4801     throw new NullPointerException();
4802     return new MapReduceEntriesToLongTask<K,V>
4803 dl 1.63 (map, null, -1, null, transformer, basis, reducer);
4804 dl 1.52 }
4805    
4806     /**
4807     * Returns a task that when invoked, returns the result of
4808     * accumulating the given transformation of all entries using the
4809     * given reducer to combine values, and the given basis as an
4810     * identity value.
4811     *
4812     * @param map the map
4813     * @param transformer a function returning the transformation
4814     * for an element
4815     * @param basis the identity (initial default value) for the reduction
4816     * @param reducer a commutative associative combining function
4817     * @return the task
4818     */
4819     public static <K,V> ForkJoinTask<Integer> reduceEntriesToInt
4820     (ConcurrentHashMapV8<K,V> map,
4821     ObjectToInt<Map.Entry<K,V>> transformer,
4822     int basis,
4823     IntByIntToInt reducer) {
4824     if (transformer == null || reducer == null)
4825     throw new NullPointerException();
4826     return new MapReduceEntriesToIntTask<K,V>
4827 dl 1.63 (map, null, -1, null, transformer, basis, reducer);
4828 dl 1.52 }
4829     }
4830    
4831     // -------------------------------------------------------
4832    
4833     /**
4834     * Base for FJ tasks for bulk operations. This adds a variant of
4835 jsr166 1.55 * CountedCompleters and some split and merge bookkeeping to
4836 dl 1.52 * iterator functionality. The forEach and reduce methods are
4837     * similar to those illustrated in CountedCompleter documentation,
4838     * except that bottom-up reduction completions perform them within
4839     * their compute methods. The search methods are like forEach
4840     * except they continually poll for success and exit early. Also,
4841     * exceptions are handled in a simpler manner, by just trying to
4842     * complete root task exceptionally.
4843     */
4844 dl 1.61 @SuppressWarnings("serial") static abstract class BulkTask<K,V,R> extends Traverser<K,V,R> {
4845 dl 1.52 final BulkTask<K,V,?> parent; // completion target
4846 dl 1.63 int batch; // split control; -1 for unknown
4847 dl 1.52 int pending; // completion control
4848    
4849 jsr166 1.64 BulkTask(ConcurrentHashMapV8<K,V> map, BulkTask<K,V,?> parent,
4850 dl 1.63 int batch) {
4851 dl 1.52 super(map);
4852     this.parent = parent;
4853     this.batch = batch;
4854 dl 1.63 if (parent != null && map != null) { // split parent
4855     Node[] t;
4856     if ((t = parent.tab) == null &&
4857     (t = parent.tab = map.table) != null)
4858     parent.baseLimit = parent.baseSize = t.length;
4859     this.tab = t;
4860     this.baseSize = parent.baseSize;
4861     int hi = this.baseLimit = parent.baseLimit;
4862     parent.baseLimit = this.index = this.baseIndex =
4863     (hi + parent.baseIndex + 1) >>> 1;
4864     }
4865 dl 1.52 }
4866    
4867     // FJ methods
4868    
4869     /**
4870 jsr166 1.56 * Propagates completion. Note that all reduce actions
4871 dl 1.52 * bypass this method to combine while completing.
4872     */
4873     final void tryComplete() {
4874     BulkTask<K,V,?> a = this, s = a;
4875     for (int c;;) {
4876     if ((c = a.pending) == 0) {
4877     if ((a = (s = a).parent) == null) {
4878     s.quietlyComplete();
4879     break;
4880     }
4881     }
4882     else if (U.compareAndSwapInt(a, PENDING, c, c - 1))
4883     break;
4884     }
4885     }
4886    
4887     /**
4888 dl 1.61 * Forces root task to complete.
4889     * @param ex if null, complete normally, else exceptionally
4890     * @return false to simplify use
4891 dl 1.52 */
4892 dl 1.61 final boolean tryCompleteComputation(Throwable ex) {
4893 dl 1.52 for (BulkTask<K,V,?> a = this;;) {
4894     BulkTask<K,V,?> p = a.parent;
4895     if (p == null) {
4896 dl 1.61 if (ex != null)
4897     a.completeExceptionally(ex);
4898     else
4899     a.quietlyComplete();
4900     return false;
4901 dl 1.52 }
4902     a = p;
4903     }
4904     }
4905    
4906 dl 1.61 /**
4907     * Version of tryCompleteComputation for function screening checks
4908     */
4909     final boolean abortOnNullFunction() {
4910     return tryCompleteComputation(new Error("Unexpected null function"));
4911 dl 1.52 }
4912    
4913     // utilities
4914    
4915     /** CompareAndSet pending count */
4916     final boolean casPending(int cmp, int val) {
4917     return U.compareAndSwapInt(this, PENDING, cmp, val);
4918     }
4919    
4920     /**
4921 jsr166 1.56 * Returns approx exp2 of the number of times (minus one) to
4922 dl 1.52 * split task by two before executing leaf action. This value
4923     * is faster to compute and more convenient to use as a guide
4924     * to splitting than is the depth, since it is used while
4925     * dividing by two anyway.
4926     */
4927     final int batch() {
4928 dl 1.63 ConcurrentHashMapV8<K, V> m; int b; Node[] t;
4929     if ((b = batch) < 0 && (m = map) != null) { // force initialization
4930     if ((t = tab) == null && (t = tab = m.table) != null)
4931     baseLimit = baseSize = t.length;
4932     if (t != null) {
4933     long n = m.counter.sum();
4934     int sp = getPool().getParallelism() << 3; // slack of 8
4935     b = batch = (n <= 0L) ? 0 : (n < (long)sp) ? (int)n : sp;
4936     }
4937 dl 1.52 }
4938     return b;
4939     }
4940    
4941     /**
4942 jsr166 1.56 * Returns exportable snapshot entry.
4943 dl 1.52 */
4944     static <K,V> AbstractMap.SimpleEntry<K,V> entryFor(K k, V v) {
4945 dl 1.59 return new AbstractMap.SimpleEntry<K,V>(k, v);
4946 dl 1.52 }
4947    
4948     // Unsafe mechanics
4949     private static final sun.misc.Unsafe U;
4950     private static final long PENDING;
4951     static {
4952     try {
4953 dl 1.59 U = getUnsafe();
4954 dl 1.52 PENDING = U.objectFieldOffset
4955     (BulkTask.class.getDeclaredField("pending"));
4956     } catch (Exception e) {
4957     throw new Error(e);
4958     }
4959     }
4960     }
4961    
4962     /*
4963     * Task classes. Coded in a regular but ugly format/style to
4964     * simplify checks that each variant differs in the right way from
4965     * others.
4966     */
4967    
4968 dl 1.61 @SuppressWarnings("serial") static final class ForEachKeyTask<K,V>
4969 dl 1.52 extends BulkTask<K,V,Void> {
4970     final Action<K> action;
4971     ForEachKeyTask
4972 dl 1.63 (ConcurrentHashMapV8<K,V> m, BulkTask<K,V,?> p, int b,
4973 dl 1.52 Action<K> action) {
4974 dl 1.63 super(m, p, b);
4975 dl 1.52 this.action = action;
4976     }
4977 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
4978 dl 1.52 final Action<K> action = this.action;
4979     if (action == null)
4980 dl 1.61 return abortOnNullFunction();
4981     try {
4982     int b = batch(), c;
4983     while (b > 1 && baseIndex != baseLimit) {
4984     do {} while (!casPending(c = pending, c+1));
4985 dl 1.63 new ForEachKeyTask<K,V>(map, this, b >>>= 1, action).fork();
4986 dl 1.61 }
4987     while (advance() != null)
4988     action.apply((K)nextKey);
4989     tryComplete();
4990     } catch (Throwable ex) {
4991     return tryCompleteComputation(ex);
4992 dl 1.52 }
4993 dl 1.61 return false;
4994 dl 1.52 }
4995     }
4996    
4997 dl 1.61 @SuppressWarnings("serial") static final class ForEachValueTask<K,V>
4998 dl 1.52 extends BulkTask<K,V,Void> {
4999     final Action<V> action;
5000     ForEachValueTask
5001 dl 1.63 (ConcurrentHashMapV8<K,V> m, BulkTask<K,V,?> p, int b,
5002 dl 1.52 Action<V> action) {
5003 dl 1.63 super(m, p, b);
5004 dl 1.52 this.action = action;
5005     }
5006 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
5007 dl 1.52 final Action<V> action = this.action;
5008     if (action == null)
5009 dl 1.61 return abortOnNullFunction();
5010     try {
5011     int b = batch(), c;
5012     while (b > 1 && baseIndex != baseLimit) {
5013     do {} while (!casPending(c = pending, c+1));
5014 dl 1.63 new ForEachValueTask<K,V>(map, this, b >>>= 1, action).fork();
5015 dl 1.61 }
5016     Object v;
5017     while ((v = advance()) != null)
5018     action.apply((V)v);
5019     tryComplete();
5020     } catch (Throwable ex) {
5021     return tryCompleteComputation(ex);
5022 dl 1.52 }
5023 dl 1.61 return false;
5024 dl 1.52 }
5025     }
5026    
5027 dl 1.61 @SuppressWarnings("serial") static final class ForEachEntryTask<K,V>
5028 dl 1.52 extends BulkTask<K,V,Void> {
5029     final Action<Entry<K,V>> action;
5030     ForEachEntryTask
5031 dl 1.63 (ConcurrentHashMapV8<K,V> m, BulkTask<K,V,?> p, int b,
5032 dl 1.52 Action<Entry<K,V>> action) {
5033 dl 1.63 super(m, p, b);
5034 dl 1.52 this.action = action;
5035     }
5036 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
5037 dl 1.52 final Action<Entry<K,V>> action = this.action;
5038     if (action == null)
5039 dl 1.61 return abortOnNullFunction();
5040     try {
5041     int b = batch(), c;
5042     while (b > 1 && baseIndex != baseLimit) {
5043     do {} while (!casPending(c = pending, c+1));
5044 dl 1.63 new ForEachEntryTask<K,V>(map, this, b >>>= 1, action).fork();
5045 dl 1.61 }
5046     Object v;
5047     while ((v = advance()) != null)
5048     action.apply(entryFor((K)nextKey, (V)v));
5049     tryComplete();
5050     } catch (Throwable ex) {
5051     return tryCompleteComputation(ex);
5052 dl 1.52 }
5053 dl 1.61 return false;
5054 dl 1.52 }
5055     }
5056    
5057 dl 1.61 @SuppressWarnings("serial") static final class ForEachMappingTask<K,V>
5058 dl 1.52 extends BulkTask<K,V,Void> {
5059     final BiAction<K,V> action;
5060     ForEachMappingTask
5061 dl 1.63 (ConcurrentHashMapV8<K,V> m, BulkTask<K,V,?> p, int b,
5062 dl 1.52 BiAction<K,V> action) {
5063 dl 1.63 super(m, p, b);
5064 dl 1.52 this.action = action;
5065     }
5066 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
5067 dl 1.52 final BiAction<K,V> action = this.action;
5068     if (action == null)
5069 dl 1.61 return abortOnNullFunction();
5070     try {
5071     int b = batch(), c;
5072     while (b > 1 && baseIndex != baseLimit) {
5073     do {} while (!casPending(c = pending, c+1));
5074 dl 1.63 new ForEachMappingTask<K,V>(map, this, b >>>= 1,
5075 dl 1.61 action).fork();
5076     }
5077     Object v;
5078     while ((v = advance()) != null)
5079     action.apply((K)nextKey, (V)v);
5080     tryComplete();
5081     } catch (Throwable ex) {
5082     return tryCompleteComputation(ex);
5083 dl 1.52 }
5084 dl 1.61 return false;
5085 dl 1.52 }
5086     }
5087    
5088 dl 1.61 @SuppressWarnings("serial") static final class ForEachTransformedKeyTask<K,V,U>
5089 dl 1.52 extends BulkTask<K,V,Void> {
5090     final Fun<? super K, ? extends U> transformer;
5091     final Action<U> action;
5092     ForEachTransformedKeyTask
5093 dl 1.63 (ConcurrentHashMapV8<K,V> m, BulkTask<K,V,?> p, int b,
5094 dl 1.52 Fun<? super K, ? extends U> transformer,
5095     Action<U> action) {
5096 dl 1.63 super(m, p, b);
5097 dl 1.52 this.transformer = transformer;
5098     this.action = action;
5099    
5100     }
5101 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
5102 dl 1.52 final Fun<? super K, ? extends U> transformer =
5103     this.transformer;
5104     final Action<U> action = this.action;
5105     if (transformer == null || action == null)
5106 dl 1.61 return abortOnNullFunction();
5107     try {
5108     int b = batch(), c;
5109     while (b > 1 && baseIndex != baseLimit) {
5110     do {} while (!casPending(c = pending, c+1));
5111     new ForEachTransformedKeyTask<K,V,U>
5112 dl 1.63 (map, this, b >>>= 1, transformer, action).fork();
5113 dl 1.61 }
5114     U u;
5115     while (advance() != null) {
5116     if ((u = transformer.apply((K)nextKey)) != null)
5117     action.apply(u);
5118     }
5119     tryComplete();
5120     } catch (Throwable ex) {
5121     return tryCompleteComputation(ex);
5122 dl 1.52 }
5123 dl 1.61 return false;
5124 dl 1.52 }
5125     }
5126    
5127 dl 1.61 @SuppressWarnings("serial") static final class ForEachTransformedValueTask<K,V,U>
5128 dl 1.52 extends BulkTask<K,V,Void> {
5129     final Fun<? super V, ? extends U> transformer;
5130     final Action<U> action;
5131     ForEachTransformedValueTask
5132 dl 1.63 (ConcurrentHashMapV8<K,V> m, BulkTask<K,V,?> p, int b,
5133 dl 1.52 Fun<? super V, ? extends U> transformer,
5134     Action<U> action) {
5135 dl 1.63 super(m, p, b);
5136 dl 1.52 this.transformer = transformer;
5137     this.action = action;
5138    
5139     }
5140 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
5141 dl 1.52 final Fun<? super V, ? extends U> transformer =
5142     this.transformer;
5143     final Action<U> action = this.action;
5144     if (transformer == null || action == null)
5145 dl 1.61 return abortOnNullFunction();
5146     try {
5147     int b = batch(), c;
5148     while (b > 1 && baseIndex != baseLimit) {
5149     do {} while (!casPending(c = pending, c+1));
5150     new ForEachTransformedValueTask<K,V,U>
5151 dl 1.63 (map, this, b >>>= 1, transformer, action).fork();
5152 dl 1.61 }
5153     Object v; U u;
5154     while ((v = advance()) != null) {
5155     if ((u = transformer.apply((V)v)) != null)
5156     action.apply(u);
5157     }
5158     tryComplete();
5159     } catch (Throwable ex) {
5160     return tryCompleteComputation(ex);
5161 dl 1.52 }
5162 dl 1.61 return false;
5163 dl 1.52 }
5164     }
5165    
5166 dl 1.61 @SuppressWarnings("serial") static final class ForEachTransformedEntryTask<K,V,U>
5167 dl 1.52 extends BulkTask<K,V,Void> {
5168     final Fun<Map.Entry<K,V>, ? extends U> transformer;
5169     final Action<U> action;
5170     ForEachTransformedEntryTask
5171 dl 1.63 (ConcurrentHashMapV8<K,V> m, BulkTask<K,V,?> p, int b,
5172 dl 1.52 Fun<Map.Entry<K,V>, ? extends U> transformer,
5173     Action<U> action) {
5174 dl 1.63 super(m, p, b);
5175 dl 1.52 this.transformer = transformer;
5176     this.action = action;
5177    
5178     }
5179 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
5180 dl 1.52 final Fun<Map.Entry<K,V>, ? extends U> transformer =
5181     this.transformer;
5182     final Action<U> action = this.action;
5183     if (transformer == null || action == null)
5184 dl 1.61 return abortOnNullFunction();
5185     try {
5186     int b = batch(), c;
5187     while (b > 1 && baseIndex != baseLimit) {
5188     do {} while (!casPending(c = pending, c+1));
5189     new ForEachTransformedEntryTask<K,V,U>
5190 dl 1.63 (map, this, b >>>= 1, transformer, action).fork();
5191 dl 1.61 }
5192     Object v; U u;
5193     while ((v = advance()) != null) {
5194     if ((u = transformer.apply(entryFor((K)nextKey, (V)v))) != null)
5195     action.apply(u);
5196     }
5197     tryComplete();
5198     } catch (Throwable ex) {
5199     return tryCompleteComputation(ex);
5200 dl 1.52 }
5201 dl 1.61 return false;
5202 dl 1.52 }
5203     }
5204    
5205 dl 1.61 @SuppressWarnings("serial") static final class ForEachTransformedMappingTask<K,V,U>
5206 dl 1.52 extends BulkTask<K,V,Void> {
5207     final BiFun<? super K, ? super V, ? extends U> transformer;
5208     final Action<U> action;
5209     ForEachTransformedMappingTask
5210 dl 1.63 (ConcurrentHashMapV8<K,V> m, BulkTask<K,V,?> p, int b,
5211 dl 1.52 BiFun<? super K, ? super V, ? extends U> transformer,
5212     Action<U> action) {
5213 dl 1.63 super(m, p, b);
5214 dl 1.52 this.transformer = transformer;
5215     this.action = action;
5216    
5217     }
5218 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
5219 dl 1.52 final BiFun<? super K, ? super V, ? extends U> transformer =
5220     this.transformer;
5221     final Action<U> action = this.action;
5222     if (transformer == null || action == null)
5223 dl 1.61 return abortOnNullFunction();
5224     try {
5225     int b = batch(), c;
5226     while (b > 1 && baseIndex != baseLimit) {
5227     do {} while (!casPending(c = pending, c+1));
5228     new ForEachTransformedMappingTask<K,V,U>
5229 dl 1.63 (map, this, b >>>= 1, transformer, action).fork();
5230 dl 1.61 }
5231     Object v; U u;
5232     while ((v = advance()) != null) {
5233     if ((u = transformer.apply((K)nextKey, (V)v)) != null)
5234     action.apply(u);
5235     }
5236     tryComplete();
5237     } catch (Throwable ex) {
5238     return tryCompleteComputation(ex);
5239 dl 1.52 }
5240 dl 1.61 return false;
5241 dl 1.52 }
5242     }
5243    
5244 dl 1.61 @SuppressWarnings("serial") static final class SearchKeysTask<K,V,U>
5245 dl 1.52 extends BulkTask<K,V,U> {
5246     final Fun<? super K, ? extends U> searchFunction;
5247     final AtomicReference<U> result;
5248     SearchKeysTask
5249 dl 1.63 (ConcurrentHashMapV8<K,V> m, BulkTask<K,V,?> p, int b,
5250 dl 1.52 Fun<? super K, ? extends U> searchFunction,
5251     AtomicReference<U> result) {
5252 dl 1.63 super(m, p, b);
5253 dl 1.52 this.searchFunction = searchFunction; this.result = result;
5254     }
5255 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
5256 dl 1.52 AtomicReference<U> result = this.result;
5257     final Fun<? super K, ? extends U> searchFunction =
5258     this.searchFunction;
5259     if (searchFunction == null || result == null)
5260 dl 1.61 return abortOnNullFunction();
5261     try {
5262     int b = batch(), c;
5263     while (b > 1 && baseIndex != baseLimit && result.get() == null) {
5264     do {} while (!casPending(c = pending, c+1));
5265 dl 1.63 new SearchKeysTask<K,V,U>(map, this, b >>>= 1,
5266 dl 1.61 searchFunction, result).fork();
5267     }
5268     U u;
5269     while (result.get() == null && advance() != null) {
5270     if ((u = searchFunction.apply((K)nextKey)) != null) {
5271     if (result.compareAndSet(null, u))
5272     tryCompleteComputation(null);
5273     break;
5274 dl 1.59 }
5275 dl 1.52 }
5276 dl 1.61 tryComplete();
5277     } catch (Throwable ex) {
5278     return tryCompleteComputation(ex);
5279 dl 1.52 }
5280 dl 1.61 return false;
5281 dl 1.52 }
5282     public final U getRawResult() { return result.get(); }
5283     }
5284    
5285 dl 1.61 @SuppressWarnings("serial") static final class SearchValuesTask<K,V,U>
5286 dl 1.52 extends BulkTask<K,V,U> {
5287     final Fun<? super V, ? extends U> searchFunction;
5288     final AtomicReference<U> result;
5289     SearchValuesTask
5290 dl 1.63 (ConcurrentHashMapV8<K,V> m, BulkTask<K,V,?> p, int b,
5291 dl 1.52 Fun<? super V, ? extends U> searchFunction,
5292     AtomicReference<U> result) {
5293 dl 1.63 super(m, p, b);
5294 dl 1.52 this.searchFunction = searchFunction; this.result = result;
5295     }
5296 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
5297 dl 1.52 AtomicReference<U> result = this.result;
5298     final Fun<? super V, ? extends U> searchFunction =
5299     this.searchFunction;
5300     if (searchFunction == null || result == null)
5301 dl 1.61 return abortOnNullFunction();
5302     try {
5303     int b = batch(), c;
5304     while (b > 1 && baseIndex != baseLimit && result.get() == null) {
5305     do {} while (!casPending(c = pending, c+1));
5306 dl 1.63 new SearchValuesTask<K,V,U>(map, this, b >>>= 1,
5307 dl 1.61 searchFunction, result).fork();
5308     }
5309     Object v; U u;
5310     while (result.get() == null && (v = advance()) != null) {
5311     if ((u = searchFunction.apply((V)v)) != null) {
5312     if (result.compareAndSet(null, u))
5313     tryCompleteComputation(null);
5314     break;
5315 dl 1.59 }
5316 dl 1.52 }
5317 dl 1.61 tryComplete();
5318     } catch (Throwable ex) {
5319     return tryCompleteComputation(ex);
5320 dl 1.52 }
5321 dl 1.61 return false;
5322 dl 1.52 }
5323     public final U getRawResult() { return result.get(); }
5324     }
5325    
5326 dl 1.61 @SuppressWarnings("serial") static final class SearchEntriesTask<K,V,U>
5327 dl 1.52 extends BulkTask<K,V,U> {
5328     final Fun<Entry<K,V>, ? extends U> searchFunction;
5329     final AtomicReference<U> result;
5330     SearchEntriesTask
5331 dl 1.63 (ConcurrentHashMapV8<K,V> m, BulkTask<K,V,?> p, int b,
5332 dl 1.52 Fun<Entry<K,V>, ? extends U> searchFunction,
5333     AtomicReference<U> result) {
5334 dl 1.63 super(m, p, b);
5335 dl 1.52 this.searchFunction = searchFunction; this.result = result;
5336     }
5337 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
5338 dl 1.52 AtomicReference<U> result = this.result;
5339     final Fun<Entry<K,V>, ? extends U> searchFunction =
5340     this.searchFunction;
5341     if (searchFunction == null || result == null)
5342 dl 1.61 return abortOnNullFunction();
5343     try {
5344     int b = batch(), c;
5345     while (b > 1 && baseIndex != baseLimit && result.get() == null) {
5346     do {} while (!casPending(c = pending, c+1));
5347 dl 1.63 new SearchEntriesTask<K,V,U>(map, this, b >>>= 1,
5348 dl 1.61 searchFunction, result).fork();
5349     }
5350     Object v; U u;
5351     while (result.get() == null && (v = advance()) != null) {
5352     if ((u = searchFunction.apply(entryFor((K)nextKey, (V)v))) != null) {
5353     if (result.compareAndSet(null, u))
5354     tryCompleteComputation(null);
5355     break;
5356 dl 1.59 }
5357 dl 1.52 }
5358 dl 1.61 tryComplete();
5359     } catch (Throwable ex) {
5360     return tryCompleteComputation(ex);
5361 dl 1.52 }
5362 dl 1.61 return false;
5363 dl 1.52 }
5364     public final U getRawResult() { return result.get(); }
5365     }
5366    
5367 dl 1.61 @SuppressWarnings("serial") static final class SearchMappingsTask<K,V,U>
5368 dl 1.52 extends BulkTask<K,V,U> {
5369     final BiFun<? super K, ? super V, ? extends U> searchFunction;
5370     final AtomicReference<U> result;
5371     SearchMappingsTask
5372 dl 1.63 (ConcurrentHashMapV8<K,V> m, BulkTask<K,V,?> p, int b,
5373 dl 1.52 BiFun<? super K, ? super V, ? extends U> searchFunction,
5374     AtomicReference<U> result) {
5375 dl 1.63 super(m, p, b);
5376 dl 1.52 this.searchFunction = searchFunction; this.result = result;
5377     }
5378 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
5379 dl 1.52 AtomicReference<U> result = this.result;
5380     final BiFun<? super K, ? super V, ? extends U> searchFunction =
5381     this.searchFunction;
5382     if (searchFunction == null || result == null)
5383 dl 1.61 return abortOnNullFunction();
5384     try {
5385     int b = batch(), c;
5386     while (b > 1 && baseIndex != baseLimit && result.get() == null) {
5387     do {} while (!casPending(c = pending, c+1));
5388 dl 1.63 new SearchMappingsTask<K,V,U>(map, this, b >>>= 1,
5389 dl 1.61 searchFunction, result).fork();
5390     }
5391     Object v; U u;
5392     while (result.get() == null && (v = advance()) != null) {
5393     if ((u = searchFunction.apply((K)nextKey, (V)v)) != null) {
5394     if (result.compareAndSet(null, u))
5395     tryCompleteComputation(null);
5396     break;
5397 dl 1.59 }
5398 dl 1.52 }
5399 dl 1.61 tryComplete();
5400     } catch (Throwable ex) {
5401     return tryCompleteComputation(ex);
5402 dl 1.52 }
5403 dl 1.61 return false;
5404 dl 1.52 }
5405     public final U getRawResult() { return result.get(); }
5406     }
5407    
5408 dl 1.61 @SuppressWarnings("serial") static final class ReduceKeysTask<K,V>
5409 dl 1.52 extends BulkTask<K,V,K> {
5410     final BiFun<? super K, ? super K, ? extends K> reducer;
5411     K result;
5412 dl 1.61 ReduceKeysTask<K,V> rights, nextRight;
5413 dl 1.52 ReduceKeysTask
5414 dl 1.63 (ConcurrentHashMapV8<K,V> m, BulkTask<K,V,?> p, int b,
5415 dl 1.61 ReduceKeysTask<K,V> nextRight,
5416 dl 1.52 BiFun<? super K, ? super K, ? extends K> reducer) {
5417 dl 1.63 super(m, p, b); this.nextRight = nextRight;
5418 dl 1.52 this.reducer = reducer;
5419     }
5420 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
5421 dl 1.52 final BiFun<? super K, ? super K, ? extends K> reducer =
5422     this.reducer;
5423     if (reducer == null)
5424 dl 1.61 return abortOnNullFunction();
5425     try {
5426     for (int c, b = batch(); b > 1 && baseIndex != baseLimit;) {
5427     do {} while (!casPending(c = pending, c+1));
5428     (rights = new ReduceKeysTask<K,V>
5429 dl 1.63 (map, this, b >>>= 1, rights, reducer)).fork();
5430 dl 1.61 }
5431     K r = null;
5432     while (advance() != null) {
5433     K u = (K)nextKey;
5434     r = (r == null) ? u : reducer.apply(r, u);
5435 dl 1.52 }
5436 dl 1.61 result = r;
5437     for (ReduceKeysTask<K,V> t = this, s;;) {
5438     int c; BulkTask<K,V,?> par; K tr, sr;
5439     if ((c = t.pending) == 0) {
5440     for (s = t.rights; s != null; s = t.rights = s.nextRight) {
5441     if ((sr = s.result) != null)
5442     t.result = (tr = t.result) == null? sr : reducer.apply(tr, sr);
5443     }
5444     if ((par = t.parent) == null ||
5445     !(par instanceof ReduceKeysTask)) {
5446     t.quietlyComplete();
5447     break;
5448     }
5449     t = (ReduceKeysTask<K,V>)par;
5450     }
5451     else if (t.casPending(c, c - 1))
5452     break;
5453 dl 1.52 }
5454 dl 1.61 } catch (Throwable ex) {
5455     return tryCompleteComputation(ex);
5456 dl 1.52 }
5457 dl 1.61 return false;
5458 dl 1.52 }
5459     public final K getRawResult() { return result; }
5460     }
5461    
5462 dl 1.61 @SuppressWarnings("serial") static final class ReduceValuesTask<K,V>
5463 dl 1.52 extends BulkTask<K,V,V> {
5464     final BiFun<? super V, ? super V, ? extends V> reducer;
5465     V result;
5466 dl 1.61 ReduceValuesTask<K,V> rights, nextRight;
5467 dl 1.52 ReduceValuesTask
5468 dl 1.63 (ConcurrentHashMapV8<K,V> m, BulkTask<K,V,?> p, int b,
5469 dl 1.61 ReduceValuesTask<K,V> nextRight,
5470 dl 1.52 BiFun<? super V, ? super V, ? extends V> reducer) {
5471 dl 1.63 super(m, p, b); this.nextRight = nextRight;
5472 dl 1.52 this.reducer = reducer;
5473     }
5474 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
5475 dl 1.52 final BiFun<? super V, ? super V, ? extends V> reducer =
5476     this.reducer;
5477     if (reducer == null)
5478 dl 1.61 return abortOnNullFunction();
5479     try {
5480     for (int c, b = batch(); b > 1 && baseIndex != baseLimit;) {
5481     do {} while (!casPending(c = pending, c+1));
5482     (rights = new ReduceValuesTask<K,V>
5483 dl 1.63 (map, this, b >>>= 1, rights, reducer)).fork();
5484 dl 1.61 }
5485     V r = null;
5486     Object v;
5487     while ((v = advance()) != null) {
5488     V u = (V)v;
5489     r = (r == null) ? u : reducer.apply(r, u);
5490 dl 1.52 }
5491 dl 1.61 result = r;
5492     for (ReduceValuesTask<K,V> t = this, s;;) {
5493     int c; BulkTask<K,V,?> par; V tr, sr;
5494     if ((c = t.pending) == 0) {
5495     for (s = t.rights; s != null; s = t.rights = s.nextRight) {
5496     if ((sr = s.result) != null)
5497     t.result = (tr = t.result) == null? sr : reducer.apply(tr, sr);
5498     }
5499     if ((par = t.parent) == null ||
5500     !(par instanceof ReduceValuesTask)) {
5501     t.quietlyComplete();
5502     break;
5503     }
5504     t = (ReduceValuesTask<K,V>)par;
5505     }
5506     else if (t.casPending(c, c - 1))
5507     break;
5508 dl 1.52 }
5509 dl 1.61 } catch (Throwable ex) {
5510     return tryCompleteComputation(ex);
5511 dl 1.52 }
5512 dl 1.61 return false;
5513 dl 1.52 }
5514     public final V getRawResult() { return result; }
5515     }
5516    
5517 dl 1.61 @SuppressWarnings("serial") static final class ReduceEntriesTask<K,V>
5518 dl 1.52 extends BulkTask<K,V,Map.Entry<K,V>> {
5519     final BiFun<Map.Entry<K,V>, Map.Entry<K,V>, ? extends Map.Entry<K,V>> reducer;
5520     Map.Entry<K,V> result;
5521 dl 1.61 ReduceEntriesTask<K,V> rights, nextRight;
5522 dl 1.52 ReduceEntriesTask
5523 dl 1.63 (ConcurrentHashMapV8<K,V> m, BulkTask<K,V,?> p, int b,
5524     ReduceEntriesTask<K,V> nextRight,
5525 dl 1.52 BiFun<Entry<K,V>, Map.Entry<K,V>, ? extends Map.Entry<K,V>> reducer) {
5526 dl 1.63 super(m, p, b); this.nextRight = nextRight;
5527 dl 1.52 this.reducer = reducer;
5528     }
5529 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
5530 dl 1.52 final BiFun<Map.Entry<K,V>, Map.Entry<K,V>, ? extends Map.Entry<K,V>> reducer =
5531     this.reducer;
5532     if (reducer == null)
5533 dl 1.61 return abortOnNullFunction();
5534     try {
5535     for (int c, b = batch(); b > 1 && baseIndex != baseLimit;) {
5536     do {} while (!casPending(c = pending, c+1));
5537     (rights = new ReduceEntriesTask<K,V>
5538 dl 1.63 (map, this, b >>>= 1, rights, reducer)).fork();
5539 dl 1.61 }
5540     Map.Entry<K,V> r = null;
5541     Object v;
5542     while ((v = advance()) != null) {
5543     Map.Entry<K,V> u = entryFor((K)nextKey, (V)v);
5544     r = (r == null) ? u : reducer.apply(r, u);
5545 dl 1.52 }
5546 dl 1.61 result = r;
5547     for (ReduceEntriesTask<K,V> t = this, s;;) {
5548     int c; BulkTask<K,V,?> par; Map.Entry<K,V> tr, sr;
5549     if ((c = t.pending) == 0) {
5550     for (s = t.rights; s != null; s = t.rights = s.nextRight) {
5551     if ((sr = s.result) != null)
5552     t.result = (tr = t.result) == null? sr : reducer.apply(tr, sr);
5553     }
5554     if ((par = t.parent) == null ||
5555     !(par instanceof ReduceEntriesTask)) {
5556     t.quietlyComplete();
5557     break;
5558     }
5559     t = (ReduceEntriesTask<K,V>)par;
5560     }
5561     else if (t.casPending(c, c - 1))
5562     break;
5563 dl 1.52 }
5564 dl 1.61 } catch (Throwable ex) {
5565     return tryCompleteComputation(ex);
5566 dl 1.52 }
5567 dl 1.61 return false;
5568 dl 1.52 }
5569     public final Map.Entry<K,V> getRawResult() { return result; }
5570     }
5571    
5572 dl 1.61 @SuppressWarnings("serial") static final class MapReduceKeysTask<K,V,U>
5573 dl 1.52 extends BulkTask<K,V,U> {
5574     final Fun<? super K, ? extends U> transformer;
5575     final BiFun<? super U, ? super U, ? extends U> reducer;
5576     U result;
5577 dl 1.61 MapReduceKeysTask<K,V,U> rights, nextRight;
5578 dl 1.52 MapReduceKeysTask
5579 dl 1.63 (ConcurrentHashMapV8<K,V> m, BulkTask<K,V,?> p, int b,
5580 dl 1.61 MapReduceKeysTask<K,V,U> nextRight,
5581 dl 1.52 Fun<? super K, ? extends U> transformer,
5582     BiFun<? super U, ? super U, ? extends U> reducer) {
5583 dl 1.63 super(m, p, b); this.nextRight = nextRight;
5584 dl 1.52 this.transformer = transformer;
5585     this.reducer = reducer;
5586     }
5587 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
5588 dl 1.52 final Fun<? super K, ? extends U> transformer =
5589     this.transformer;
5590     final BiFun<? super U, ? super U, ? extends U> reducer =
5591     this.reducer;
5592     if (transformer == null || reducer == null)
5593 dl 1.61 return abortOnNullFunction();
5594     try {
5595     for (int c, b = batch(); b > 1 && baseIndex != baseLimit;) {
5596     do {} while (!casPending(c = pending, c+1));
5597     (rights = new MapReduceKeysTask<K,V,U>
5598 dl 1.63 (map, this, b >>>= 1, rights, transformer, reducer)).fork();
5599 dl 1.61 }
5600     U r = null, u;
5601     while (advance() != null) {
5602     if ((u = transformer.apply((K)nextKey)) != null)
5603     r = (r == null) ? u : reducer.apply(r, u);
5604 dl 1.52 }
5605 dl 1.61 result = r;
5606     for (MapReduceKeysTask<K,V,U> t = this, s;;) {
5607     int c; BulkTask<K,V,?> par; U tr, sr;
5608     if ((c = t.pending) == 0) {
5609     for (s = t.rights; s != null; s = t.rights = s.nextRight) {
5610     if ((sr = s.result) != null)
5611     t.result = (tr = t.result) == null? sr : reducer.apply(tr, sr);
5612     }
5613     if ((par = t.parent) == null ||
5614     !(par instanceof MapReduceKeysTask)) {
5615     t.quietlyComplete();
5616     break;
5617     }
5618     t = (MapReduceKeysTask<K,V,U>)par;
5619     }
5620     else if (t.casPending(c, c - 1))
5621     break;
5622 dl 1.52 }
5623 dl 1.61 } catch (Throwable ex) {
5624     return tryCompleteComputation(ex);
5625 dl 1.52 }
5626 dl 1.61 return false;
5627 dl 1.52 }
5628     public final U getRawResult() { return result; }
5629     }
5630    
5631 dl 1.61 @SuppressWarnings("serial") static final class MapReduceValuesTask<K,V,U>
5632 dl 1.52 extends BulkTask<K,V,U> {
5633     final Fun<? super V, ? extends U> transformer;
5634     final BiFun<? super U, ? super U, ? extends U> reducer;
5635     U result;
5636 dl 1.61 MapReduceValuesTask<K,V,U> rights, nextRight;
5637 dl 1.52 MapReduceValuesTask
5638 dl 1.63 (ConcurrentHashMapV8<K,V> m, BulkTask<K,V,?> p, int b,
5639 dl 1.61 MapReduceValuesTask<K,V,U> nextRight,
5640 dl 1.52 Fun<? super V, ? extends U> transformer,
5641     BiFun<? super U, ? super U, ? extends U> reducer) {
5642 dl 1.63 super(m, p, b); this.nextRight = nextRight;
5643 dl 1.52 this.transformer = transformer;
5644     this.reducer = reducer;
5645     }
5646 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
5647 dl 1.52 final Fun<? super V, ? extends U> transformer =
5648     this.transformer;
5649     final BiFun<? super U, ? super U, ? extends U> reducer =
5650     this.reducer;
5651     if (transformer == null || reducer == null)
5652 dl 1.61 return abortOnNullFunction();
5653     try {
5654     for (int c, b = batch(); b > 1 && baseIndex != baseLimit;) {
5655     do {} while (!casPending(c = pending, c+1));
5656     (rights = new MapReduceValuesTask<K,V,U>
5657 dl 1.63 (map, this, b >>>= 1, rights, transformer, reducer)).fork();
5658 dl 1.61 }
5659     U r = null, u;
5660     Object v;
5661     while ((v = advance()) != null) {
5662     if ((u = transformer.apply((V)v)) != null)
5663     r = (r == null) ? u : reducer.apply(r, u);
5664 dl 1.52 }
5665 dl 1.61 result = r;
5666     for (MapReduceValuesTask<K,V,U> t = this, s;;) {
5667     int c; BulkTask<K,V,?> par; U tr, sr;
5668     if ((c = t.pending) == 0) {
5669     for (s = t.rights; s != null; s = t.rights = s.nextRight) {
5670     if ((sr = s.result) != null)
5671     t.result = (tr = t.result) == null? sr : reducer.apply(tr, sr);
5672     }
5673     if ((par = t.parent) == null ||
5674     !(par instanceof MapReduceValuesTask)) {
5675     t.quietlyComplete();
5676     break;
5677     }
5678     t = (MapReduceValuesTask<K,V,U>)par;
5679     }
5680     else if (t.casPending(c, c - 1))
5681     break;
5682 dl 1.52 }
5683 dl 1.61 } catch (Throwable ex) {
5684     return tryCompleteComputation(ex);
5685 dl 1.52 }
5686 dl 1.61 return false;
5687 dl 1.52 }
5688     public final U getRawResult() { return result; }
5689     }
5690    
5691 dl 1.61 @SuppressWarnings("serial") static final class MapReduceEntriesTask<K,V,U>
5692 dl 1.52 extends BulkTask<K,V,U> {
5693     final Fun<Map.Entry<K,V>, ? extends U> transformer;
5694     final BiFun<? super U, ? super U, ? extends U> reducer;
5695     U result;
5696 dl 1.61 MapReduceEntriesTask<K,V,U> rights, nextRight;
5697 dl 1.52 MapReduceEntriesTask
5698 dl 1.63 (ConcurrentHashMapV8<K,V> m, BulkTask<K,V,?> p, int b,
5699 dl 1.61 MapReduceEntriesTask<K,V,U> nextRight,
5700 dl 1.52 Fun<Map.Entry<K,V>, ? extends U> transformer,
5701     BiFun<? super U, ? super U, ? extends U> reducer) {
5702 dl 1.63 super(m, p, b); this.nextRight = nextRight;
5703 dl 1.52 this.transformer = transformer;
5704     this.reducer = reducer;
5705     }
5706 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
5707 dl 1.52 final Fun<Map.Entry<K,V>, ? extends U> transformer =
5708     this.transformer;
5709     final BiFun<? super U, ? super U, ? extends U> reducer =
5710     this.reducer;
5711     if (transformer == null || reducer == null)
5712 dl 1.61 return abortOnNullFunction();
5713     try {
5714     for (int c, b = batch(); b > 1 && baseIndex != baseLimit;) {
5715     do {} while (!casPending(c = pending, c+1));
5716     (rights = new MapReduceEntriesTask<K,V,U>
5717 dl 1.63 (map, this, b >>>= 1, rights, transformer, reducer)).fork();
5718 dl 1.61 }
5719     U r = null, u;
5720     Object v;
5721     while ((v = advance()) != null) {
5722     if ((u = transformer.apply(entryFor((K)nextKey, (V)v))) != null)
5723     r = (r == null) ? u : reducer.apply(r, u);
5724 dl 1.52 }
5725 dl 1.61 result = r;
5726     for (MapReduceEntriesTask<K,V,U> t = this, s;;) {
5727     int c; BulkTask<K,V,?> par; U tr, sr;
5728     if ((c = t.pending) == 0) {
5729     for (s = t.rights; s != null; s = t.rights = s.nextRight) {
5730     if ((sr = s.result) != null)
5731     t.result = (tr = t.result) == null? sr : reducer.apply(tr, sr);
5732     }
5733     if ((par = t.parent) == null ||
5734     !(par instanceof MapReduceEntriesTask)) {
5735     t.quietlyComplete();
5736     break;
5737     }
5738     t = (MapReduceEntriesTask<K,V,U>)par;
5739     }
5740     else if (t.casPending(c, c - 1))
5741     break;
5742 dl 1.52 }
5743 dl 1.61 } catch (Throwable ex) {
5744     return tryCompleteComputation(ex);
5745 dl 1.52 }
5746 dl 1.61 return false;
5747 dl 1.52 }
5748     public final U getRawResult() { return result; }
5749     }
5750    
5751 dl 1.61 @SuppressWarnings("serial") static final class MapReduceMappingsTask<K,V,U>
5752 dl 1.52 extends BulkTask<K,V,U> {
5753     final BiFun<? super K, ? super V, ? extends U> transformer;
5754     final BiFun<? super U, ? super U, ? extends U> reducer;
5755     U result;
5756 dl 1.61 MapReduceMappingsTask<K,V,U> rights, nextRight;
5757 dl 1.52 MapReduceMappingsTask
5758 dl 1.63 (ConcurrentHashMapV8<K,V> m, BulkTask<K,V,?> p, int b,
5759 dl 1.61 MapReduceMappingsTask<K,V,U> nextRight,
5760 dl 1.52 BiFun<? super K, ? super V, ? extends U> transformer,
5761     BiFun<? super U, ? super U, ? extends U> reducer) {
5762 dl 1.63 super(m, p, b); this.nextRight = nextRight;
5763 dl 1.52 this.transformer = transformer;
5764     this.reducer = reducer;
5765     }
5766 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
5767 dl 1.52 final BiFun<? super K, ? super V, ? extends U> transformer =
5768     this.transformer;
5769     final BiFun<? super U, ? super U, ? extends U> reducer =
5770     this.reducer;
5771     if (transformer == null || reducer == null)
5772 dl 1.61 return abortOnNullFunction();
5773     try {
5774     for (int c, b = batch(); b > 1 && baseIndex != baseLimit;) {
5775     do {} while (!casPending(c = pending, c+1));
5776     (rights = new MapReduceMappingsTask<K,V,U>
5777 dl 1.63 (map, this, b >>>= 1, rights, transformer, reducer)).fork();
5778 dl 1.61 }
5779     U r = null, u;
5780     Object v;
5781     while ((v = advance()) != null) {
5782     if ((u = transformer.apply((K)nextKey, (V)v)) != null)
5783     r = (r == null) ? u : reducer.apply(r, u);
5784 dl 1.52 }
5785 dl 1.61 result = r;
5786     for (MapReduceMappingsTask<K,V,U> t = this, s;;) {
5787     int c; BulkTask<K,V,?> par; U tr, sr;
5788     if ((c = t.pending) == 0) {
5789     for (s = t.rights; s != null; s = t.rights = s.nextRight) {
5790     if ((sr = s.result) != null)
5791     t.result = (tr = t.result) == null? sr : reducer.apply(tr, sr);
5792     }
5793     if ((par = t.parent) == null ||
5794     !(par instanceof MapReduceMappingsTask)) {
5795     t.quietlyComplete();
5796     break;
5797     }
5798     t = (MapReduceMappingsTask<K,V,U>)par;
5799     }
5800     else if (t.casPending(c, c - 1))
5801     break;
5802 dl 1.52 }
5803 dl 1.61 } catch (Throwable ex) {
5804     return tryCompleteComputation(ex);
5805 dl 1.52 }
5806 dl 1.61 return false;
5807 dl 1.52 }
5808     public final U getRawResult() { return result; }
5809     }
5810    
5811 dl 1.61 @SuppressWarnings("serial") static final class MapReduceKeysToDoubleTask<K,V>
5812 dl 1.52 extends BulkTask<K,V,Double> {
5813     final ObjectToDouble<? super K> transformer;
5814     final DoubleByDoubleToDouble reducer;
5815     final double basis;
5816     double result;
5817 dl 1.61 MapReduceKeysToDoubleTask<K,V> rights, nextRight;
5818 dl 1.52 MapReduceKeysToDoubleTask
5819 dl 1.63 (ConcurrentHashMapV8<K,V> m, BulkTask<K,V,?> p, int b,
5820 dl 1.61 MapReduceKeysToDoubleTask<K,V> nextRight,
5821 dl 1.52 ObjectToDouble<? super K> transformer,
5822     double basis,
5823     DoubleByDoubleToDouble reducer) {
5824 dl 1.63 super(m, p, b); this.nextRight = nextRight;
5825 dl 1.52 this.transformer = transformer;
5826     this.basis = basis; this.reducer = reducer;
5827     }
5828 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
5829 dl 1.52 final ObjectToDouble<? super K> transformer =
5830     this.transformer;
5831     final DoubleByDoubleToDouble reducer = this.reducer;
5832     if (transformer == null || reducer == null)
5833 dl 1.61 return abortOnNullFunction();
5834     try {
5835     final double id = this.basis;
5836     for (int c, b = batch(); b > 1 && baseIndex != baseLimit;) {
5837     do {} while (!casPending(c = pending, c+1));
5838     (rights = new MapReduceKeysToDoubleTask<K,V>
5839 dl 1.63 (map, this, b >>>= 1, rights, transformer, id, reducer)).fork();
5840 dl 1.61 }
5841     double r = id;
5842     while (advance() != null)
5843     r = reducer.apply(r, transformer.apply((K)nextKey));
5844     result = r;
5845     for (MapReduceKeysToDoubleTask<K,V> t = this, s;;) {
5846     int c; BulkTask<K,V,?> par;
5847     if ((c = t.pending) == 0) {
5848     for (s = t.rights; s != null; s = t.rights = s.nextRight) {
5849     t.result = reducer.apply(t.result, s.result);
5850     }
5851     if ((par = t.parent) == null ||
5852     !(par instanceof MapReduceKeysToDoubleTask)) {
5853     t.quietlyComplete();
5854     break;
5855     }
5856     t = (MapReduceKeysToDoubleTask<K,V>)par;
5857     }
5858     else if (t.casPending(c, c - 1))
5859     break;
5860 dl 1.52 }
5861 dl 1.61 } catch (Throwable ex) {
5862     return tryCompleteComputation(ex);
5863 dl 1.52 }
5864 dl 1.61 return false;
5865 dl 1.52 }
5866     public final Double getRawResult() { return result; }
5867     }
5868    
5869 dl 1.61 @SuppressWarnings("serial") static final class MapReduceValuesToDoubleTask<K,V>
5870 dl 1.52 extends BulkTask<K,V,Double> {
5871     final ObjectToDouble<? super V> transformer;
5872     final DoubleByDoubleToDouble reducer;
5873     final double basis;
5874     double result;
5875 dl 1.61 MapReduceValuesToDoubleTask<K,V> rights, nextRight;
5876 dl 1.52 MapReduceValuesToDoubleTask
5877 dl 1.63 (ConcurrentHashMapV8<K,V> m, BulkTask<K,V,?> p, int b,
5878 dl 1.61 MapReduceValuesToDoubleTask<K,V> nextRight,
5879 dl 1.52 ObjectToDouble<? super V> transformer,
5880     double basis,
5881     DoubleByDoubleToDouble reducer) {
5882 dl 1.63 super(m, p, b); this.nextRight = nextRight;
5883 dl 1.52 this.transformer = transformer;
5884     this.basis = basis; this.reducer = reducer;
5885     }
5886 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
5887 dl 1.52 final ObjectToDouble<? super V> transformer =
5888     this.transformer;
5889     final DoubleByDoubleToDouble reducer = this.reducer;
5890     if (transformer == null || reducer == null)
5891 dl 1.61 return abortOnNullFunction();
5892     try {
5893     final double id = this.basis;
5894     for (int c, b = batch(); b > 1 && baseIndex != baseLimit;) {
5895     do {} while (!casPending(c = pending, c+1));
5896     (rights = new MapReduceValuesToDoubleTask<K,V>
5897 dl 1.63 (map, this, b >>>= 1, rights, transformer, id, reducer)).fork();
5898 dl 1.61 }
5899     double r = id;
5900     Object v;
5901     while ((v = advance()) != null)
5902     r = reducer.apply(r, transformer.apply((V)v));
5903     result = r;
5904     for (MapReduceValuesToDoubleTask<K,V> t = this, s;;) {
5905     int c; BulkTask<K,V,?> par;
5906     if ((c = t.pending) == 0) {
5907     for (s = t.rights; s != null; s = t.rights = s.nextRight) {
5908     t.result = reducer.apply(t.result, s.result);
5909     }
5910     if ((par = t.parent) == null ||
5911     !(par instanceof MapReduceValuesToDoubleTask)) {
5912     t.quietlyComplete();
5913     break;
5914     }
5915     t = (MapReduceValuesToDoubleTask<K,V>)par;
5916     }
5917     else if (t.casPending(c, c - 1))
5918     break;
5919 dl 1.52 }
5920 dl 1.61 } catch (Throwable ex) {
5921     return tryCompleteComputation(ex);
5922 dl 1.52 }
5923 dl 1.61 return false;
5924 dl 1.52 }
5925     public final Double getRawResult() { return result; }
5926     }
5927    
5928 dl 1.61 @SuppressWarnings("serial") static final class MapReduceEntriesToDoubleTask<K,V>
5929 dl 1.52 extends BulkTask<K,V,Double> {
5930     final ObjectToDouble<Map.Entry<K,V>> transformer;
5931     final DoubleByDoubleToDouble reducer;
5932     final double basis;
5933     double result;
5934 dl 1.61 MapReduceEntriesToDoubleTask<K,V> rights, nextRight;
5935 dl 1.52 MapReduceEntriesToDoubleTask
5936 dl 1.63 (ConcurrentHashMapV8<K,V> m, BulkTask<K,V,?> p, int b,
5937 dl 1.61 MapReduceEntriesToDoubleTask<K,V> nextRight,
5938 dl 1.52 ObjectToDouble<Map.Entry<K,V>> transformer,
5939     double basis,
5940     DoubleByDoubleToDouble reducer) {
5941 dl 1.63 super(m, p, b); this.nextRight = nextRight;
5942 dl 1.52 this.transformer = transformer;
5943     this.basis = basis; this.reducer = reducer;
5944     }
5945 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
5946 dl 1.52 final ObjectToDouble<Map.Entry<K,V>> transformer =
5947     this.transformer;
5948     final DoubleByDoubleToDouble reducer = this.reducer;
5949     if (transformer == null || reducer == null)
5950 dl 1.61 return abortOnNullFunction();
5951     try {
5952     final double id = this.basis;
5953     for (int c, b = batch(); b > 1 && baseIndex != baseLimit;) {
5954     do {} while (!casPending(c = pending, c+1));
5955     (rights = new MapReduceEntriesToDoubleTask<K,V>
5956 dl 1.63 (map, this, b >>>= 1, rights, transformer, id, reducer)).fork();
5957 dl 1.61 }
5958     double r = id;
5959     Object v;
5960     while ((v = advance()) != null)
5961     r = reducer.apply(r, transformer.apply(entryFor((K)nextKey, (V)v)));
5962     result = r;
5963     for (MapReduceEntriesToDoubleTask<K,V> t = this, s;;) {
5964     int c; BulkTask<K,V,?> par;
5965     if ((c = t.pending) == 0) {
5966     for (s = t.rights; s != null; s = t.rights = s.nextRight) {
5967     t.result = reducer.apply(t.result, s.result);
5968     }
5969     if ((par = t.parent) == null ||
5970     !(par instanceof MapReduceEntriesToDoubleTask)) {
5971     t.quietlyComplete();
5972     break;
5973     }
5974     t = (MapReduceEntriesToDoubleTask<K,V>)par;
5975     }
5976     else if (t.casPending(c, c - 1))
5977     break;
5978 dl 1.52 }
5979 dl 1.61 } catch (Throwable ex) {
5980     return tryCompleteComputation(ex);
5981 dl 1.52 }
5982 dl 1.61 return false;
5983 dl 1.52 }
5984     public final Double getRawResult() { return result; }
5985     }
5986    
5987 dl 1.61 @SuppressWarnings("serial") static final class MapReduceMappingsToDoubleTask<K,V>
5988 dl 1.52 extends BulkTask<K,V,Double> {
5989     final ObjectByObjectToDouble<? super K, ? super V> transformer;
5990     final DoubleByDoubleToDouble reducer;
5991     final double basis;
5992     double result;
5993 dl 1.61 MapReduceMappingsToDoubleTask<K,V> rights, nextRight;
5994 dl 1.52 MapReduceMappingsToDoubleTask
5995 dl 1.63 (ConcurrentHashMapV8<K,V> m, BulkTask<K,V,?> p, int b,
5996 dl 1.61 MapReduceMappingsToDoubleTask<K,V> nextRight,
5997 dl 1.52 ObjectByObjectToDouble<? super K, ? super V> transformer,
5998     double basis,
5999     DoubleByDoubleToDouble reducer) {
6000 dl 1.63 super(m, p, b); this.nextRight = nextRight;
6001 dl 1.52 this.transformer = transformer;
6002     this.basis = basis; this.reducer = reducer;
6003     }
6004 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
6005 dl 1.52 final ObjectByObjectToDouble<? super K, ? super V> transformer =
6006     this.transformer;
6007     final DoubleByDoubleToDouble reducer = this.reducer;
6008     if (transformer == null || reducer == null)
6009 dl 1.61 return abortOnNullFunction();
6010     try {
6011     final double id = this.basis;
6012     for (int c, b = batch(); b > 1 && baseIndex != baseLimit;) {
6013     do {} while (!casPending(c = pending, c+1));
6014     (rights = new MapReduceMappingsToDoubleTask<K,V>
6015 dl 1.63 (map, this, b >>>= 1, rights, transformer, id, reducer)).fork();
6016 dl 1.61 }
6017     double r = id;
6018     Object v;
6019     while ((v = advance()) != null)
6020     r = reducer.apply(r, transformer.apply((K)nextKey, (V)v));
6021     result = r;
6022     for (MapReduceMappingsToDoubleTask<K,V> t = this, s;;) {
6023     int c; BulkTask<K,V,?> par;
6024     if ((c = t.pending) == 0) {
6025     for (s = t.rights; s != null; s = t.rights = s.nextRight) {
6026     t.result = reducer.apply(t.result, s.result);
6027     }
6028     if ((par = t.parent) == null ||
6029     !(par instanceof MapReduceMappingsToDoubleTask)) {
6030     t.quietlyComplete();
6031     break;
6032     }
6033     t = (MapReduceMappingsToDoubleTask<K,V>)par;
6034     }
6035     else if (t.casPending(c, c - 1))
6036     break;
6037 dl 1.52 }
6038 dl 1.61 } catch (Throwable ex) {
6039     return tryCompleteComputation(ex);
6040 dl 1.52 }
6041 dl 1.61 return false;
6042 dl 1.52 }
6043     public final Double getRawResult() { return result; }
6044     }
6045    
6046 dl 1.61 @SuppressWarnings("serial") static final class MapReduceKeysToLongTask<K,V>
6047 dl 1.52 extends BulkTask<K,V,Long> {
6048     final ObjectToLong<? super K> transformer;
6049     final LongByLongToLong reducer;
6050     final long basis;
6051     long result;
6052 dl 1.61 MapReduceKeysToLongTask<K,V> rights, nextRight;
6053 dl 1.52 MapReduceKeysToLongTask
6054 dl 1.63 (ConcurrentHashMapV8<K,V> m, BulkTask<K,V,?> p, int b,
6055 dl 1.61 MapReduceKeysToLongTask<K,V> nextRight,
6056 dl 1.52 ObjectToLong<? super K> transformer,
6057     long basis,
6058     LongByLongToLong reducer) {
6059 dl 1.63 super(m, p, b); this.nextRight = nextRight;
6060 dl 1.52 this.transformer = transformer;
6061     this.basis = basis; this.reducer = reducer;
6062     }
6063 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
6064 dl 1.52 final ObjectToLong<? super K> transformer =
6065     this.transformer;
6066     final LongByLongToLong reducer = this.reducer;
6067     if (transformer == null || reducer == null)
6068 dl 1.61 return abortOnNullFunction();
6069     try {
6070     final long id = this.basis;
6071     for (int c, b = batch(); b > 1 && baseIndex != baseLimit;) {
6072     do {} while (!casPending(c = pending, c+1));
6073     (rights = new MapReduceKeysToLongTask<K,V>
6074 dl 1.63 (map, this, b >>>= 1, rights, transformer, id, reducer)).fork();
6075 dl 1.61 }
6076     long r = id;
6077     while (advance() != null)
6078     r = reducer.apply(r, transformer.apply((K)nextKey));
6079     result = r;
6080     for (MapReduceKeysToLongTask<K,V> t = this, s;;) {
6081     int c; BulkTask<K,V,?> par;
6082     if ((c = t.pending) == 0) {
6083     for (s = t.rights; s != null; s = t.rights = s.nextRight) {
6084     t.result = reducer.apply(t.result, s.result);
6085     }
6086     if ((par = t.parent) == null ||
6087     !(par instanceof MapReduceKeysToLongTask)) {
6088     t.quietlyComplete();
6089     break;
6090     }
6091     t = (MapReduceKeysToLongTask<K,V>)par;
6092     }
6093     else if (t.casPending(c, c - 1))
6094     break;
6095 dl 1.52 }
6096 dl 1.61 } catch (Throwable ex) {
6097     return tryCompleteComputation(ex);
6098 dl 1.52 }
6099 dl 1.61 return false;
6100 dl 1.52 }
6101     public final Long getRawResult() { return result; }
6102     }
6103    
6104 dl 1.61 @SuppressWarnings("serial") static final class MapReduceValuesToLongTask<K,V>
6105 dl 1.52 extends BulkTask<K,V,Long> {
6106     final ObjectToLong<? super V> transformer;
6107     final LongByLongToLong reducer;
6108     final long basis;
6109     long result;
6110 dl 1.61 MapReduceValuesToLongTask<K,V> rights, nextRight;
6111 dl 1.52 MapReduceValuesToLongTask
6112 dl 1.63 (ConcurrentHashMapV8<K,V> m, BulkTask<K,V,?> p, int b,
6113 dl 1.61 MapReduceValuesToLongTask<K,V> nextRight,
6114 dl 1.52 ObjectToLong<? super V> transformer,
6115     long basis,
6116     LongByLongToLong reducer) {
6117 dl 1.63 super(m, p, b); this.nextRight = nextRight;
6118 dl 1.52 this.transformer = transformer;
6119     this.basis = basis; this.reducer = reducer;
6120     }
6121 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
6122 dl 1.52 final ObjectToLong<? super V> transformer =
6123     this.transformer;
6124     final LongByLongToLong reducer = this.reducer;
6125     if (transformer == null || reducer == null)
6126 dl 1.61 return abortOnNullFunction();
6127     try {
6128     final long id = this.basis;
6129     for (int c, b = batch(); b > 1 && baseIndex != baseLimit;) {
6130     do {} while (!casPending(c = pending, c+1));
6131     (rights = new MapReduceValuesToLongTask<K,V>
6132 dl 1.63 (map, this, b >>>= 1, rights, transformer, id, reducer)).fork();
6133 dl 1.61 }
6134     long r = id;
6135     Object v;
6136     while ((v = advance()) != null)
6137     r = reducer.apply(r, transformer.apply((V)v));
6138     result = r;
6139     for (MapReduceValuesToLongTask<K,V> t = this, s;;) {
6140     int c; BulkTask<K,V,?> par;
6141     if ((c = t.pending) == 0) {
6142     for (s = t.rights; s != null; s = t.rights = s.nextRight) {
6143     t.result = reducer.apply(t.result, s.result);
6144     }
6145     if ((par = t.parent) == null ||
6146     !(par instanceof MapReduceValuesToLongTask)) {
6147     t.quietlyComplete();
6148     break;
6149     }
6150     t = (MapReduceValuesToLongTask<K,V>)par;
6151     }
6152     else if (t.casPending(c, c - 1))
6153     break;
6154 dl 1.52 }
6155 dl 1.61 } catch (Throwable ex) {
6156     return tryCompleteComputation(ex);
6157 dl 1.52 }
6158 dl 1.61 return false;
6159 dl 1.52 }
6160     public final Long getRawResult() { return result; }
6161     }
6162    
6163 dl 1.61 @SuppressWarnings("serial") static final class MapReduceEntriesToLongTask<K,V>
6164 dl 1.52 extends BulkTask<K,V,Long> {
6165     final ObjectToLong<Map.Entry<K,V>> transformer;
6166     final LongByLongToLong reducer;
6167     final long basis;
6168     long result;
6169 dl 1.61 MapReduceEntriesToLongTask<K,V> rights, nextRight;
6170 dl 1.52 MapReduceEntriesToLongTask
6171 dl 1.63 (ConcurrentHashMapV8<K,V> m, BulkTask<K,V,?> p, int b,
6172 dl 1.61 MapReduceEntriesToLongTask<K,V> nextRight,
6173 dl 1.52 ObjectToLong<Map.Entry<K,V>> transformer,
6174     long basis,
6175     LongByLongToLong reducer) {
6176 dl 1.63 super(m, p, b); this.nextRight = nextRight;
6177 dl 1.52 this.transformer = transformer;
6178     this.basis = basis; this.reducer = reducer;
6179     }
6180 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
6181 dl 1.52 final ObjectToLong<Map.Entry<K,V>> transformer =
6182     this.transformer;
6183     final LongByLongToLong reducer = this.reducer;
6184     if (transformer == null || reducer == null)
6185 dl 1.61 return abortOnNullFunction();
6186     try {
6187     final long id = this.basis;
6188     for (int c, b = batch(); b > 1 && baseIndex != baseLimit;) {
6189     do {} while (!casPending(c = pending, c+1));
6190     (rights = new MapReduceEntriesToLongTask<K,V>
6191 dl 1.63 (map, this, b >>>= 1, rights, transformer, id, reducer)).fork();
6192 dl 1.61 }
6193     long r = id;
6194     Object v;
6195     while ((v = advance()) != null)
6196     r = reducer.apply(r, transformer.apply(entryFor((K)nextKey, (V)v)));
6197     result = r;
6198     for (MapReduceEntriesToLongTask<K,V> t = this, s;;) {
6199     int c; BulkTask<K,V,?> par;
6200     if ((c = t.pending) == 0) {
6201     for (s = t.rights; s != null; s = t.rights = s.nextRight) {
6202     t.result = reducer.apply(t.result, s.result);
6203     }
6204     if ((par = t.parent) == null ||
6205     !(par instanceof MapReduceEntriesToLongTask)) {
6206     t.quietlyComplete();
6207     break;
6208     }
6209     t = (MapReduceEntriesToLongTask<K,V>)par;
6210     }
6211     else if (t.casPending(c, c - 1))
6212     break;
6213 dl 1.52 }
6214 dl 1.61 } catch (Throwable ex) {
6215     return tryCompleteComputation(ex);
6216 dl 1.52 }
6217 dl 1.61 return false;
6218 dl 1.52 }
6219     public final Long getRawResult() { return result; }
6220     }
6221    
6222 dl 1.61 @SuppressWarnings("serial") static final class MapReduceMappingsToLongTask<K,V>
6223 dl 1.52 extends BulkTask<K,V,Long> {
6224     final ObjectByObjectToLong<? super K, ? super V> transformer;
6225     final LongByLongToLong reducer;
6226     final long basis;
6227     long result;
6228 dl 1.61 MapReduceMappingsToLongTask<K,V> rights, nextRight;
6229 dl 1.52 MapReduceMappingsToLongTask
6230 dl 1.63 (ConcurrentHashMapV8<K,V> m, BulkTask<K,V,?> p, int b,
6231 dl 1.61 MapReduceMappingsToLongTask<K,V> nextRight,
6232 dl 1.52 ObjectByObjectToLong<? super K, ? super V> transformer,
6233     long basis,
6234     LongByLongToLong reducer) {
6235 dl 1.63 super(m, p, b); this.nextRight = nextRight;
6236 dl 1.52 this.transformer = transformer;
6237     this.basis = basis; this.reducer = reducer;
6238     }
6239 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
6240 dl 1.52 final ObjectByObjectToLong<? super K, ? super V> transformer =
6241     this.transformer;
6242     final LongByLongToLong reducer = this.reducer;
6243     if (transformer == null || reducer == null)
6244 dl 1.61 return abortOnNullFunction();
6245     try {
6246     final long id = this.basis;
6247     for (int c, b = batch(); b > 1 && baseIndex != baseLimit;) {
6248     do {} while (!casPending(c = pending, c+1));
6249     (rights = new MapReduceMappingsToLongTask<K,V>
6250 dl 1.63 (map, this, b >>>= 1, rights, transformer, id, reducer)).fork();
6251 dl 1.61 }
6252     long r = id;
6253     Object v;
6254     while ((v = advance()) != null)
6255     r = reducer.apply(r, transformer.apply((K)nextKey, (V)v));
6256     result = r;
6257     for (MapReduceMappingsToLongTask<K,V> t = this, s;;) {
6258     int c; BulkTask<K,V,?> par;
6259     if ((c = t.pending) == 0) {
6260     for (s = t.rights; s != null; s = t.rights = s.nextRight) {
6261     t.result = reducer.apply(t.result, s.result);
6262     }
6263     if ((par = t.parent) == null ||
6264     !(par instanceof MapReduceMappingsToLongTask)) {
6265     t.quietlyComplete();
6266     break;
6267     }
6268     t = (MapReduceMappingsToLongTask<K,V>)par;
6269     }
6270     else if (t.casPending(c, c - 1))
6271     break;
6272 dl 1.52 }
6273 dl 1.61 } catch (Throwable ex) {
6274     return tryCompleteComputation(ex);
6275 dl 1.52 }
6276 dl 1.61 return false;
6277 dl 1.52 }
6278     public final Long getRawResult() { return result; }
6279     }
6280    
6281 dl 1.61 @SuppressWarnings("serial") static final class MapReduceKeysToIntTask<K,V>
6282 dl 1.52 extends BulkTask<K,V,Integer> {
6283     final ObjectToInt<? super K> transformer;
6284     final IntByIntToInt reducer;
6285     final int basis;
6286     int result;
6287 dl 1.61 MapReduceKeysToIntTask<K,V> rights, nextRight;
6288 dl 1.52 MapReduceKeysToIntTask
6289 dl 1.63 (ConcurrentHashMapV8<K,V> m, BulkTask<K,V,?> p, int b,
6290 dl 1.61 MapReduceKeysToIntTask<K,V> nextRight,
6291 dl 1.52 ObjectToInt<? super K> transformer,
6292     int basis,
6293     IntByIntToInt reducer) {
6294 dl 1.63 super(m, p, b); this.nextRight = nextRight;
6295 dl 1.52 this.transformer = transformer;
6296     this.basis = basis; this.reducer = reducer;
6297     }
6298 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
6299 dl 1.52 final ObjectToInt<? super K> transformer =
6300     this.transformer;
6301     final IntByIntToInt reducer = this.reducer;
6302     if (transformer == null || reducer == null)
6303 dl 1.61 return abortOnNullFunction();
6304     try {
6305     final int id = this.basis;
6306     for (int c, b = batch(); b > 1 && baseIndex != baseLimit;) {
6307     do {} while (!casPending(c = pending, c+1));
6308     (rights = new MapReduceKeysToIntTask<K,V>
6309 dl 1.63 (map, this, b >>>= 1, rights, transformer, id, reducer)).fork();
6310 dl 1.61 }
6311     int r = id;
6312     while (advance() != null)
6313     r = reducer.apply(r, transformer.apply((K)nextKey));
6314     result = r;
6315     for (MapReduceKeysToIntTask<K,V> t = this, s;;) {
6316     int c; BulkTask<K,V,?> par;
6317     if ((c = t.pending) == 0) {
6318     for (s = t.rights; s != null; s = t.rights = s.nextRight) {
6319     t.result = reducer.apply(t.result, s.result);
6320     }
6321     if ((par = t.parent) == null ||
6322     !(par instanceof MapReduceKeysToIntTask)) {
6323     t.quietlyComplete();
6324     break;
6325     }
6326     t = (MapReduceKeysToIntTask<K,V>)par;
6327     }
6328     else if (t.casPending(c, c - 1))
6329     break;
6330 dl 1.52 }
6331 dl 1.61 } catch (Throwable ex) {
6332     return tryCompleteComputation(ex);
6333 dl 1.52 }
6334 dl 1.61 return false;
6335 dl 1.52 }
6336     public final Integer getRawResult() { return result; }
6337     }
6338    
6339 dl 1.61 @SuppressWarnings("serial") static final class MapReduceValuesToIntTask<K,V>
6340 dl 1.52 extends BulkTask<K,V,Integer> {
6341     final ObjectToInt<? super V> transformer;
6342     final IntByIntToInt reducer;
6343     final int basis;
6344     int result;
6345 dl 1.61 MapReduceValuesToIntTask<K,V> rights, nextRight;
6346 dl 1.52 MapReduceValuesToIntTask
6347 dl 1.63 (ConcurrentHashMapV8<K,V> m, BulkTask<K,V,?> p, int b,
6348 dl 1.61 MapReduceValuesToIntTask<K,V> nextRight,
6349 dl 1.52 ObjectToInt<? super V> transformer,
6350     int basis,
6351     IntByIntToInt reducer) {
6352 dl 1.63 super(m, p, b); this.nextRight = nextRight;
6353 dl 1.52 this.transformer = transformer;
6354     this.basis = basis; this.reducer = reducer;
6355     }
6356 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
6357 dl 1.52 final ObjectToInt<? super V> transformer =
6358     this.transformer;
6359     final IntByIntToInt reducer = this.reducer;
6360     if (transformer == null || reducer == null)
6361 dl 1.61 return abortOnNullFunction();
6362     try {
6363     final int id = this.basis;
6364     for (int c, b = batch(); b > 1 && baseIndex != baseLimit;) {
6365     do {} while (!casPending(c = pending, c+1));
6366     (rights = new MapReduceValuesToIntTask<K,V>
6367 dl 1.63 (map, this, b >>>= 1, rights, transformer, id, reducer)).fork();
6368 dl 1.61 }
6369     int r = id;
6370     Object v;
6371     while ((v = advance()) != null)
6372     r = reducer.apply(r, transformer.apply((V)v));
6373     result = r;
6374     for (MapReduceValuesToIntTask<K,V> t = this, s;;) {
6375     int c; BulkTask<K,V,?> par;
6376     if ((c = t.pending) == 0) {
6377     for (s = t.rights; s != null; s = t.rights = s.nextRight) {
6378     t.result = reducer.apply(t.result, s.result);
6379     }
6380     if ((par = t.parent) == null ||
6381     !(par instanceof MapReduceValuesToIntTask)) {
6382     t.quietlyComplete();
6383     break;
6384     }
6385     t = (MapReduceValuesToIntTask<K,V>)par;
6386     }
6387     else if (t.casPending(c, c - 1))
6388     break;
6389 dl 1.52 }
6390 dl 1.61 } catch (Throwable ex) {
6391     return tryCompleteComputation(ex);
6392 dl 1.52 }
6393 dl 1.61 return false;
6394 dl 1.52 }
6395     public final Integer getRawResult() { return result; }
6396     }
6397    
6398 dl 1.61 @SuppressWarnings("serial") static final class MapReduceEntriesToIntTask<K,V>
6399 dl 1.52 extends BulkTask<K,V,Integer> {
6400     final ObjectToInt<Map.Entry<K,V>> transformer;
6401     final IntByIntToInt reducer;
6402     final int basis;
6403     int result;
6404 dl 1.61 MapReduceEntriesToIntTask<K,V> rights, nextRight;
6405 dl 1.52 MapReduceEntriesToIntTask
6406 dl 1.63 (ConcurrentHashMapV8<K,V> m, BulkTask<K,V,?> p, int b,
6407 dl 1.61 MapReduceEntriesToIntTask<K,V> nextRight,
6408 dl 1.52 ObjectToInt<Map.Entry<K,V>> transformer,
6409     int basis,
6410     IntByIntToInt reducer) {
6411 dl 1.63 super(m, p, b); this.nextRight = nextRight;
6412 dl 1.52 this.transformer = transformer;
6413     this.basis = basis; this.reducer = reducer;
6414     }
6415 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
6416 dl 1.52 final ObjectToInt<Map.Entry<K,V>> transformer =
6417     this.transformer;
6418     final IntByIntToInt reducer = this.reducer;
6419     if (transformer == null || reducer == null)
6420 dl 1.61 return abortOnNullFunction();
6421     try {
6422     final int id = this.basis;
6423     for (int c, b = batch(); b > 1 && baseIndex != baseLimit;) {
6424     do {} while (!casPending(c = pending, c+1));
6425     (rights = new MapReduceEntriesToIntTask<K,V>
6426 dl 1.63 (map, this, b >>>= 1, rights, transformer, id, reducer)).fork();
6427 dl 1.61 }
6428     int r = id;
6429     Object v;
6430     while ((v = advance()) != null)
6431     r = reducer.apply(r, transformer.apply(entryFor((K)nextKey, (V)v)));
6432     result = r;
6433     for (MapReduceEntriesToIntTask<K,V> t = this, s;;) {
6434     int c; BulkTask<K,V,?> par;
6435     if ((c = t.pending) == 0) {
6436     for (s = t.rights; s != null; s = t.rights = s.nextRight) {
6437     t.result = reducer.apply(t.result, s.result);
6438     }
6439     if ((par = t.parent) == null ||
6440     !(par instanceof MapReduceEntriesToIntTask)) {
6441     t.quietlyComplete();
6442     break;
6443     }
6444     t = (MapReduceEntriesToIntTask<K,V>)par;
6445     }
6446     else if (t.casPending(c, c - 1))
6447     break;
6448 dl 1.52 }
6449 dl 1.61 } catch (Throwable ex) {
6450     return tryCompleteComputation(ex);
6451 dl 1.52 }
6452 dl 1.61 return false;
6453 dl 1.52 }
6454     public final Integer getRawResult() { return result; }
6455     }
6456    
6457 dl 1.61 @SuppressWarnings("serial") static final class MapReduceMappingsToIntTask<K,V>
6458 dl 1.52 extends BulkTask<K,V,Integer> {
6459     final ObjectByObjectToInt<? super K, ? super V> transformer;
6460     final IntByIntToInt reducer;
6461     final int basis;
6462     int result;
6463 dl 1.61 MapReduceMappingsToIntTask<K,V> rights, nextRight;
6464 dl 1.52 MapReduceMappingsToIntTask
6465 dl 1.63 (ConcurrentHashMapV8<K,V> m, BulkTask<K,V,?> p, int b,
6466     MapReduceMappingsToIntTask<K,V> rights,
6467 dl 1.52 ObjectByObjectToInt<? super K, ? super V> transformer,
6468     int basis,
6469     IntByIntToInt reducer) {
6470 dl 1.63 super(m, p, b); this.nextRight = nextRight;
6471 dl 1.52 this.transformer = transformer;
6472     this.basis = basis; this.reducer = reducer;
6473     }
6474 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
6475 dl 1.52 final ObjectByObjectToInt<? super K, ? super V> transformer =
6476     this.transformer;
6477     final IntByIntToInt reducer = this.reducer;
6478     if (transformer == null || reducer == null)
6479 dl 1.61 return abortOnNullFunction();
6480     try {
6481     final int id = this.basis;
6482     for (int c, b = batch(); b > 1 && baseIndex != baseLimit;) {
6483     do {} while (!casPending(c = pending, c+1));
6484     (rights = new MapReduceMappingsToIntTask<K,V>
6485 dl 1.63 (map, this, b >>>= 1, rights, transformer, id, reducer)).fork();
6486 dl 1.61 }
6487     int r = id;
6488     Object v;
6489     while ((v = advance()) != null)
6490     r = reducer.apply(r, transformer.apply((K)nextKey, (V)v));
6491     result = r;
6492     for (MapReduceMappingsToIntTask<K,V> t = this, s;;) {
6493     int c; BulkTask<K,V,?> par;
6494     if ((c = t.pending) == 0) {
6495     for (s = t.rights; s != null; s = t.rights = s.nextRight) {
6496     t.result = reducer.apply(t.result, s.result);
6497     }
6498     if ((par = t.parent) == null ||
6499     !(par instanceof MapReduceMappingsToIntTask)) {
6500     t.quietlyComplete();
6501     break;
6502     }
6503     t = (MapReduceMappingsToIntTask<K,V>)par;
6504     }
6505     else if (t.casPending(c, c - 1))
6506     break;
6507 dl 1.52 }
6508 dl 1.61 } catch (Throwable ex) {
6509     return tryCompleteComputation(ex);
6510 dl 1.52 }
6511 dl 1.61 return false;
6512 dl 1.52 }
6513     public final Integer getRawResult() { return result; }
6514     }
6515    
6516    
6517     // Unsafe mechanics
6518     private static final sun.misc.Unsafe UNSAFE;
6519     private static final long counterOffset;
6520     private static final long sizeCtlOffset;
6521     private static final long ABASE;
6522     private static final int ASHIFT;
6523    
6524     static {
6525     int ss;
6526     try {
6527     UNSAFE = getUnsafe();
6528     Class<?> k = ConcurrentHashMapV8.class;
6529     counterOffset = UNSAFE.objectFieldOffset
6530     (k.getDeclaredField("counter"));
6531     sizeCtlOffset = UNSAFE.objectFieldOffset
6532     (k.getDeclaredField("sizeCtl"));
6533     Class<?> sc = Node[].class;
6534     ABASE = UNSAFE.arrayBaseOffset(sc);
6535     ss = UNSAFE.arrayIndexScale(sc);
6536     } catch (Exception e) {
6537     throw new Error(e);
6538     }
6539     if ((ss & (ss-1)) != 0)
6540     throw new Error("data type scale not a power of two");
6541     ASHIFT = 31 - Integer.numberOfLeadingZeros(ss);
6542     }
6543    
6544     /**
6545     * Returns a sun.misc.Unsafe. Suitable for use in a 3rd party package.
6546     * Replace with a simple call to Unsafe.getUnsafe when integrating
6547     * into a jdk.
6548     *
6549     * @return a sun.misc.Unsafe
6550     */
6551     private static sun.misc.Unsafe getUnsafe() {
6552     try {
6553     return sun.misc.Unsafe.getUnsafe();
6554     } catch (SecurityException se) {
6555     try {
6556     return java.security.AccessController.doPrivileged
6557     (new java.security
6558     .PrivilegedExceptionAction<sun.misc.Unsafe>() {
6559     public sun.misc.Unsafe run() throws Exception {
6560     java.lang.reflect.Field f = sun.misc
6561     .Unsafe.class.getDeclaredField("theUnsafe");
6562     f.setAccessible(true);
6563     return (sun.misc.Unsafe) f.get(null);
6564     }});
6565     } catch (java.security.PrivilegedActionException e) {
6566     throw new RuntimeException("Could not initialize intrinsics",
6567     e.getCause());
6568     }
6569     }
6570     }
6571 dl 1.1 }