ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jsr166e/ConcurrentHashMapV8.java
Revision: 1.61
Committed: Thu Sep 13 10:41:37 2012 UTC (11 years, 7 months ago) by dl
Branch: MAIN
Changes since 1.60: +1023 -1075 lines
Log Message:
Reduce task overhead; incorporate review suggestions

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.14 final int baseSize; // initial table size
2291    
2292     /** Creates iterator for all entries in the table. */
2293 dl 1.52 Traverser(ConcurrentHashMapV8<K, V> map) {
2294 dl 1.41 this.tab = (this.map = map).table;
2295 dl 1.14 baseLimit = baseSize = (tab == null) ? 0 : tab.length;
2296     }
2297    
2298 dl 1.52 /** Creates iterator for split() methods */
2299 dl 1.61 Traverser(Traverser<K,V,?> it) {
2300 dl 1.41 this.map = it.map;
2301     this.tab = it.tab;
2302     this.baseSize = it.baseSize;
2303 dl 1.61 it.baseLimit = this.index = this.baseIndex =
2304     ((this.baseLimit = it.baseLimit) + it.baseIndex + 1) >>> 1;
2305 dl 1.41 }
2306    
2307     /**
2308 jsr166 1.48 * Advances next; returns nextVal or null if terminated.
2309 dl 1.41 * See above for explanation.
2310     */
2311     final Object advance() {
2312 dl 1.14 Node e = last = next;
2313 dl 1.41 Object ev = null;
2314 dl 1.14 outer: do {
2315 dl 1.24 if (e != null) // advance past used/skipped node
2316 dl 1.1 e = e.next;
2317 dl 1.24 while (e == null) { // get to next non-null bin
2318 dl 1.38 Node[] t; int b, i, n; Object ek; // checks must use locals
2319 dl 1.14 if ((b = baseIndex) >= baseLimit || (i = index) < 0 ||
2320     (t = tab) == null || i >= (n = t.length))
2321     break outer;
2322 dl 1.38 else if ((e = tabAt(t, i)) != null && e.hash == MOVED) {
2323     if ((ek = e.key) instanceof TreeBin)
2324     e = ((TreeBin)ek).first;
2325     else {
2326     tab = (Node[])ek;
2327     continue; // restarts due to null val
2328     }
2329     } // visit upper slots if present
2330     index = (i += baseSize) < n ? i : (baseIndex = b + 1);
2331 dl 1.1 }
2332 dl 1.14 nextKey = e.key;
2333 dl 1.41 } while ((ev = e.val) == null); // skip deleted or special nodes
2334 dl 1.14 next = e;
2335 dl 1.41 return nextVal = ev;
2336 dl 1.1 }
2337 dl 1.41
2338     public final void remove() {
2339 dl 1.57 if (nextVal == null && last == null)
2340 dl 1.41 advance();
2341     Node e = last;
2342     if (e == null)
2343     throw new IllegalStateException();
2344     last = null;
2345     map.remove(e.key);
2346     }
2347    
2348     public final boolean hasNext() {
2349     return nextVal != null || advance() != null;
2350     }
2351    
2352     public final boolean hasMoreElements() { return hasNext(); }
2353 dl 1.52 public final void setRawResult(Object x) { }
2354     public R getRawResult() { return null; }
2355     public boolean exec() { return true; }
2356 dl 1.1 }
2357    
2358     /* ---------------- Public operations -------------- */
2359    
2360     /**
2361 jsr166 1.48 * Creates a new, empty map with the default initial table size (16).
2362 dl 1.1 */
2363 dl 1.16 public ConcurrentHashMapV8() {
2364 dl 1.14 this.counter = new LongAdder();
2365 dl 1.1 }
2366    
2367     /**
2368 dl 1.16 * Creates a new, empty map with an initial table size
2369     * accommodating the specified number of elements without the need
2370     * to dynamically resize.
2371 dl 1.1 *
2372     * @param initialCapacity The implementation performs internal
2373     * sizing to accommodate this many elements.
2374     * @throws IllegalArgumentException if the initial capacity of
2375 jsr166 1.18 * elements is negative
2376 dl 1.1 */
2377 dl 1.16 public ConcurrentHashMapV8(int initialCapacity) {
2378     if (initialCapacity < 0)
2379     throw new IllegalArgumentException();
2380     int cap = ((initialCapacity >= (MAXIMUM_CAPACITY >>> 1)) ?
2381     MAXIMUM_CAPACITY :
2382     tableSizeFor(initialCapacity + (initialCapacity >>> 1) + 1));
2383     this.counter = new LongAdder();
2384 dl 1.24 this.sizeCtl = cap;
2385 dl 1.1 }
2386    
2387     /**
2388 dl 1.16 * Creates a new map with the same mappings as the given map.
2389 dl 1.1 *
2390 dl 1.16 * @param m the map
2391 dl 1.1 */
2392 dl 1.16 public ConcurrentHashMapV8(Map<? extends K, ? extends V> m) {
2393     this.counter = new LongAdder();
2394 dl 1.24 this.sizeCtl = DEFAULT_CAPACITY;
2395 dl 1.27 internalPutAll(m);
2396 dl 1.1 }
2397    
2398     /**
2399 dl 1.16 * Creates a new, empty map with an initial table size based on
2400     * the given number of elements ({@code initialCapacity}) and
2401     * initial table density ({@code loadFactor}).
2402     *
2403     * @param initialCapacity the initial capacity. The implementation
2404     * performs internal sizing to accommodate this many elements,
2405     * given the specified load factor.
2406     * @param loadFactor the load factor (table density) for
2407 jsr166 1.18 * establishing the initial table size
2408 dl 1.16 * @throws IllegalArgumentException if the initial capacity of
2409     * elements is negative or the load factor is nonpositive
2410 jsr166 1.22 *
2411     * @since 1.6
2412 dl 1.1 */
2413 dl 1.16 public ConcurrentHashMapV8(int initialCapacity, float loadFactor) {
2414     this(initialCapacity, loadFactor, 1);
2415 dl 1.1 }
2416    
2417     /**
2418 dl 1.16 * Creates a new, empty map with an initial table size based on
2419     * the given number of elements ({@code initialCapacity}), table
2420     * density ({@code loadFactor}), and number of concurrently
2421     * updating threads ({@code concurrencyLevel}).
2422 dl 1.1 *
2423 dl 1.16 * @param initialCapacity the initial capacity. The implementation
2424     * performs internal sizing to accommodate this many elements,
2425     * given the specified load factor.
2426     * @param loadFactor the load factor (table density) for
2427 jsr166 1.18 * establishing the initial table size
2428 dl 1.16 * @param concurrencyLevel the estimated number of concurrently
2429     * updating threads. The implementation may use this value as
2430     * a sizing hint.
2431     * @throws IllegalArgumentException if the initial capacity is
2432     * negative or the load factor or concurrencyLevel are
2433 jsr166 1.18 * nonpositive
2434 dl 1.1 */
2435 dl 1.16 public ConcurrentHashMapV8(int initialCapacity,
2436     float loadFactor, int concurrencyLevel) {
2437     if (!(loadFactor > 0.0f) || initialCapacity < 0 || concurrencyLevel <= 0)
2438     throw new IllegalArgumentException();
2439     if (initialCapacity < concurrencyLevel) // Use at least as many bins
2440     initialCapacity = concurrencyLevel; // as estimated threads
2441     long size = (long)(1.0 + (long)initialCapacity / loadFactor);
2442 jsr166 1.49 int cap = (size >= (long)MAXIMUM_CAPACITY) ?
2443     MAXIMUM_CAPACITY : tableSizeFor((int)size);
2444 dl 1.16 this.counter = new LongAdder();
2445 dl 1.24 this.sizeCtl = cap;
2446 dl 1.1 }
2447    
2448     /**
2449 dl 1.14 * {@inheritDoc}
2450 dl 1.1 */
2451     public boolean isEmpty() {
2452 dl 1.2 return counter.sum() <= 0L; // ignore transient negative values
2453 dl 1.1 }
2454    
2455     /**
2456 dl 1.14 * {@inheritDoc}
2457 dl 1.1 */
2458     public int size() {
2459     long n = counter.sum();
2460 jsr166 1.15 return ((n < 0L) ? 0 :
2461     (n > (long)Integer.MAX_VALUE) ? Integer.MAX_VALUE :
2462 dl 1.14 (int)n);
2463 dl 1.1 }
2464    
2465 dl 1.52 /**
2466     * Returns the number of mappings. This method should be used
2467     * instead of {@link #size} because a ConcurrentHashMap may
2468     * contain more mappings than can be represented as an int. The
2469     * value returned is a snapshot; the actual count may differ if
2470 dl 1.60 * there are ongoing concurrent insertions or removals.
2471 dl 1.52 *
2472     * @return the number of mappings
2473     */
2474     public long mappingCount() {
2475 dl 1.24 long n = counter.sum();
2476 dl 1.59 return (n < 0L) ? 0L : n; // ignore transient negative values
2477 dl 1.24 }
2478    
2479 dl 1.1 /**
2480     * Returns the value to which the specified key is mapped,
2481     * or {@code null} if this map contains no mapping for the key.
2482     *
2483     * <p>More formally, if this map contains a mapping from a key
2484     * {@code k} to a value {@code v} such that {@code key.equals(k)},
2485     * then this method returns {@code v}; otherwise it returns
2486     * {@code null}. (There can be at most one such mapping.)
2487     *
2488     * @throws NullPointerException if the specified key is null
2489     */
2490 dl 1.61 @SuppressWarnings("unchecked") public V get(Object key) {
2491 dl 1.1 if (key == null)
2492     throw new NullPointerException();
2493     return (V)internalGet(key);
2494     }
2495    
2496     /**
2497     * Tests if the specified object is a key in this table.
2498     *
2499     * @param key possible key
2500     * @return {@code true} if and only if the specified object
2501     * is a key in this table, as determined by the
2502 jsr166 1.18 * {@code equals} method; {@code false} otherwise
2503 dl 1.1 * @throws NullPointerException if the specified key is null
2504     */
2505     public boolean containsKey(Object key) {
2506     if (key == null)
2507     throw new NullPointerException();
2508     return internalGet(key) != null;
2509     }
2510    
2511     /**
2512     * Returns {@code true} if this map maps one or more keys to the
2513 dl 1.14 * specified value. Note: This method may require a full traversal
2514     * of the map, and is much slower than method {@code containsKey}.
2515 dl 1.1 *
2516     * @param value value whose presence in this map is to be tested
2517     * @return {@code true} if this map maps one or more keys to the
2518     * specified value
2519     * @throws NullPointerException if the specified value is null
2520     */
2521     public boolean containsValue(Object value) {
2522     if (value == null)
2523     throw new NullPointerException();
2524 dl 1.14 Object v;
2525 dl 1.52 Traverser<K,V,Object> it = new Traverser<K,V,Object>(this);
2526 dl 1.41 while ((v = it.advance()) != null) {
2527     if (v == value || value.equals(v))
2528 dl 1.14 return true;
2529     }
2530     return false;
2531 dl 1.1 }
2532    
2533     /**
2534     * Legacy method testing if some key maps into the specified value
2535     * in this table. This method is identical in functionality to
2536     * {@link #containsValue}, and exists solely to ensure
2537     * full compatibility with class {@link java.util.Hashtable},
2538     * which supported this method prior to introduction of the
2539     * Java Collections framework.
2540     *
2541     * @param value a value to search for
2542     * @return {@code true} if and only if some key maps to the
2543     * {@code value} argument in this table as
2544     * determined by the {@code equals} method;
2545     * {@code false} otherwise
2546     * @throws NullPointerException if the specified value is null
2547     */
2548     public boolean contains(Object value) {
2549     return containsValue(value);
2550     }
2551    
2552     /**
2553     * Maps the specified key to the specified value in this table.
2554     * Neither the key nor the value can be null.
2555     *
2556     * <p> The value can be retrieved by calling the {@code get} method
2557     * with a key that is equal to the original key.
2558     *
2559     * @param key key with which the specified value is to be associated
2560     * @param value value to be associated with the specified key
2561     * @return the previous value associated with {@code key}, or
2562     * {@code null} if there was no mapping for {@code key}
2563     * @throws NullPointerException if the specified key or value is null
2564     */
2565 dl 1.61 @SuppressWarnings("unchecked") public V put(K key, V value) {
2566 dl 1.1 if (key == null || value == null)
2567     throw new NullPointerException();
2568 dl 1.27 return (V)internalPut(key, value);
2569 dl 1.1 }
2570    
2571     /**
2572     * {@inheritDoc}
2573     *
2574     * @return the previous value associated with the specified key,
2575     * or {@code null} if there was no mapping for the key
2576     * @throws NullPointerException if the specified key or value is null
2577     */
2578 dl 1.61 @SuppressWarnings("unchecked") public V putIfAbsent(K key, V value) {
2579 dl 1.1 if (key == null || value == null)
2580     throw new NullPointerException();
2581 dl 1.27 return (V)internalPutIfAbsent(key, value);
2582 dl 1.1 }
2583    
2584     /**
2585     * Copies all of the mappings from the specified map to this one.
2586     * These mappings replace any mappings that this map had for any of the
2587     * keys currently in the specified map.
2588     *
2589     * @param m mappings to be stored in this map
2590     */
2591     public void putAll(Map<? extends K, ? extends V> m) {
2592 dl 1.27 internalPutAll(m);
2593 dl 1.1 }
2594    
2595     /**
2596     * If the specified key is not already associated with a value,
2597 dl 1.41 * computes its value using the given mappingFunction and enters
2598     * it into the map unless null. This is equivalent to
2599 dl 1.27 * <pre> {@code
2600 jsr166 1.13 * if (map.containsKey(key))
2601     * return map.get(key);
2602 dl 1.52 * value = mappingFunction.apply(key);
2603 dl 1.41 * if (value != null)
2604     * map.put(key, value);
2605 jsr166 1.13 * return value;}</pre>
2606 dl 1.1 *
2607 dl 1.27 * except that the action is performed atomically. If the
2608 dl 1.41 * function returns {@code null} no mapping is recorded. If the
2609     * function itself throws an (unchecked) exception, the exception
2610     * is rethrown to its caller, and no mapping is recorded. Some
2611     * attempted update operations on this map by other threads may be
2612     * blocked while computation is in progress, so the computation
2613     * should be short and simple, and must not attempt to update any
2614     * other mappings of this Map. The most appropriate usage is to
2615     * construct a new object serving as an initial mapped value, or
2616     * memoized result, as in:
2617 dl 1.27 *
2618 jsr166 1.13 * <pre> {@code
2619 dl 1.52 * map.computeIfAbsent(key, new Fun<K, V>() {
2620 jsr166 1.13 * public V map(K k) { return new Value(f(k)); }});}</pre>
2621 dl 1.1 *
2622     * @param key key with which the specified value is to be associated
2623     * @param mappingFunction the function to compute a value
2624     * @return the current (existing or computed) value associated with
2625 dl 1.41 * the specified key, or null if the computed value is null.
2626     * @throws NullPointerException if the specified key or mappingFunction
2627     * is null
2628 dl 1.5 * @throws IllegalStateException if the computation detectably
2629     * attempts a recursive update to this map that would
2630 jsr166 1.18 * otherwise never complete
2631 dl 1.1 * @throws RuntimeException or Error if the mappingFunction does so,
2632 jsr166 1.18 * in which case the mapping is left unestablished
2633 dl 1.1 */
2634 dl 1.61 @SuppressWarnings("unchecked") public V computeIfAbsent
2635     (K key, Fun<? super K, ? extends V> mappingFunction) {
2636 dl 1.1 if (key == null || mappingFunction == null)
2637     throw new NullPointerException();
2638 dl 1.27 return (V)internalComputeIfAbsent(key, mappingFunction);
2639 dl 1.2 }
2640    
2641     /**
2642 dl 1.52 * If the given key is present, computes a new mapping value given a key and
2643     * its current mapped value. This is equivalent to
2644     * <pre> {@code
2645     * if (map.containsKey(key)) {
2646     * value = remappingFunction.apply(key, map.get(key));
2647     * if (value != null)
2648     * map.put(key, value);
2649     * else
2650     * map.remove(key);
2651     * }
2652     * }</pre>
2653     *
2654     * except that the action is performed atomically. If the
2655     * function returns {@code null}, the mapping is removed. If the
2656     * function itself throws an (unchecked) exception, the exception
2657     * is rethrown to its caller, and the current mapping is left
2658     * unchanged. Some attempted update operations on this map by
2659     * other threads may be blocked while computation is in progress,
2660     * so the computation should be short and simple, and must not
2661     * attempt to update any other mappings of this Map. For example,
2662     * to either create or append new messages to a value mapping:
2663     *
2664     * @param key key with which the specified value is to be associated
2665     * @param remappingFunction the function to compute a value
2666 jsr166 1.56 * @return the new value associated with the specified key, or null if none
2667 dl 1.52 * @throws NullPointerException if the specified key or remappingFunction
2668     * is null
2669     * @throws IllegalStateException if the computation detectably
2670     * attempts a recursive update to this map that would
2671     * otherwise never complete
2672     * @throws RuntimeException or Error if the remappingFunction does so,
2673     * in which case the mapping is unchanged
2674     */
2675 dl 1.61 @SuppressWarnings("unchecked") public V computeIfPresent
2676     (K key, BiFun<? super K, ? super V, ? extends V> remappingFunction) {
2677 dl 1.52 if (key == null || remappingFunction == null)
2678     throw new NullPointerException();
2679     return (V)internalCompute(key, true, remappingFunction);
2680     }
2681    
2682     /**
2683 dl 1.41 * Computes a new mapping value given a key and
2684 dl 1.27 * its current mapped value (or {@code null} if there is no current
2685     * mapping). This is equivalent to
2686 jsr166 1.13 * <pre> {@code
2687 dl 1.52 * value = remappingFunction.apply(key, map.get(key));
2688 dl 1.41 * if (value != null)
2689     * map.put(key, value);
2690     * else
2691     * map.remove(key);
2692 dl 1.27 * }</pre>
2693 dl 1.2 *
2694 dl 1.27 * except that the action is performed atomically. If the
2695 dl 1.41 * function returns {@code null}, the mapping is removed. If the
2696     * function itself throws an (unchecked) exception, the exception
2697     * is rethrown to its caller, and the current mapping is left
2698     * unchanged. Some attempted update operations on this map by
2699     * other threads may be blocked while computation is in progress,
2700     * so the computation should be short and simple, and must not
2701     * attempt to update any other mappings of this Map. For example,
2702     * to either create or append new messages to a value mapping:
2703 dl 1.27 *
2704     * <pre> {@code
2705     * Map<Key, String> map = ...;
2706     * final String msg = ...;
2707 dl 1.52 * map.compute(key, new BiFun<Key, String, String>() {
2708     * public String apply(Key k, String v) {
2709 dl 1.28 * return (v == null) ? msg : v + msg;});}}</pre>
2710 dl 1.2 *
2711     * @param key key with which the specified value is to be associated
2712 dl 1.27 * @param remappingFunction the function to compute a value
2713 jsr166 1.56 * @return the new value associated with the specified key, or null if none
2714 dl 1.27 * @throws NullPointerException if the specified key or remappingFunction
2715 dl 1.41 * is null
2716 dl 1.5 * @throws IllegalStateException if the computation detectably
2717     * attempts a recursive update to this map that would
2718 jsr166 1.18 * otherwise never complete
2719 dl 1.29 * @throws RuntimeException or Error if the remappingFunction does so,
2720 jsr166 1.18 * in which case the mapping is unchanged
2721 dl 1.2 */
2722 dl 1.61 @SuppressWarnings("unchecked") public V compute
2723     (K key, BiFun<? super K, ? super V, ? extends V> remappingFunction) {
2724 dl 1.27 if (key == null || remappingFunction == null)
2725 dl 1.2 throw new NullPointerException();
2726 dl 1.52 return (V)internalCompute(key, false, remappingFunction);
2727     }
2728    
2729     /**
2730     * If the specified key is not already associated
2731     * with a value, associate it with the given value.
2732     * Otherwise, replace the value with the results of
2733     * the given remapping function. This is equivalent to:
2734     * <pre> {@code
2735     * if (!map.containsKey(key))
2736     * map.put(value);
2737     * else {
2738     * newValue = remappingFunction.apply(map.get(key), value);
2739     * if (value != null)
2740     * map.put(key, value);
2741     * else
2742     * map.remove(key);
2743     * }
2744     * }</pre>
2745     * except that the action is performed atomically. If the
2746     * function returns {@code null}, the mapping is removed. If the
2747     * function itself throws an (unchecked) exception, the exception
2748     * is rethrown to its caller, and the current mapping is left
2749     * unchanged. Some attempted update operations on this map by
2750     * other threads may be blocked while computation is in progress,
2751     * so the computation should be short and simple, and must not
2752     * attempt to update any other mappings of this Map.
2753     */
2754 dl 1.61 @SuppressWarnings("unchecked") public V merge
2755     (K key, V value, BiFun<? super V, ? super V, ? extends V> remappingFunction) {
2756 dl 1.52 if (key == null || value == null || remappingFunction == null)
2757     throw new NullPointerException();
2758     return (V)internalMerge(key, value, remappingFunction);
2759 dl 1.1 }
2760    
2761     /**
2762     * Removes the key (and its corresponding value) from this map.
2763     * This method does nothing if the key is not in the map.
2764     *
2765     * @param key the key that needs to be removed
2766     * @return the previous value associated with {@code key}, or
2767     * {@code null} if there was no mapping for {@code key}
2768     * @throws NullPointerException if the specified key is null
2769     */
2770 dl 1.61 @SuppressWarnings("unchecked") public V remove(Object key) {
2771 dl 1.1 if (key == null)
2772     throw new NullPointerException();
2773 jsr166 1.3 return (V)internalReplace(key, null, null);
2774 dl 1.1 }
2775    
2776     /**
2777     * {@inheritDoc}
2778     *
2779     * @throws NullPointerException if the specified key is null
2780     */
2781     public boolean remove(Object key, Object value) {
2782     if (key == null)
2783     throw new NullPointerException();
2784     if (value == null)
2785     return false;
2786     return internalReplace(key, null, value) != null;
2787     }
2788    
2789     /**
2790     * {@inheritDoc}
2791     *
2792     * @throws NullPointerException if any of the arguments are null
2793     */
2794     public boolean replace(K key, V oldValue, V newValue) {
2795     if (key == null || oldValue == null || newValue == null)
2796     throw new NullPointerException();
2797 jsr166 1.3 return internalReplace(key, newValue, oldValue) != null;
2798 dl 1.1 }
2799    
2800     /**
2801     * {@inheritDoc}
2802     *
2803     * @return the previous value associated with the specified key,
2804     * or {@code null} if there was no mapping for the key
2805     * @throws NullPointerException if the specified key or value is null
2806     */
2807 dl 1.61 @SuppressWarnings("unchecked") public V replace(K key, V value) {
2808 dl 1.1 if (key == null || value == null)
2809     throw new NullPointerException();
2810 jsr166 1.3 return (V)internalReplace(key, value, null);
2811 dl 1.1 }
2812    
2813     /**
2814     * Removes all of the mappings from this map.
2815     */
2816     public void clear() {
2817     internalClear();
2818     }
2819    
2820     /**
2821     * Returns a {@link Set} view of the keys contained in this map.
2822     * The set is backed by the map, so changes to the map are
2823     * reflected in the set, and vice-versa. The set supports element
2824     * removal, which removes the corresponding mapping from this map,
2825     * via the {@code Iterator.remove}, {@code Set.remove},
2826     * {@code removeAll}, {@code retainAll}, and {@code clear}
2827     * operations. It does not support the {@code add} or
2828     * {@code addAll} operations.
2829     *
2830     * <p>The view's {@code iterator} is a "weakly consistent" iterator
2831     * that will never throw {@link ConcurrentModificationException},
2832     * and guarantees to traverse elements as they existed upon
2833     * construction of the iterator, and may (but is not guaranteed to)
2834     * reflect any modifications subsequent to construction.
2835     */
2836     public Set<K> keySet() {
2837 dl 1.14 KeySet<K,V> ks = keySet;
2838     return (ks != null) ? ks : (keySet = new KeySet<K,V>(this));
2839 dl 1.1 }
2840    
2841     /**
2842     * Returns a {@link Collection} view of the values contained in this map.
2843     * The collection is backed by the map, so changes to the map are
2844     * reflected in the collection, and vice-versa. The collection
2845     * supports element removal, which removes the corresponding
2846     * mapping from this map, via the {@code Iterator.remove},
2847     * {@code Collection.remove}, {@code removeAll},
2848     * {@code retainAll}, and {@code clear} operations. It does not
2849     * support the {@code add} or {@code addAll} operations.
2850     *
2851     * <p>The view's {@code iterator} is a "weakly consistent" iterator
2852     * that will never throw {@link ConcurrentModificationException},
2853     * and guarantees to traverse elements as they existed upon
2854     * construction of the iterator, and may (but is not guaranteed to)
2855     * reflect any modifications subsequent to construction.
2856     */
2857     public Collection<V> values() {
2858 dl 1.14 Values<K,V> vs = values;
2859     return (vs != null) ? vs : (values = new Values<K,V>(this));
2860 dl 1.1 }
2861    
2862     /**
2863     * Returns a {@link Set} view of the mappings contained in this map.
2864     * The set is backed by the map, so changes to the map are
2865     * reflected in the set, and vice-versa. The set supports element
2866     * removal, which removes the corresponding mapping from the map,
2867     * via the {@code Iterator.remove}, {@code Set.remove},
2868     * {@code removeAll}, {@code retainAll}, and {@code clear}
2869     * operations. It does not support the {@code add} or
2870     * {@code addAll} operations.
2871     *
2872     * <p>The view's {@code iterator} is a "weakly consistent" iterator
2873     * that will never throw {@link ConcurrentModificationException},
2874     * and guarantees to traverse elements as they existed upon
2875     * construction of the iterator, and may (but is not guaranteed to)
2876     * reflect any modifications subsequent to construction.
2877     */
2878     public Set<Map.Entry<K,V>> entrySet() {
2879 dl 1.14 EntrySet<K,V> es = entrySet;
2880     return (es != null) ? es : (entrySet = new EntrySet<K,V>(this));
2881 dl 1.1 }
2882    
2883     /**
2884     * Returns an enumeration of the keys in this table.
2885     *
2886     * @return an enumeration of the keys in this table
2887     * @see #keySet()
2888     */
2889     public Enumeration<K> keys() {
2890 dl 1.14 return new KeyIterator<K,V>(this);
2891 dl 1.1 }
2892    
2893     /**
2894     * Returns an enumeration of the values in this table.
2895     *
2896     * @return an enumeration of the values in this table
2897     * @see #values()
2898     */
2899     public Enumeration<V> elements() {
2900 dl 1.14 return new ValueIterator<K,V>(this);
2901 dl 1.1 }
2902    
2903     /**
2904 jsr166 1.55 * Returns a partitionable iterator of the keys in this map.
2905 dl 1.41 *
2906 jsr166 1.55 * @return a partitionable iterator of the keys in this map
2907 dl 1.41 */
2908     public Spliterator<K> keySpliterator() {
2909     return new KeyIterator<K,V>(this);
2910     }
2911    
2912     /**
2913 jsr166 1.55 * Returns a partitionable iterator of the values in this map.
2914 dl 1.41 *
2915 jsr166 1.55 * @return a partitionable iterator of the values in this map
2916 dl 1.41 */
2917     public Spliterator<V> valueSpliterator() {
2918     return new ValueIterator<K,V>(this);
2919     }
2920    
2921     /**
2922 jsr166 1.55 * Returns a partitionable iterator of the entries in this map.
2923 dl 1.41 *
2924 jsr166 1.55 * @return a partitionable iterator of the entries in this map
2925 dl 1.41 */
2926     public Spliterator<Map.Entry<K,V>> entrySpliterator() {
2927     return new EntryIterator<K,V>(this);
2928     }
2929    
2930     /**
2931 dl 1.2 * Returns the hash code value for this {@link Map}, i.e.,
2932     * the sum of, for each key-value pair in the map,
2933     * {@code key.hashCode() ^ value.hashCode()}.
2934     *
2935     * @return the hash code value for this map
2936 dl 1.1 */
2937     public int hashCode() {
2938 dl 1.14 int h = 0;
2939 dl 1.52 Traverser<K,V,Object> it = new Traverser<K,V,Object>(this);
2940 dl 1.41 Object v;
2941     while ((v = it.advance()) != null) {
2942     h += it.nextKey.hashCode() ^ v.hashCode();
2943 dl 1.14 }
2944     return h;
2945 dl 1.1 }
2946    
2947     /**
2948 dl 1.2 * Returns a string representation of this map. The string
2949     * representation consists of a list of key-value mappings (in no
2950     * particular order) enclosed in braces ("{@code {}}"). Adjacent
2951     * mappings are separated by the characters {@code ", "} (comma
2952     * and space). Each key-value mapping is rendered as the key
2953     * followed by an equals sign ("{@code =}") followed by the
2954     * associated value.
2955     *
2956     * @return a string representation of this map
2957 dl 1.1 */
2958     public String toString() {
2959 dl 1.52 Traverser<K,V,Object> it = new Traverser<K,V,Object>(this);
2960 dl 1.14 StringBuilder sb = new StringBuilder();
2961     sb.append('{');
2962 dl 1.41 Object v;
2963     if ((v = it.advance()) != null) {
2964 dl 1.14 for (;;) {
2965 dl 1.41 Object k = it.nextKey;
2966 dl 1.14 sb.append(k == this ? "(this Map)" : k);
2967     sb.append('=');
2968     sb.append(v == this ? "(this Map)" : v);
2969 dl 1.41 if ((v = it.advance()) == null)
2970 dl 1.14 break;
2971     sb.append(',').append(' ');
2972     }
2973     }
2974     return sb.append('}').toString();
2975 dl 1.1 }
2976    
2977     /**
2978 dl 1.2 * Compares the specified object with this map for equality.
2979     * Returns {@code true} if the given object is a map with the same
2980     * mappings as this map. This operation may return misleading
2981     * results if either map is concurrently modified during execution
2982     * of this method.
2983     *
2984     * @param o object to be compared for equality with this map
2985     * @return {@code true} if the specified object is equal to this map
2986 dl 1.1 */
2987     public boolean equals(Object o) {
2988 dl 1.14 if (o != this) {
2989     if (!(o instanceof Map))
2990     return false;
2991     Map<?,?> m = (Map<?,?>) o;
2992 dl 1.52 Traverser<K,V,Object> it = new Traverser<K,V,Object>(this);
2993 dl 1.41 Object val;
2994     while ((val = it.advance()) != null) {
2995 dl 1.14 Object v = m.get(it.nextKey);
2996     if (v == null || (v != val && !v.equals(val)))
2997 dl 1.1 return false;
2998 dl 1.14 }
2999 dl 1.1 for (Map.Entry<?,?> e : m.entrySet()) {
3000 dl 1.14 Object mk, mv, v;
3001     if ((mk = e.getKey()) == null ||
3002     (mv = e.getValue()) == null ||
3003     (v = internalGet(mk)) == null ||
3004     (mv != v && !mv.equals(v)))
3005 dl 1.1 return false;
3006     }
3007 dl 1.14 }
3008     return true;
3009     }
3010    
3011     /* ----------------Iterators -------------- */
3012    
3013 dl 1.61 @SuppressWarnings("serial") static final class KeyIterator<K,V> extends Traverser<K,V,Object>
3014 dl 1.41 implements Spliterator<K>, Enumeration<K> {
3015     KeyIterator(ConcurrentHashMapV8<K, V> map) { super(map); }
3016 dl 1.61 KeyIterator(Traverser<K,V,Object> it) {
3017     super(it);
3018 dl 1.41 }
3019     public KeyIterator<K,V> split() {
3020     if (last != null || (next != null && nextVal == null))
3021     throw new IllegalStateException();
3022 dl 1.61 return new KeyIterator<K,V>(this);
3023 dl 1.14 }
3024 dl 1.61 @SuppressWarnings("unchecked") public final K next() {
3025 dl 1.41 if (nextVal == null && advance() == null)
3026 dl 1.14 throw new NoSuchElementException();
3027     Object k = nextKey;
3028 dl 1.41 nextVal = null;
3029     return (K) k;
3030 dl 1.14 }
3031    
3032     public final K nextElement() { return next(); }
3033     }
3034    
3035 dl 1.61 @SuppressWarnings("serial") static final class ValueIterator<K,V> extends Traverser<K,V,Object>
3036 dl 1.41 implements Spliterator<V>, Enumeration<V> {
3037 dl 1.14 ValueIterator(ConcurrentHashMapV8<K, V> map) { super(map); }
3038 dl 1.61 ValueIterator(Traverser<K,V,Object> it) {
3039     super(it);
3040 dl 1.41 }
3041     public ValueIterator<K,V> split() {
3042     if (last != null || (next != null && nextVal == null))
3043     throw new IllegalStateException();
3044 dl 1.61 return new ValueIterator<K,V>(this);
3045 dl 1.41 }
3046    
3047 dl 1.61 @SuppressWarnings("unchecked") public final V next() {
3048 dl 1.41 Object v;
3049     if ((v = nextVal) == null && (v = advance()) == null)
3050 dl 1.14 throw new NoSuchElementException();
3051 dl 1.41 nextVal = null;
3052     return (V) v;
3053 dl 1.14 }
3054    
3055     public final V nextElement() { return next(); }
3056     }
3057    
3058 dl 1.61 @SuppressWarnings("serial") static final class EntryIterator<K,V> extends Traverser<K,V,Object>
3059 dl 1.41 implements Spliterator<Map.Entry<K,V>> {
3060 dl 1.14 EntryIterator(ConcurrentHashMapV8<K, V> map) { super(map); }
3061 dl 1.61 EntryIterator(Traverser<K,V,Object> it) {
3062     super(it);
3063 dl 1.41 }
3064     public EntryIterator<K,V> split() {
3065     if (last != null || (next != null && nextVal == null))
3066     throw new IllegalStateException();
3067 dl 1.61 return new EntryIterator<K,V>(this);
3068 dl 1.41 }
3069 dl 1.24
3070 dl 1.61 @SuppressWarnings("unchecked") public final Map.Entry<K,V> next() {
3071 dl 1.41 Object v;
3072     if ((v = nextVal) == null && (v = advance()) == null)
3073 dl 1.24 throw new NoSuchElementException();
3074     Object k = nextKey;
3075 dl 1.41 nextVal = null;
3076     return new MapEntry<K,V>((K)k, (V)v, map);
3077 dl 1.1 }
3078     }
3079    
3080     /**
3081 dl 1.41 * Exported Entry for iterators
3082 dl 1.1 */
3083 dl 1.41 static final class MapEntry<K,V> implements Map.Entry<K, V> {
3084 dl 1.14 final K key; // non-null
3085     V val; // non-null
3086 dl 1.41 final ConcurrentHashMapV8<K, V> map;
3087     MapEntry(K key, V val, ConcurrentHashMapV8<K, V> map) {
3088     this.key = key;
3089     this.val = val;
3090     this.map = map;
3091     }
3092 dl 1.14 public final K getKey() { return key; }
3093     public final V getValue() { return val; }
3094     public final int hashCode() { return key.hashCode() ^ val.hashCode(); }
3095     public final String toString(){ return key + "=" + val; }
3096    
3097     public final boolean equals(Object o) {
3098     Object k, v; Map.Entry<?,?> e;
3099     return ((o instanceof Map.Entry) &&
3100     (k = (e = (Map.Entry<?,?>)o).getKey()) != null &&
3101     (v = e.getValue()) != null &&
3102     (k == key || k.equals(key)) &&
3103     (v == val || v.equals(val)));
3104 dl 1.1 }
3105    
3106     /**
3107     * Sets our entry's value and writes through to the map. The
3108 jsr166 1.50 * value to return is somewhat arbitrary here. Since we do not
3109     * necessarily track asynchronous changes, the most recent
3110 dl 1.41 * "previous" value could be different from what we return (or
3111     * could even have been removed in which case the put will
3112     * re-establish). We do not and cannot guarantee more.
3113 dl 1.1 */
3114 dl 1.14 public final V setValue(V value) {
3115 dl 1.1 if (value == null) throw new NullPointerException();
3116 dl 1.14 V v = val;
3117     val = value;
3118     map.put(key, value);
3119 dl 1.1 return v;
3120     }
3121     }
3122    
3123 dl 1.14 /* ----------------Views -------------- */
3124 dl 1.1
3125 dl 1.24 /**
3126 dl 1.41 * Base class for views.
3127 dl 1.14 */
3128 dl 1.52 static abstract class CHMView<K, V> {
3129 dl 1.14 final ConcurrentHashMapV8<K, V> map;
3130 dl 1.52 CHMView(ConcurrentHashMapV8<K, V> map) { this.map = map; }
3131 dl 1.14 public final int size() { return map.size(); }
3132     public final boolean isEmpty() { return map.isEmpty(); }
3133     public final void clear() { map.clear(); }
3134 dl 1.24
3135     // implementations below rely on concrete classes supplying these
3136 dl 1.41 abstract public Iterator<?> iterator();
3137 dl 1.24 abstract public boolean contains(Object o);
3138     abstract public boolean remove(Object o);
3139    
3140     private static final String oomeMsg = "Required array size too large";
3141    
3142     public final Object[] toArray() {
3143 dl 1.52 long sz = map.mappingCount();
3144 dl 1.24 if (sz > (long)(MAX_ARRAY_SIZE))
3145     throw new OutOfMemoryError(oomeMsg);
3146     int n = (int)sz;
3147     Object[] r = new Object[n];
3148     int i = 0;
3149 dl 1.41 Iterator<?> it = iterator();
3150 dl 1.24 while (it.hasNext()) {
3151     if (i == n) {
3152     if (n >= MAX_ARRAY_SIZE)
3153     throw new OutOfMemoryError(oomeMsg);
3154     if (n >= MAX_ARRAY_SIZE - (MAX_ARRAY_SIZE >>> 1) - 1)
3155     n = MAX_ARRAY_SIZE;
3156     else
3157     n += (n >>> 1) + 1;
3158     r = Arrays.copyOf(r, n);
3159     }
3160     r[i++] = it.next();
3161     }
3162     return (i == n) ? r : Arrays.copyOf(r, i);
3163     }
3164    
3165 dl 1.61 @SuppressWarnings("unchecked") public final <T> T[] toArray(T[] a) {
3166 dl 1.52 long sz = map.mappingCount();
3167 dl 1.24 if (sz > (long)(MAX_ARRAY_SIZE))
3168     throw new OutOfMemoryError(oomeMsg);
3169     int m = (int)sz;
3170     T[] r = (a.length >= m) ? a :
3171     (T[])java.lang.reflect.Array
3172     .newInstance(a.getClass().getComponentType(), m);
3173     int n = r.length;
3174     int i = 0;
3175 dl 1.41 Iterator<?> it = iterator();
3176 dl 1.24 while (it.hasNext()) {
3177     if (i == n) {
3178     if (n >= MAX_ARRAY_SIZE)
3179     throw new OutOfMemoryError(oomeMsg);
3180     if (n >= MAX_ARRAY_SIZE - (MAX_ARRAY_SIZE >>> 1) - 1)
3181     n = MAX_ARRAY_SIZE;
3182     else
3183     n += (n >>> 1) + 1;
3184     r = Arrays.copyOf(r, n);
3185     }
3186     r[i++] = (T)it.next();
3187     }
3188     if (a == r && i < n) {
3189     r[i] = null; // null-terminate
3190     return r;
3191     }
3192     return (i == n) ? r : Arrays.copyOf(r, i);
3193     }
3194    
3195     public final int hashCode() {
3196     int h = 0;
3197 dl 1.41 for (Iterator<?> it = iterator(); it.hasNext();)
3198 dl 1.24 h += it.next().hashCode();
3199     return h;
3200     }
3201    
3202     public final String toString() {
3203     StringBuilder sb = new StringBuilder();
3204     sb.append('[');
3205 dl 1.41 Iterator<?> it = iterator();
3206 dl 1.24 if (it.hasNext()) {
3207     for (;;) {
3208     Object e = it.next();
3209     sb.append(e == this ? "(this Collection)" : e);
3210     if (!it.hasNext())
3211     break;
3212     sb.append(',').append(' ');
3213     }
3214     }
3215     return sb.append(']').toString();
3216     }
3217    
3218     public final boolean containsAll(Collection<?> c) {
3219     if (c != this) {
3220     for (Iterator<?> it = c.iterator(); it.hasNext();) {
3221     Object e = it.next();
3222     if (e == null || !contains(e))
3223     return false;
3224     }
3225     }
3226     return true;
3227     }
3228    
3229 jsr166 1.32 public final boolean removeAll(Collection<?> c) {
3230 dl 1.24 boolean modified = false;
3231 dl 1.41 for (Iterator<?> it = iterator(); it.hasNext();) {
3232 dl 1.24 if (c.contains(it.next())) {
3233     it.remove();
3234     modified = true;
3235     }
3236     }
3237     return modified;
3238     }
3239    
3240     public final boolean retainAll(Collection<?> c) {
3241     boolean modified = false;
3242 dl 1.41 for (Iterator<?> it = iterator(); it.hasNext();) {
3243 dl 1.24 if (!c.contains(it.next())) {
3244     it.remove();
3245     modified = true;
3246     }
3247     }
3248     return modified;
3249     }
3250    
3251     }
3252    
3253 dl 1.52 static final class KeySet<K,V> extends CHMView<K,V> implements Set<K> {
3254     KeySet(ConcurrentHashMapV8<K, V> map) {
3255     super(map);
3256     }
3257 dl 1.14 public final boolean contains(Object o) { return map.containsKey(o); }
3258     public final boolean remove(Object o) { return map.remove(o) != null; }
3259     public final Iterator<K> iterator() {
3260     return new KeyIterator<K,V>(map);
3261 dl 1.1 }
3262 dl 1.24 public final boolean add(K e) {
3263     throw new UnsupportedOperationException();
3264     }
3265     public final boolean addAll(Collection<? extends K> c) {
3266     throw new UnsupportedOperationException();
3267     }
3268     public boolean equals(Object o) {
3269     Set<?> c;
3270     return ((o instanceof Set) &&
3271     ((c = (Set<?>)o) == this ||
3272     (containsAll(c) && c.containsAll(this))));
3273     }
3274 dl 1.1 }
3275    
3276 dl 1.52
3277     static final class Values<K,V> extends CHMView<K,V>
3278 jsr166 1.34 implements Collection<V> {
3279 dl 1.24 Values(ConcurrentHashMapV8<K, V> map) { super(map); }
3280     public final boolean contains(Object o) { return map.containsValue(o); }
3281     public final boolean remove(Object o) {
3282     if (o != null) {
3283     Iterator<V> it = new ValueIterator<K,V>(map);
3284     while (it.hasNext()) {
3285     if (o.equals(it.next())) {
3286     it.remove();
3287     return true;
3288     }
3289     }
3290     }
3291     return false;
3292     }
3293 dl 1.14 public final Iterator<V> iterator() {
3294     return new ValueIterator<K,V>(map);
3295 dl 1.1 }
3296 dl 1.24 public final boolean add(V e) {
3297     throw new UnsupportedOperationException();
3298     }
3299     public final boolean addAll(Collection<? extends V> c) {
3300     throw new UnsupportedOperationException();
3301     }
3302 dl 1.52
3303 dl 1.1 }
3304    
3305 dl 1.52 static final class EntrySet<K,V> extends CHMView<K,V>
3306 dl 1.24 implements Set<Map.Entry<K,V>> {
3307     EntrySet(ConcurrentHashMapV8<K, V> map) { super(map); }
3308 dl 1.14 public final boolean contains(Object o) {
3309     Object k, v, r; Map.Entry<?,?> e;
3310     return ((o instanceof Map.Entry) &&
3311     (k = (e = (Map.Entry<?,?>)o).getKey()) != null &&
3312     (r = map.get(k)) != null &&
3313     (v = e.getValue()) != null &&
3314     (v == r || v.equals(r)));
3315 dl 1.1 }
3316 dl 1.14 public final boolean remove(Object o) {
3317     Object k, v; Map.Entry<?,?> e;
3318     return ((o instanceof Map.Entry) &&
3319     (k = (e = (Map.Entry<?,?>)o).getKey()) != null &&
3320     (v = e.getValue()) != null &&
3321     map.remove(k, v));
3322 dl 1.1 }
3323 dl 1.24 public final Iterator<Map.Entry<K,V>> iterator() {
3324     return new EntryIterator<K,V>(map);
3325     }
3326     public final boolean add(Entry<K,V> e) {
3327     throw new UnsupportedOperationException();
3328     }
3329     public final boolean addAll(Collection<? extends Entry<K,V>> c) {
3330     throw new UnsupportedOperationException();
3331     }
3332     public boolean equals(Object o) {
3333     Set<?> c;
3334     return ((o instanceof Set) &&
3335     ((c = (Set<?>)o) == this ||
3336     (containsAll(c) && c.containsAll(this))));
3337     }
3338 dl 1.1 }
3339    
3340     /* ---------------- Serialization Support -------------- */
3341    
3342     /**
3343 dl 1.14 * Stripped-down version of helper class used in previous version,
3344     * declared for the sake of serialization compatibility
3345 dl 1.1 */
3346 dl 1.14 static class Segment<K,V> implements Serializable {
3347 dl 1.1 private static final long serialVersionUID = 2249069246763182397L;
3348     final float loadFactor;
3349     Segment(float lf) { this.loadFactor = lf; }
3350     }
3351    
3352     /**
3353     * Saves the state of the {@code ConcurrentHashMapV8} instance to a
3354     * stream (i.e., serializes it).
3355     * @param s the stream
3356     * @serialData
3357     * the key (Object) and value (Object)
3358     * for each key-value mapping, followed by a null pair.
3359     * The key-value mappings are emitted in no particular order.
3360     */
3361 dl 1.61 @SuppressWarnings("unchecked") private void writeObject(java.io.ObjectOutputStream s)
3362 dl 1.52 throws java.io.IOException {
3363 dl 1.1 if (segments == null) { // for serialization compatibility
3364     segments = (Segment<K,V>[])
3365     new Segment<?,?>[DEFAULT_CONCURRENCY_LEVEL];
3366     for (int i = 0; i < segments.length; ++i)
3367 dl 1.16 segments[i] = new Segment<K,V>(LOAD_FACTOR);
3368 dl 1.1 }
3369     s.defaultWriteObject();
3370 dl 1.52 Traverser<K,V,Object> it = new Traverser<K,V,Object>(this);
3371 dl 1.41 Object v;
3372     while ((v = it.advance()) != null) {
3373 dl 1.14 s.writeObject(it.nextKey);
3374 dl 1.41 s.writeObject(v);
3375 dl 1.14 }
3376 dl 1.1 s.writeObject(null);
3377     s.writeObject(null);
3378     segments = null; // throw away
3379     }
3380    
3381     /**
3382 jsr166 1.9 * Reconstitutes the instance from a stream (that is, deserializes it).
3383 dl 1.1 * @param s the stream
3384     */
3385 dl 1.61 @SuppressWarnings("unchecked") private void readObject(java.io.ObjectInputStream s)
3386 dl 1.52 throws java.io.IOException, ClassNotFoundException {
3387 dl 1.1 s.defaultReadObject();
3388     this.segments = null; // unneeded
3389 jsr166 1.21 // initialize transient final field
3390 dl 1.14 UNSAFE.putObjectVolatile(this, counterOffset, new LongAdder());
3391    
3392     // Create all nodes, then place in table once size is known
3393     long size = 0L;
3394     Node p = null;
3395 dl 1.1 for (;;) {
3396 dl 1.14 K k = (K) s.readObject();
3397     V v = (V) s.readObject();
3398     if (k != null && v != null) {
3399 dl 1.38 int h = spread(k.hashCode());
3400     p = new Node(h, k, v, p);
3401 dl 1.14 ++size;
3402     }
3403     else
3404 dl 1.1 break;
3405 dl 1.14 }
3406     if (p != null) {
3407     boolean init = false;
3408 dl 1.24 int n;
3409     if (size >= (long)(MAXIMUM_CAPACITY >>> 1))
3410     n = MAXIMUM_CAPACITY;
3411     else {
3412     int sz = (int)size;
3413     n = tableSizeFor(sz + (sz >>> 1) + 1);
3414     }
3415     int sc = sizeCtl;
3416 dl 1.38 boolean collide = false;
3417 dl 1.24 if (n > sc &&
3418     UNSAFE.compareAndSwapInt(this, sizeCtlOffset, sc, -1)) {
3419 dl 1.14 try {
3420     if (table == null) {
3421     init = true;
3422     Node[] tab = new Node[n];
3423     int mask = n - 1;
3424     while (p != null) {
3425     int j = p.hash & mask;
3426     Node next = p.next;
3427 dl 1.38 Node q = p.next = tabAt(tab, j);
3428 dl 1.14 setTabAt(tab, j, p);
3429 dl 1.38 if (!collide && q != null && q.hash == p.hash)
3430     collide = true;
3431 dl 1.14 p = next;
3432     }
3433     table = tab;
3434     counter.add(size);
3435 dl 1.29 sc = n - (n >>> 2);
3436 dl 1.14 }
3437     } finally {
3438 dl 1.24 sizeCtl = sc;
3439 dl 1.14 }
3440 dl 1.38 if (collide) { // rescan and convert to TreeBins
3441     Node[] tab = table;
3442     for (int i = 0; i < tab.length; ++i) {
3443     int c = 0;
3444     for (Node e = tabAt(tab, i); e != null; e = e.next) {
3445     if (++c > TREE_THRESHOLD &&
3446     (e.key instanceof Comparable)) {
3447     replaceWithTreeBin(tab, i, e.key);
3448     break;
3449     }
3450     }
3451     }
3452     }
3453 dl 1.14 }
3454     if (!init) { // Can only happen if unsafely published.
3455     while (p != null) {
3456 dl 1.27 internalPut(p.key, p.val);
3457 dl 1.14 p = p.next;
3458     }
3459     }
3460 dl 1.1 }
3461     }
3462    
3463    
3464 dl 1.52 // -------------------------------------------------------
3465    
3466     // Sams
3467     /** Interface describing a void action of one argument */
3468     public interface Action<A> { void apply(A a); }
3469     /** Interface describing a void action of two arguments */
3470     public interface BiAction<A,B> { void apply(A a, B b); }
3471     /** Interface describing a function of one argument */
3472     public interface Fun<A,T> { T apply(A a); }
3473     /** Interface describing a function of two arguments */
3474     public interface BiFun<A,B,T> { T apply(A a, B b); }
3475     /** Interface describing a function of no arguments */
3476     public interface Generator<T> { T apply(); }
3477     /** Interface describing a function mapping its argument to a double */
3478     public interface ObjectToDouble<A> { double apply(A a); }
3479     /** Interface describing a function mapping its argument to a long */
3480     public interface ObjectToLong<A> { long apply(A a); }
3481     /** Interface describing a function mapping its argument to an int */
3482     public interface ObjectToInt<A> {int apply(A a); }
3483     /** Interface describing a function mapping two arguments to a double */
3484     public interface ObjectByObjectToDouble<A,B> { double apply(A a, B b); }
3485     /** Interface describing a function mapping two arguments to a long */
3486     public interface ObjectByObjectToLong<A,B> { long apply(A a, B b); }
3487     /** Interface describing a function mapping two arguments to an int */
3488     public interface ObjectByObjectToInt<A,B> {int apply(A a, B b); }
3489     /** Interface describing a function mapping a double to a double */
3490     public interface DoubleToDouble { double apply(double a); }
3491     /** Interface describing a function mapping a long to a long */
3492     public interface LongToLong { long apply(long a); }
3493     /** Interface describing a function mapping an int to an int */
3494     public interface IntToInt { int apply(int a); }
3495     /** Interface describing a function mapping two doubles to a double */
3496     public interface DoubleByDoubleToDouble { double apply(double a, double b); }
3497     /** Interface describing a function mapping two longs to a long */
3498     public interface LongByLongToLong { long apply(long a, long b); }
3499     /** Interface describing a function mapping two ints to an int */
3500     public interface IntByIntToInt { int apply(int a, int b); }
3501    
3502    
3503     // -------------------------------------------------------
3504    
3505     /**
3506     * Returns an extended {@link Parallel} view of this map using the
3507     * given executor for bulk parallel operations.
3508     *
3509     * @param executor the executor
3510     * @return a parallel view
3511     */
3512     public Parallel parallel(ForkJoinPool executor) {
3513     return new Parallel(executor);
3514     }
3515    
3516     /**
3517     * An extended view of a ConcurrentHashMap supporting bulk
3518 jsr166 1.54 * parallel operations. These operations are designed to be
3519 dl 1.52 * safely, and often sensibly, applied even with maps that are
3520     * being concurrently updated by other threads; for example, when
3521     * computing a snapshot summary of the values in a shared
3522     * registry. There are three kinds of operation, each with four
3523     * forms, accepting functions with Keys, Values, Entries, and
3524     * (Key, Value) arguments and/or return values. Because the
3525     * elements of a ConcurrentHashMap are not ordered in any
3526     * particular way, and may be processed in different orders in
3527     * different parallel executions, the correctness of supplied
3528     * functions should not depend on any ordering, or on any other
3529     * objects or values that may transiently change while computation
3530     * is in progress; and except for forEach actions, should ideally
3531     * be side-effect-free.
3532     *
3533     * <ul>
3534     * <li> forEach: Perform a given action on each element.
3535     * A variant form applies a given transformation on each element
3536     * before performing the action.</li>
3537     *
3538     * <li> search: Return the first available non-null result of
3539     * applying a given function on each element; skipping further
3540     * search when a result is found.</li>
3541     *
3542     * <li> reduce: Accumulate each element. The supplied reduction
3543     * function cannot rely on ordering (more formally, it should be
3544     * both associative and commutative). There are five variants:
3545     *
3546     * <ul>
3547     *
3548     * <li> Plain reductions. (There is not a form of this method for
3549     * (key, value) function arguments since there is no corresponding
3550     * return type.)</li>
3551     *
3552     * <li> Mapped reductions that accumulate the results of a given
3553     * function applied to each element.</li>
3554     *
3555     * <li> Reductions to scalar doubles, longs, and ints, using a
3556     * given basis value.</li>
3557     *
3558     * </li>
3559     * </ul>
3560     * </ul>
3561     *
3562     * <p>The concurrency properties of the bulk operations follow
3563     * from those of ConcurrentHashMap: Any non-null result returned
3564     * from {@code get(key)} and related access methods bears a
3565     * happens-before relation with the associated insertion or
3566     * update. The result of any bulk operation reflects the
3567     * composition of these per-element relations (but is not
3568     * necessarily atomic with respect to the map as a whole unless it
3569     * is somehow known to be quiescent). Conversely, because keys
3570     * and values in the map are never null, null serves as a reliable
3571     * atomic indicator of the current lack of any result. To
3572     * maintain this property, null serves as an implicit basis for
3573     * all non-scalar reduction operations. For the double, long, and
3574     * int versions, the basis should be one that, when combined with
3575     * any other value, returns that other value (more formally, it
3576     * should be the identity element for the reduction). Most common
3577     * reductions have these properties; for example, computing a sum
3578     * with basis 0 or a minimum with basis MAX_VALUE.
3579     *
3580     * <p>Search and transformation functions provided as arguments
3581     * should similarly return null to indicate the lack of any result
3582     * (in which case it is not used). In the case of mapped
3583     * reductions, this also enables transformations to serve as
3584     * filters, returning null (or, in the case of primitive
3585     * specializations, the identity basis) if the element should not
3586     * be combined. You can create compound transformations and
3587     * filterings by composing them yourself under this "null means
3588     * there is nothing there now" rule before using them in search or
3589     * reduce operations.
3590     *
3591     * <p>Methods accepting and/or returning Entry arguments maintain
3592     * key-value associations. They may be useful for example when
3593     * finding the key for the greatest value. Note that "plain" Entry
3594     * arguments can be supplied using {@code new
3595     * AbstractMap.SimpleEntry(k,v)}.
3596     *
3597     * <p> Bulk operations may complete abruptly, throwing an
3598     * exception encountered in the application of a supplied
3599     * function. Bear in mind when handling such exceptions that other
3600     * concurrently executing functions could also have thrown
3601     * exceptions, or would have done so if the first exception had
3602     * not occurred.
3603     *
3604     * <p>Parallel speedups compared to sequential processing are
3605     * common but not guaranteed. Operations involving brief
3606     * functions on small maps may execute more slowly than sequential
3607     * loops if the underlying work to parallelize the computation is
3608     * more expensive than the computation itself. Similarly,
3609     * parallelization may not lead to much actual parallelism if all
3610     * processors are busy performing unrelated tasks.
3611     *
3612     * <p> All arguments to all task methods must be non-null.
3613     *
3614     * <p><em>jsr166e note: During transition, this class
3615     * uses nested functional interfaces with different names but the
3616     * same forms as those expected for JDK8.<em>
3617     */
3618     public class Parallel {
3619     final ForkJoinPool fjp;
3620    
3621     /**
3622     * Returns an extended view of this map using the given
3623     * executor for bulk parallel operations.
3624     *
3625     * @param executor the executor
3626     */
3627     public Parallel(ForkJoinPool executor) {
3628     this.fjp = executor;
3629     }
3630    
3631     /**
3632     * Performs the given action for each (key, value).
3633     *
3634     * @param action the action
3635     */
3636 jsr166 1.53 public void forEach(BiAction<K,V> action) {
3637 dl 1.52 fjp.invoke(ForkJoinTasks.forEach
3638     (ConcurrentHashMapV8.this, action));
3639     }
3640    
3641     /**
3642     * Performs the given action for each non-null transformation
3643     * of each (key, value).
3644     *
3645     * @param transformer a function returning the transformation
3646     * for an element, or null of there is no transformation (in
3647     * which case the action is not applied).
3648     * @param action the action
3649     */
3650 jsr166 1.53 public <U> void forEach(BiFun<? super K, ? super V, ? extends U> transformer,
3651 dl 1.52 Action<U> action) {
3652     fjp.invoke(ForkJoinTasks.forEach
3653     (ConcurrentHashMapV8.this, transformer, action));
3654     }
3655    
3656     /**
3657     * Returns a non-null result from applying the given search
3658 dl 1.59 * function on each (key, value), or null if none. Upon
3659     * success, further element processing is suppressed and the
3660     * results of any other parallel invocations of the search
3661     * function are ignored.
3662 dl 1.52 *
3663     * @param searchFunction a function returning a non-null
3664     * result on success, else null
3665     * @return a non-null result from applying the given search
3666     * function on each (key, value), or null if none
3667     */
3668     public <U> U search(BiFun<? super K, ? super V, ? extends U> searchFunction) {
3669     return fjp.invoke(ForkJoinTasks.search
3670     (ConcurrentHashMapV8.this, searchFunction));
3671 dl 1.1 }
3672    
3673 dl 1.52 /**
3674     * Returns the result of accumulating the given transformation
3675     * of all (key, value) pairs using the given reducer to
3676     * combine values, or null if none.
3677     *
3678     * @param transformer a function returning the transformation
3679     * for an element, or null of there is no transformation (in
3680     * which case it is not combined).
3681     * @param reducer a commutative associative combining function
3682     * @return the result of accumulating the given transformation
3683     * of all (key, value) pairs
3684     */
3685     public <U> U reduce(BiFun<? super K, ? super V, ? extends U> transformer,
3686     BiFun<? super U, ? super U, ? extends U> reducer) {
3687     return fjp.invoke(ForkJoinTasks.reduce
3688     (ConcurrentHashMapV8.this, transformer, reducer));
3689 dl 1.1 }
3690    
3691 dl 1.52 /**
3692     * Returns the result of accumulating the given transformation
3693     * of all (key, value) pairs using the given reducer to
3694     * combine values, and the given basis as an identity value.
3695     *
3696     * @param transformer a function returning the transformation
3697     * for an element
3698     * @param basis the identity (initial default value) for the reduction
3699     * @param reducer a commutative associative combining function
3700     * @return the result of accumulating the given transformation
3701     * of all (key, value) pairs
3702     */
3703     public double reduceToDouble(ObjectByObjectToDouble<? super K, ? super V> transformer,
3704     double basis,
3705     DoubleByDoubleToDouble reducer) {
3706     return fjp.invoke(ForkJoinTasks.reduceToDouble
3707     (ConcurrentHashMapV8.this, transformer, basis, reducer));
3708     }
3709    
3710     /**
3711     * Returns the result of accumulating the given transformation
3712     * of all (key, value) pairs using the given reducer to
3713     * combine values, and the given basis as an identity value.
3714     *
3715     * @param transformer a function returning the transformation
3716     * for an element
3717     * @param basis the identity (initial default value) for the reduction
3718     * @param reducer a commutative associative combining function
3719     * @return the result of accumulating the given transformation
3720 dl 1.59 * of all (key, value) pairs
3721 dl 1.52 */
3722     public long reduceToLong(ObjectByObjectToLong<? super K, ? super V> transformer,
3723     long basis,
3724     LongByLongToLong reducer) {
3725     return fjp.invoke(ForkJoinTasks.reduceToLong
3726     (ConcurrentHashMapV8.this, transformer, basis, reducer));
3727     }
3728    
3729     /**
3730     * Returns the result of accumulating the given transformation
3731     * of all (key, value) pairs using the given reducer to
3732     * combine values, and the given basis as an identity value.
3733     *
3734     * @param transformer a function returning the transformation
3735     * for an element
3736     * @param basis the identity (initial default value) for the reduction
3737     * @param reducer a commutative associative combining function
3738     * @return the result of accumulating the given transformation
3739     * of all (key, value) pairs
3740     */
3741     public int reduceToInt(ObjectByObjectToInt<? super K, ? super V> transformer,
3742     int basis,
3743     IntByIntToInt reducer) {
3744     return fjp.invoke(ForkJoinTasks.reduceToInt
3745     (ConcurrentHashMapV8.this, transformer, basis, reducer));
3746     }
3747    
3748     /**
3749 jsr166 1.56 * Performs the given action for each key.
3750 dl 1.52 *
3751     * @param action the action
3752     */
3753 jsr166 1.53 public void forEachKey(Action<K> action) {
3754 dl 1.52 fjp.invoke(ForkJoinTasks.forEachKey
3755     (ConcurrentHashMapV8.this, action));
3756     }
3757    
3758     /**
3759     * Performs the given action for each non-null transformation
3760 jsr166 1.56 * of each key.
3761 dl 1.52 *
3762     * @param transformer a function returning the transformation
3763     * for an element, or null of there is no transformation (in
3764     * which case the action is not applied).
3765     * @param action the action
3766     */
3767 jsr166 1.53 public <U> void forEachKey(Fun<? super K, ? extends U> transformer,
3768 dl 1.52 Action<U> action) {
3769     fjp.invoke(ForkJoinTasks.forEachKey
3770     (ConcurrentHashMapV8.this, transformer, action));
3771     }
3772    
3773     /**
3774     * Returns a non-null result from applying the given search
3775 dl 1.59 * function on each key, or null if none. Upon success,
3776     * further element processing is suppressed and the results of
3777     * any other parallel invocations of the search function are
3778     * ignored.
3779 dl 1.52 *
3780     * @param searchFunction a function returning a non-null
3781     * result on success, else null
3782     * @return a non-null result from applying the given search
3783     * function on each key, or null if none
3784     */
3785     public <U> U searchKeys(Fun<? super K, ? extends U> searchFunction) {
3786     return fjp.invoke(ForkJoinTasks.searchKeys
3787     (ConcurrentHashMapV8.this, searchFunction));
3788     }
3789    
3790     /**
3791     * Returns the result of accumulating all keys using the given
3792     * reducer to combine values, or null if none.
3793     *
3794     * @param reducer a commutative associative combining function
3795     * @return the result of accumulating all keys using the given
3796     * reducer to combine values, or null if none
3797     */
3798     public K reduceKeys(BiFun<? super K, ? super K, ? extends K> reducer) {
3799     return fjp.invoke(ForkJoinTasks.reduceKeys
3800     (ConcurrentHashMapV8.this, reducer));
3801     }
3802    
3803     /**
3804     * Returns the result of accumulating the given transformation
3805     * of all keys using the given reducer to combine values, or
3806     * null if none.
3807     *
3808     * @param transformer a function returning the transformation
3809     * for an element, or null of there is no transformation (in
3810     * which case it is not combined).
3811     * @param reducer a commutative associative combining function
3812     * @return the result of accumulating the given transformation
3813     * of all keys
3814     */
3815     public <U> U reduceKeys(Fun<? super K, ? extends U> transformer,
3816     BiFun<? super U, ? super U, ? extends U> reducer) {
3817     return fjp.invoke(ForkJoinTasks.reduceKeys
3818     (ConcurrentHashMapV8.this, transformer, reducer));
3819     }
3820    
3821     /**
3822     * Returns the result of accumulating the given transformation
3823     * of all keys using the given reducer to combine values, and
3824     * the given basis as an identity value.
3825     *
3826     * @param transformer a function returning the transformation
3827     * for an element
3828     * @param basis the identity (initial default value) for the reduction
3829     * @param reducer a commutative associative combining function
3830     * @return the result of accumulating the given transformation
3831     * of all keys
3832     */
3833     public double reduceKeysToDouble(ObjectToDouble<? super K> transformer,
3834     double basis,
3835     DoubleByDoubleToDouble reducer) {
3836     return fjp.invoke(ForkJoinTasks.reduceKeysToDouble
3837     (ConcurrentHashMapV8.this, transformer, basis, reducer));
3838     }
3839    
3840     /**
3841     * Returns the result of accumulating the given transformation
3842     * of all keys using the given reducer to combine values, and
3843     * the given basis as an identity value.
3844     *
3845     * @param transformer a function returning the transformation
3846     * for an element
3847     * @param basis the identity (initial default value) for the reduction
3848     * @param reducer a commutative associative combining function
3849     * @return the result of accumulating the given transformation
3850     * of all keys
3851     */
3852     public long reduceKeysToLong(ObjectToLong<? super K> transformer,
3853     long basis,
3854     LongByLongToLong reducer) {
3855     return fjp.invoke(ForkJoinTasks.reduceKeysToLong
3856     (ConcurrentHashMapV8.this, transformer, basis, reducer));
3857     }
3858    
3859     /**
3860     * Returns the result of accumulating the given transformation
3861     * of all keys using the given reducer to combine values, and
3862     * the given basis as an identity value.
3863     *
3864     * @param transformer a function returning the transformation
3865     * for an element
3866     * @param basis the identity (initial default value) for the reduction
3867     * @param reducer a commutative associative combining function
3868     * @return the result of accumulating the given transformation
3869     * of all keys
3870     */
3871     public int reduceKeysToInt(ObjectToInt<? super K> transformer,
3872     int basis,
3873     IntByIntToInt reducer) {
3874     return fjp.invoke(ForkJoinTasks.reduceKeysToInt
3875     (ConcurrentHashMapV8.this, transformer, basis, reducer));
3876     }
3877    
3878     /**
3879 jsr166 1.56 * Performs the given action for each value.
3880 dl 1.52 *
3881     * @param action the action
3882     */
3883 jsr166 1.53 public void forEachValue(Action<V> action) {
3884 dl 1.52 fjp.invoke(ForkJoinTasks.forEachValue
3885     (ConcurrentHashMapV8.this, action));
3886     }
3887    
3888     /**
3889     * Performs the given action for each non-null transformation
3890 jsr166 1.56 * of each value.
3891 dl 1.52 *
3892     * @param transformer a function returning the transformation
3893     * for an element, or null of there is no transformation (in
3894     * which case the action is not applied).
3895     */
3896 jsr166 1.53 public <U> void forEachValue(Fun<? super V, ? extends U> transformer,
3897 dl 1.52 Action<U> action) {
3898     fjp.invoke(ForkJoinTasks.forEachValue
3899     (ConcurrentHashMapV8.this, transformer, action));
3900     }
3901    
3902     /**
3903     * Returns a non-null result from applying the given search
3904 dl 1.59 * function on each value, or null if none. Upon success,
3905     * further element processing is suppressed and the results of
3906     * any other parallel invocations of the search function are
3907     * ignored.
3908 dl 1.52 *
3909     * @param searchFunction a function returning a non-null
3910     * result on success, else null
3911     * @return a non-null result from applying the given search
3912     * function on each value, or null if none
3913     *
3914     */
3915     public <U> U searchValues(Fun<? super V, ? extends U> searchFunction) {
3916     return fjp.invoke(ForkJoinTasks.searchValues
3917     (ConcurrentHashMapV8.this, searchFunction));
3918     }
3919    
3920     /**
3921     * Returns the result of accumulating all values using the
3922     * given reducer to combine values, or null if none.
3923     *
3924     * @param reducer a commutative associative combining function
3925     * @return the result of accumulating all values
3926     */
3927     public V reduceValues(BiFun<? super V, ? super V, ? extends V> reducer) {
3928     return fjp.invoke(ForkJoinTasks.reduceValues
3929     (ConcurrentHashMapV8.this, reducer));
3930     }
3931    
3932     /**
3933     * Returns the result of accumulating the given transformation
3934     * of all values using the given reducer to combine values, or
3935     * null if none.
3936     *
3937     * @param transformer a function returning the transformation
3938     * for an element, or null of there is no transformation (in
3939     * which case it is not combined).
3940     * @param reducer a commutative associative combining function
3941     * @return the result of accumulating the given transformation
3942     * of all values
3943     */
3944     public <U> U reduceValues(Fun<? super V, ? extends U> transformer,
3945     BiFun<? super U, ? super U, ? extends U> reducer) {
3946     return fjp.invoke(ForkJoinTasks.reduceValues
3947     (ConcurrentHashMapV8.this, transformer, reducer));
3948     }
3949    
3950     /**
3951     * Returns the result of accumulating the given transformation
3952     * of all values using the given reducer to combine values,
3953     * and the given basis as an identity value.
3954     *
3955     * @param transformer a function returning the transformation
3956     * for an element
3957     * @param basis the identity (initial default value) for the reduction
3958     * @param reducer a commutative associative combining function
3959     * @return the result of accumulating the given transformation
3960     * of all values
3961     */
3962     public double reduceValuesToDouble(ObjectToDouble<? super V> transformer,
3963     double basis,
3964     DoubleByDoubleToDouble reducer) {
3965     return fjp.invoke(ForkJoinTasks.reduceValuesToDouble
3966     (ConcurrentHashMapV8.this, transformer, basis, reducer));
3967     }
3968    
3969     /**
3970     * Returns the result of accumulating the given transformation
3971     * of all values using the given reducer to combine values,
3972     * and the given basis as an identity value.
3973     *
3974     * @param transformer a function returning the transformation
3975     * for an element
3976     * @param basis the identity (initial default value) for the reduction
3977     * @param reducer a commutative associative combining function
3978     * @return the result of accumulating the given transformation
3979     * of all values
3980     */
3981     public long reduceValuesToLong(ObjectToLong<? super V> transformer,
3982     long basis,
3983     LongByLongToLong reducer) {
3984     return fjp.invoke(ForkJoinTasks.reduceValuesToLong
3985     (ConcurrentHashMapV8.this, transformer, basis, reducer));
3986     }
3987    
3988     /**
3989     * Returns the result of accumulating the given transformation
3990     * of all values using the given reducer to combine values,
3991     * and the given basis as an identity value.
3992     *
3993     * @param transformer a function returning the transformation
3994     * for an element
3995     * @param basis the identity (initial default value) for the reduction
3996     * @param reducer a commutative associative combining function
3997     * @return the result of accumulating the given transformation
3998     * of all values
3999     */
4000     public int reduceValuesToInt(ObjectToInt<? super V> transformer,
4001     int basis,
4002     IntByIntToInt reducer) {
4003     return fjp.invoke(ForkJoinTasks.reduceValuesToInt
4004     (ConcurrentHashMapV8.this, transformer, basis, reducer));
4005     }
4006    
4007     /**
4008 jsr166 1.56 * Performs the given action for each entry.
4009 dl 1.52 *
4010     * @param action the action
4011     */
4012 jsr166 1.53 public void forEachEntry(Action<Map.Entry<K,V>> action) {
4013 dl 1.52 fjp.invoke(ForkJoinTasks.forEachEntry
4014     (ConcurrentHashMapV8.this, action));
4015     }
4016    
4017     /**
4018 jsr166 1.56 * Performs the given action for each non-null transformation
4019     * of each entry.
4020 dl 1.52 *
4021     * @param transformer a function returning the transformation
4022     * for an element, or null of there is no transformation (in
4023     * which case the action is not applied).
4024     * @param action the action
4025     */
4026 jsr166 1.53 public <U> void forEachEntry(Fun<Map.Entry<K,V>, ? extends U> transformer,
4027 dl 1.52 Action<U> action) {
4028     fjp.invoke(ForkJoinTasks.forEachEntry
4029     (ConcurrentHashMapV8.this, transformer, action));
4030     }
4031    
4032     /**
4033     * Returns a non-null result from applying the given search
4034 dl 1.59 * function on each entry, or null if none. Upon success,
4035     * further element processing is suppressed and the results of
4036     * any other parallel invocations of the search function are
4037     * ignored.
4038 dl 1.52 *
4039     * @param searchFunction a function returning a non-null
4040     * result on success, else null
4041     * @return a non-null result from applying the given search
4042     * function on each entry, or null if none
4043     */
4044     public <U> U searchEntries(Fun<Map.Entry<K,V>, ? extends U> searchFunction) {
4045     return fjp.invoke(ForkJoinTasks.searchEntries
4046     (ConcurrentHashMapV8.this, searchFunction));
4047     }
4048    
4049     /**
4050     * Returns the result of accumulating all entries using the
4051     * given reducer to combine values, or null if none.
4052     *
4053     * @param reducer a commutative associative combining function
4054     * @return the result of accumulating all entries
4055     */
4056     public Map.Entry<K,V> reduceEntries(BiFun<Map.Entry<K,V>, Map.Entry<K,V>, ? extends Map.Entry<K,V>> reducer) {
4057     return fjp.invoke(ForkJoinTasks.reduceEntries
4058     (ConcurrentHashMapV8.this, reducer));
4059     }
4060    
4061     /**
4062     * Returns the result of accumulating the given transformation
4063     * of all entries using the given reducer to combine values,
4064     * or null if none.
4065     *
4066     * @param transformer a function returning the transformation
4067     * for an element, or null of there is no transformation (in
4068     * which case it is not combined).
4069     * @param reducer a commutative associative combining function
4070     * @return the result of accumulating the given transformation
4071     * of all entries
4072     */
4073     public <U> U reduceEntries(Fun<Map.Entry<K,V>, ? extends U> transformer,
4074     BiFun<? super U, ? super U, ? extends U> reducer) {
4075     return fjp.invoke(ForkJoinTasks.reduceEntries
4076     (ConcurrentHashMapV8.this, transformer, reducer));
4077     }
4078    
4079     /**
4080     * Returns the result of accumulating the given transformation
4081     * of all entries using the given reducer to combine values,
4082     * and the given basis as an identity value.
4083     *
4084     * @param transformer a function returning the transformation
4085     * for an element
4086     * @param basis the identity (initial default value) for the reduction
4087     * @param reducer a commutative associative combining function
4088     * @return the result of accumulating the given transformation
4089     * of all entries
4090     */
4091     public double reduceEntriesToDouble(ObjectToDouble<Map.Entry<K,V>> transformer,
4092     double basis,
4093     DoubleByDoubleToDouble reducer) {
4094     return fjp.invoke(ForkJoinTasks.reduceEntriesToDouble
4095     (ConcurrentHashMapV8.this, transformer, basis, reducer));
4096     }
4097    
4098     /**
4099     * Returns the result of accumulating the given transformation
4100     * of all entries using the given reducer to combine values,
4101     * and the given basis as an identity value.
4102     *
4103     * @param transformer a function returning the transformation
4104     * for an element
4105     * @param basis the identity (initial default value) for the reduction
4106     * @param reducer a commutative associative combining function
4107     * @return the result of accumulating the given transformation
4108     * of all entries
4109     */
4110     public long reduceEntriesToLong(ObjectToLong<Map.Entry<K,V>> transformer,
4111     long basis,
4112     LongByLongToLong reducer) {
4113     return fjp.invoke(ForkJoinTasks.reduceEntriesToLong
4114     (ConcurrentHashMapV8.this, transformer, basis, reducer));
4115     }
4116    
4117     /**
4118     * Returns the result of accumulating the given transformation
4119     * of all entries using the given reducer to combine values,
4120     * and the given basis as an identity value.
4121     *
4122     * @param transformer a function returning the transformation
4123     * for an element
4124     * @param basis the identity (initial default value) for the reduction
4125     * @param reducer a commutative associative combining function
4126     * @return the result of accumulating the given transformation
4127     * of all entries
4128     */
4129     public int reduceEntriesToInt(ObjectToInt<Map.Entry<K,V>> transformer,
4130     int basis,
4131     IntByIntToInt reducer) {
4132     return fjp.invoke(ForkJoinTasks.reduceEntriesToInt
4133     (ConcurrentHashMapV8.this, transformer, basis, reducer));
4134     }
4135     }
4136    
4137     // ---------------------------------------------------------------------
4138    
4139     /**
4140     * Predefined tasks for performing bulk parallel operations on
4141     * ConcurrentHashMaps. These tasks follow the forms and rules used
4142     * in class {@link Parallel}. Each method has the same name, but
4143     * returns a task rather than invoking it. These methods may be
4144     * useful in custom applications such as submitting a task without
4145     * waiting for completion, or combining with other tasks.
4146     */
4147     public static class ForkJoinTasks {
4148     private ForkJoinTasks() {}
4149    
4150     /**
4151     * Returns a task that when invoked, performs the given
4152     * action for each (key, value)
4153     *
4154     * @param map the map
4155     * @param action the action
4156     * @return the task
4157     */
4158 jsr166 1.53 public static <K,V> ForkJoinTask<Void> forEach
4159 dl 1.52 (ConcurrentHashMapV8<K,V> map,
4160     BiAction<K,V> action) {
4161     if (action == null) throw new NullPointerException();
4162     return new ForEachMappingTask<K,V>(map, action);
4163     }
4164    
4165     /**
4166     * Returns a task that when invoked, performs the given
4167     * action for each non-null transformation of each (key, value)
4168     *
4169     * @param map the map
4170     * @param transformer a function returning the transformation
4171     * for an element, or null of there is no transformation (in
4172     * which case the action is not applied).
4173     * @param action the action
4174     * @return the task
4175     */
4176 jsr166 1.53 public static <K,V,U> ForkJoinTask<Void> forEach
4177 dl 1.52 (ConcurrentHashMapV8<K,V> map,
4178     BiFun<? super K, ? super V, ? extends U> transformer,
4179     Action<U> action) {
4180     if (transformer == null || action == null)
4181     throw new NullPointerException();
4182     return new ForEachTransformedMappingTask<K,V,U>
4183     (map, transformer, action);
4184     }
4185    
4186     /**
4187 dl 1.59 * Returns a task that when invoked, returns a non-null result
4188     * from applying the given search function on each (key,
4189     * value), or null if none. Upon success, further element
4190     * processing is suppressed and the results of any other
4191     * parallel invocations of the search function are ignored.
4192 dl 1.52 *
4193     * @param map the map
4194     * @param searchFunction a function returning a non-null
4195     * result on success, else null
4196     * @return the task
4197     */
4198     public static <K,V,U> ForkJoinTask<U> search
4199     (ConcurrentHashMapV8<K,V> map,
4200     BiFun<? super K, ? super V, ? extends U> searchFunction) {
4201     if (searchFunction == null) throw new NullPointerException();
4202     return new SearchMappingsTask<K,V,U>
4203     (map, searchFunction,
4204     new AtomicReference<U>());
4205     }
4206    
4207     /**
4208     * Returns a task that when invoked, returns the result of
4209     * accumulating the given transformation of all (key, value) pairs
4210     * using the given reducer to combine values, or null if none.
4211     *
4212     * @param map the map
4213     * @param transformer a function returning the transformation
4214     * for an element, or null of there is no transformation (in
4215     * which case it is not combined).
4216     * @param reducer a commutative associative combining function
4217     * @return the task
4218     */
4219     public static <K,V,U> ForkJoinTask<U> reduce
4220     (ConcurrentHashMapV8<K,V> map,
4221     BiFun<? super K, ? super V, ? extends U> transformer,
4222     BiFun<? super U, ? super U, ? extends U> reducer) {
4223     if (transformer == null || reducer == null)
4224     throw new NullPointerException();
4225     return new MapReduceMappingsTask<K,V,U>
4226     (map, transformer, reducer);
4227     }
4228    
4229     /**
4230     * Returns a task that when invoked, returns the result of
4231     * accumulating the given transformation of all (key, value) pairs
4232     * using the given reducer to combine values, and the given
4233     * basis as an identity value.
4234     *
4235     * @param map the map
4236     * @param transformer a function returning the transformation
4237     * for an element
4238     * @param basis the identity (initial default value) for the reduction
4239     * @param reducer a commutative associative combining function
4240     * @return the task
4241     */
4242     public static <K,V> ForkJoinTask<Double> reduceToDouble
4243     (ConcurrentHashMapV8<K,V> map,
4244     ObjectByObjectToDouble<? super K, ? super V> transformer,
4245     double basis,
4246     DoubleByDoubleToDouble reducer) {
4247     if (transformer == null || reducer == null)
4248     throw new NullPointerException();
4249     return new MapReduceMappingsToDoubleTask<K,V>
4250     (map, transformer, basis, reducer);
4251     }
4252    
4253     /**
4254     * Returns a task that when invoked, returns the result of
4255     * accumulating the given transformation of all (key, value) pairs
4256     * using the given reducer to combine values, and the given
4257     * basis as an identity value.
4258     *
4259     * @param map the map
4260     * @param transformer a function returning the transformation
4261     * for an element
4262     * @param basis the identity (initial default value) for the reduction
4263     * @param reducer a commutative associative combining function
4264     * @return the task
4265     */
4266     public static <K,V> ForkJoinTask<Long> reduceToLong
4267     (ConcurrentHashMapV8<K,V> map,
4268     ObjectByObjectToLong<? super K, ? super V> transformer,
4269     long basis,
4270     LongByLongToLong reducer) {
4271     if (transformer == null || reducer == null)
4272     throw new NullPointerException();
4273     return new MapReduceMappingsToLongTask<K,V>
4274     (map, transformer, basis, reducer);
4275     }
4276    
4277     /**
4278     * Returns a task that when invoked, returns the result of
4279     * accumulating the given transformation of all (key, value) pairs
4280     * using the given reducer to combine values, and the given
4281     * basis as an identity value.
4282     *
4283     * @param transformer a function returning the transformation
4284     * for an element
4285     * @param basis the identity (initial default value) for the reduction
4286     * @param reducer a commutative associative combining function
4287     * @return the task
4288     */
4289     public static <K,V> ForkJoinTask<Integer> reduceToInt
4290     (ConcurrentHashMapV8<K,V> map,
4291     ObjectByObjectToInt<? super K, ? super V> transformer,
4292     int basis,
4293     IntByIntToInt reducer) {
4294     if (transformer == null || reducer == null)
4295     throw new NullPointerException();
4296     return new MapReduceMappingsToIntTask<K,V>
4297     (map, transformer, basis, reducer);
4298     }
4299    
4300     /**
4301     * Returns a task that when invoked, performs the given action
4302 jsr166 1.56 * for each key.
4303 dl 1.52 *
4304     * @param map the map
4305     * @param action the action
4306     * @return the task
4307     */
4308 jsr166 1.53 public static <K,V> ForkJoinTask<Void> forEachKey
4309 dl 1.52 (ConcurrentHashMapV8<K,V> map,
4310     Action<K> action) {
4311     if (action == null) throw new NullPointerException();
4312     return new ForEachKeyTask<K,V>(map, action);
4313     }
4314    
4315     /**
4316     * Returns a task that when invoked, performs the given action
4317 jsr166 1.56 * for each non-null transformation of each key.
4318 dl 1.52 *
4319     * @param map the map
4320     * @param transformer a function returning the transformation
4321     * for an element, or null of there is no transformation (in
4322     * which case the action is not applied).
4323     * @param action the action
4324     * @return the task
4325     */
4326 jsr166 1.53 public static <K,V,U> ForkJoinTask<Void> forEachKey
4327 dl 1.52 (ConcurrentHashMapV8<K,V> map,
4328     Fun<? super K, ? extends U> transformer,
4329     Action<U> action) {
4330     if (transformer == null || action == null)
4331     throw new NullPointerException();
4332     return new ForEachTransformedKeyTask<K,V,U>
4333     (map, transformer, action);
4334     }
4335    
4336     /**
4337     * Returns a task that when invoked, returns a non-null result
4338     * from applying the given search function on each key, or
4339 dl 1.59 * null if none. Upon success, further element processing is
4340     * suppressed and the results of any other parallel
4341     * invocations of the search function are ignored.
4342 dl 1.52 *
4343     * @param map the map
4344     * @param searchFunction a function returning a non-null
4345     * result on success, else null
4346     * @return the task
4347     */
4348     public static <K,V,U> ForkJoinTask<U> searchKeys
4349     (ConcurrentHashMapV8<K,V> map,
4350     Fun<? super K, ? extends U> searchFunction) {
4351     if (searchFunction == null) throw new NullPointerException();
4352     return new SearchKeysTask<K,V,U>
4353     (map, searchFunction,
4354     new AtomicReference<U>());
4355     }
4356    
4357     /**
4358     * Returns a task that when invoked, returns the result of
4359     * accumulating all keys using the given reducer to combine
4360     * values, or null if none.
4361     *
4362     * @param map the map
4363     * @param reducer a commutative associative combining function
4364     * @return the task
4365     */
4366     public static <K,V> ForkJoinTask<K> reduceKeys
4367     (ConcurrentHashMapV8<K,V> map,
4368     BiFun<? super K, ? super K, ? extends K> reducer) {
4369     if (reducer == null) throw new NullPointerException();
4370     return new ReduceKeysTask<K,V>
4371     (map, reducer);
4372     }
4373 jsr166 1.58
4374 dl 1.52 /**
4375     * Returns a task that when invoked, returns the result of
4376     * accumulating the given transformation of all keys using the given
4377     * reducer to combine values, or null if none.
4378     *
4379     * @param map the map
4380     * @param transformer a function returning the transformation
4381     * for an element, or null of there is no transformation (in
4382     * which case it is not combined).
4383     * @param reducer a commutative associative combining function
4384     * @return the task
4385     */
4386     public static <K,V,U> ForkJoinTask<U> reduceKeys
4387     (ConcurrentHashMapV8<K,V> map,
4388     Fun<? super K, ? extends U> transformer,
4389     BiFun<? super U, ? super U, ? extends U> reducer) {
4390     if (transformer == null || reducer == null)
4391     throw new NullPointerException();
4392     return new MapReduceKeysTask<K,V,U>
4393     (map, transformer, reducer);
4394     }
4395    
4396     /**
4397     * Returns a task that when invoked, returns the result of
4398     * accumulating the given transformation of all keys using the given
4399     * reducer to combine values, and the given basis as an
4400     * identity value.
4401     *
4402     * @param map the map
4403     * @param transformer a function returning the transformation
4404     * for an element
4405     * @param basis the identity (initial default value) for the reduction
4406     * @param reducer a commutative associative combining function
4407     * @return the task
4408     */
4409     public static <K,V> ForkJoinTask<Double> reduceKeysToDouble
4410     (ConcurrentHashMapV8<K,V> map,
4411     ObjectToDouble<? super K> transformer,
4412     double basis,
4413     DoubleByDoubleToDouble reducer) {
4414     if (transformer == null || reducer == null)
4415     throw new NullPointerException();
4416     return new MapReduceKeysToDoubleTask<K,V>
4417     (map, transformer, basis, reducer);
4418     }
4419    
4420     /**
4421     * Returns a task that when invoked, returns the result of
4422     * accumulating the given transformation of all keys using the given
4423     * reducer to combine values, and the given basis as an
4424     * identity value.
4425     *
4426     * @param map the map
4427     * @param transformer a function returning the transformation
4428     * for an element
4429     * @param basis the identity (initial default value) for the reduction
4430     * @param reducer a commutative associative combining function
4431     * @return the task
4432     */
4433     public static <K,V> ForkJoinTask<Long> reduceKeysToLong
4434     (ConcurrentHashMapV8<K,V> map,
4435     ObjectToLong<? super K> transformer,
4436     long basis,
4437     LongByLongToLong reducer) {
4438     if (transformer == null || reducer == null)
4439     throw new NullPointerException();
4440     return new MapReduceKeysToLongTask<K,V>
4441     (map, transformer, basis, reducer);
4442     }
4443    
4444     /**
4445     * Returns a task that when invoked, returns the result of
4446     * accumulating the given transformation of all keys using the given
4447     * reducer to combine values, and the given basis as an
4448     * identity value.
4449     *
4450     * @param map the map
4451     * @param transformer a function returning the transformation
4452     * for an element
4453     * @param basis the identity (initial default value) for the reduction
4454     * @param reducer a commutative associative combining function
4455     * @return the task
4456     */
4457     public static <K,V> ForkJoinTask<Integer> reduceKeysToInt
4458     (ConcurrentHashMapV8<K,V> map,
4459     ObjectToInt<? super K> transformer,
4460     int basis,
4461     IntByIntToInt reducer) {
4462     if (transformer == null || reducer == null)
4463     throw new NullPointerException();
4464     return new MapReduceKeysToIntTask<K,V>
4465     (map, transformer, basis, reducer);
4466     }
4467    
4468     /**
4469     * Returns a task that when invoked, performs the given action
4470 jsr166 1.56 * for each value.
4471 dl 1.52 *
4472     * @param map the map
4473     * @param action the action
4474     */
4475 jsr166 1.53 public static <K,V> ForkJoinTask<Void> forEachValue
4476 dl 1.52 (ConcurrentHashMapV8<K,V> map,
4477     Action<V> action) {
4478     if (action == null) throw new NullPointerException();
4479     return new ForEachValueTask<K,V>(map, action);
4480     }
4481    
4482     /**
4483     * Returns a task that when invoked, performs the given action
4484 jsr166 1.56 * for each non-null transformation of each value.
4485 dl 1.52 *
4486     * @param map the map
4487     * @param transformer a function returning the transformation
4488     * for an element, or null of there is no transformation (in
4489     * which case the action is not applied).
4490     * @param action the action
4491     */
4492 jsr166 1.53 public static <K,V,U> ForkJoinTask<Void> forEachValue
4493 dl 1.52 (ConcurrentHashMapV8<K,V> map,
4494     Fun<? super V, ? extends U> transformer,
4495     Action<U> action) {
4496     if (transformer == null || action == null)
4497     throw new NullPointerException();
4498     return new ForEachTransformedValueTask<K,V,U>
4499     (map, transformer, action);
4500     }
4501    
4502     /**
4503     * Returns a task that when invoked, returns a non-null result
4504     * from applying the given search function on each value, or
4505 dl 1.59 * null if none. Upon success, further element processing is
4506     * suppressed and the results of any other parallel
4507     * invocations of the search function are ignored.
4508 dl 1.52 *
4509     * @param map the map
4510     * @param searchFunction a function returning a non-null
4511     * result on success, else null
4512     * @return the task
4513     *
4514     */
4515     public static <K,V,U> ForkJoinTask<U> searchValues
4516     (ConcurrentHashMapV8<K,V> map,
4517     Fun<? super V, ? extends U> searchFunction) {
4518     if (searchFunction == null) throw new NullPointerException();
4519     return new SearchValuesTask<K,V,U>
4520     (map, searchFunction,
4521     new AtomicReference<U>());
4522     }
4523    
4524     /**
4525     * Returns a task that when invoked, returns the result of
4526     * accumulating all values using the given reducer to combine
4527     * values, or null if none.
4528     *
4529     * @param map the map
4530     * @param reducer a commutative associative combining function
4531     * @return the task
4532     */
4533     public static <K,V> ForkJoinTask<V> reduceValues
4534     (ConcurrentHashMapV8<K,V> map,
4535     BiFun<? super V, ? super V, ? extends V> reducer) {
4536     if (reducer == null) throw new NullPointerException();
4537     return new ReduceValuesTask<K,V>
4538     (map, reducer);
4539     }
4540    
4541     /**
4542     * Returns a task that when invoked, returns the result of
4543     * accumulating the given transformation of all values using the
4544     * given reducer to combine values, or null if none.
4545     *
4546     * @param map the map
4547     * @param transformer a function returning the transformation
4548     * for an element, or null of there is no transformation (in
4549     * which case it is not combined).
4550     * @param reducer a commutative associative combining function
4551     * @return the task
4552     */
4553     public static <K,V,U> ForkJoinTask<U> reduceValues
4554     (ConcurrentHashMapV8<K,V> map,
4555     Fun<? super V, ? extends U> transformer,
4556     BiFun<? super U, ? super U, ? extends U> reducer) {
4557     if (transformer == null || reducer == null)
4558     throw new NullPointerException();
4559     return new MapReduceValuesTask<K,V,U>
4560     (map, transformer, reducer);
4561     }
4562    
4563     /**
4564     * Returns a task that when invoked, returns the result of
4565     * accumulating the given transformation of all values using the
4566     * given reducer to combine values, and the given basis as an
4567     * identity value.
4568     *
4569     * @param map the map
4570     * @param transformer a function returning the transformation
4571     * for an element
4572     * @param basis the identity (initial default value) for the reduction
4573     * @param reducer a commutative associative combining function
4574     * @return the task
4575     */
4576     public static <K,V> ForkJoinTask<Double> reduceValuesToDouble
4577     (ConcurrentHashMapV8<K,V> map,
4578     ObjectToDouble<? super V> transformer,
4579     double basis,
4580     DoubleByDoubleToDouble reducer) {
4581     if (transformer == null || reducer == null)
4582     throw new NullPointerException();
4583     return new MapReduceValuesToDoubleTask<K,V>
4584     (map, transformer, basis, reducer);
4585     }
4586    
4587     /**
4588     * Returns a task that when invoked, returns the result of
4589     * accumulating the given transformation of all values using the
4590     * given reducer to combine values, and the given basis as an
4591     * identity value.
4592     *
4593     * @param map the map
4594     * @param transformer a function returning the transformation
4595     * for an element
4596     * @param basis the identity (initial default value) for the reduction
4597     * @param reducer a commutative associative combining function
4598     * @return the task
4599     */
4600     public static <K,V> ForkJoinTask<Long> reduceValuesToLong
4601     (ConcurrentHashMapV8<K,V> map,
4602     ObjectToLong<? super V> transformer,
4603     long basis,
4604     LongByLongToLong reducer) {
4605     if (transformer == null || reducer == null)
4606     throw new NullPointerException();
4607     return new MapReduceValuesToLongTask<K,V>
4608     (map, transformer, basis, reducer);
4609     }
4610    
4611     /**
4612     * Returns a task that when invoked, returns the result of
4613     * accumulating the given transformation of all values using the
4614     * given reducer to combine values, and the given basis as an
4615     * identity value.
4616     *
4617     * @param map the map
4618     * @param transformer a function returning the transformation
4619     * for an element
4620     * @param basis the identity (initial default value) for the reduction
4621     * @param reducer a commutative associative combining function
4622     * @return the task
4623     */
4624     public static <K,V> ForkJoinTask<Integer> reduceValuesToInt
4625     (ConcurrentHashMapV8<K,V> map,
4626     ObjectToInt<? super V> transformer,
4627     int basis,
4628     IntByIntToInt reducer) {
4629     if (transformer == null || reducer == null)
4630     throw new NullPointerException();
4631     return new MapReduceValuesToIntTask<K,V>
4632     (map, transformer, basis, reducer);
4633     }
4634    
4635     /**
4636     * Returns a task that when invoked, perform the given action
4637 jsr166 1.56 * for each entry.
4638 dl 1.52 *
4639     * @param map the map
4640     * @param action the action
4641     */
4642 jsr166 1.53 public static <K,V> ForkJoinTask<Void> forEachEntry
4643 dl 1.52 (ConcurrentHashMapV8<K,V> map,
4644     Action<Map.Entry<K,V>> action) {
4645     if (action == null) throw new NullPointerException();
4646     return new ForEachEntryTask<K,V>(map, action);
4647     }
4648    
4649     /**
4650     * Returns a task that when invoked, perform the given action
4651 jsr166 1.56 * for each non-null transformation of each entry.
4652 dl 1.52 *
4653     * @param map the map
4654     * @param transformer a function returning the transformation
4655     * for an element, or null of there is no transformation (in
4656     * which case the action is not applied).
4657     * @param action the action
4658     */
4659 jsr166 1.53 public static <K,V,U> ForkJoinTask<Void> forEachEntry
4660 dl 1.52 (ConcurrentHashMapV8<K,V> map,
4661     Fun<Map.Entry<K,V>, ? extends U> transformer,
4662     Action<U> action) {
4663     if (transformer == null || action == null)
4664     throw new NullPointerException();
4665     return new ForEachTransformedEntryTask<K,V,U>
4666     (map, transformer, action);
4667     }
4668    
4669     /**
4670     * Returns a task that when invoked, returns a non-null result
4671     * from applying the given search function on each entry, or
4672 dl 1.59 * null if none. Upon success, further element processing is
4673     * suppressed and the results of any other parallel
4674     * invocations of the search function are ignored.
4675 dl 1.52 *
4676     * @param map the map
4677     * @param searchFunction a function returning a non-null
4678     * result on success, else null
4679     * @return the task
4680     *
4681     */
4682     public static <K,V,U> ForkJoinTask<U> searchEntries
4683     (ConcurrentHashMapV8<K,V> map,
4684     Fun<Map.Entry<K,V>, ? extends U> searchFunction) {
4685     if (searchFunction == null) throw new NullPointerException();
4686     return new SearchEntriesTask<K,V,U>
4687     (map, searchFunction,
4688     new AtomicReference<U>());
4689     }
4690    
4691     /**
4692     * Returns a task that when invoked, returns the result of
4693     * accumulating all entries using the given reducer to combine
4694     * values, or null if none.
4695     *
4696     * @param map the map
4697     * @param reducer a commutative associative combining function
4698     * @return the task
4699     */
4700     public static <K,V> ForkJoinTask<Map.Entry<K,V>> reduceEntries
4701     (ConcurrentHashMapV8<K,V> map,
4702     BiFun<Map.Entry<K,V>, Map.Entry<K,V>, ? extends Map.Entry<K,V>> reducer) {
4703     if (reducer == null) throw new NullPointerException();
4704     return new ReduceEntriesTask<K,V>
4705     (map, reducer);
4706     }
4707    
4708     /**
4709     * Returns a task that when invoked, returns the result of
4710     * accumulating the given transformation of all entries using the
4711     * given reducer to combine values, or null if none.
4712     *
4713     * @param map the map
4714     * @param transformer a function returning the transformation
4715     * for an element, or null of there is no transformation (in
4716     * which case it is not combined).
4717     * @param reducer a commutative associative combining function
4718     * @return the task
4719     */
4720     public static <K,V,U> ForkJoinTask<U> reduceEntries
4721     (ConcurrentHashMapV8<K,V> map,
4722     Fun<Map.Entry<K,V>, ? extends U> transformer,
4723     BiFun<? super U, ? super U, ? extends U> reducer) {
4724     if (transformer == null || reducer == null)
4725     throw new NullPointerException();
4726     return new MapReduceEntriesTask<K,V,U>
4727     (map, transformer, reducer);
4728     }
4729    
4730     /**
4731     * Returns a task that when invoked, returns the result of
4732     * accumulating the given transformation of all entries using the
4733     * given reducer to combine values, and the given basis as an
4734     * identity value.
4735     *
4736     * @param map the map
4737     * @param transformer a function returning the transformation
4738     * for an element
4739     * @param basis the identity (initial default value) for the reduction
4740     * @param reducer a commutative associative combining function
4741     * @return the task
4742     */
4743     public static <K,V> ForkJoinTask<Double> reduceEntriesToDouble
4744     (ConcurrentHashMapV8<K,V> map,
4745     ObjectToDouble<Map.Entry<K,V>> transformer,
4746     double basis,
4747     DoubleByDoubleToDouble reducer) {
4748     if (transformer == null || reducer == null)
4749     throw new NullPointerException();
4750     return new MapReduceEntriesToDoubleTask<K,V>
4751     (map, transformer, basis, reducer);
4752     }
4753    
4754     /**
4755     * Returns a task that when invoked, returns the result of
4756     * accumulating the given transformation of all entries using the
4757     * given reducer to combine values, and the given basis as an
4758     * identity value.
4759     *
4760     * @param map the map
4761     * @param transformer a function returning the transformation
4762     * for an element
4763     * @param basis the identity (initial default value) for the reduction
4764     * @param reducer a commutative associative combining function
4765     * @return the task
4766     */
4767     public static <K,V> ForkJoinTask<Long> reduceEntriesToLong
4768     (ConcurrentHashMapV8<K,V> map,
4769     ObjectToLong<Map.Entry<K,V>> transformer,
4770     long basis,
4771     LongByLongToLong reducer) {
4772     if (transformer == null || reducer == null)
4773     throw new NullPointerException();
4774     return new MapReduceEntriesToLongTask<K,V>
4775     (map, transformer, basis, reducer);
4776     }
4777    
4778     /**
4779     * Returns a task that when invoked, returns the result of
4780     * accumulating the given transformation of all entries using the
4781     * given reducer to combine values, and the given basis as an
4782     * identity value.
4783     *
4784     * @param map the map
4785     * @param transformer a function returning the transformation
4786     * for an element
4787     * @param basis the identity (initial default value) for the reduction
4788     * @param reducer a commutative associative combining function
4789     * @return the task
4790     */
4791     public static <K,V> ForkJoinTask<Integer> reduceEntriesToInt
4792     (ConcurrentHashMapV8<K,V> map,
4793     ObjectToInt<Map.Entry<K,V>> transformer,
4794     int basis,
4795     IntByIntToInt reducer) {
4796     if (transformer == null || reducer == null)
4797     throw new NullPointerException();
4798     return new MapReduceEntriesToIntTask<K,V>
4799     (map, transformer, basis, reducer);
4800     }
4801     }
4802    
4803     // -------------------------------------------------------
4804    
4805     /**
4806     * Base for FJ tasks for bulk operations. This adds a variant of
4807 jsr166 1.55 * CountedCompleters and some split and merge bookkeeping to
4808 dl 1.52 * iterator functionality. The forEach and reduce methods are
4809     * similar to those illustrated in CountedCompleter documentation,
4810     * except that bottom-up reduction completions perform them within
4811     * their compute methods. The search methods are like forEach
4812     * except they continually poll for success and exit early. Also,
4813     * exceptions are handled in a simpler manner, by just trying to
4814     * complete root task exceptionally.
4815     */
4816 dl 1.61 @SuppressWarnings("serial") static abstract class BulkTask<K,V,R> extends Traverser<K,V,R> {
4817 dl 1.52 final BulkTask<K,V,?> parent; // completion target
4818     int batch; // split control
4819     int pending; // completion control
4820    
4821     /** Constructor for root tasks */
4822     BulkTask(ConcurrentHashMapV8<K,V> map) {
4823     super(map);
4824     this.parent = null;
4825     this.batch = -1; // force call to batch() on execution
4826     }
4827    
4828     /** Constructor for subtasks */
4829 dl 1.61 BulkTask(BulkTask<K,V,?> parent, int batch) {
4830     super(parent);
4831 dl 1.52 this.parent = parent;
4832     this.batch = batch;
4833     }
4834    
4835     // FJ methods
4836    
4837     /**
4838 jsr166 1.56 * Propagates completion. Note that all reduce actions
4839 dl 1.52 * bypass this method to combine while completing.
4840     */
4841     final void tryComplete() {
4842     BulkTask<K,V,?> a = this, s = a;
4843     for (int c;;) {
4844     if ((c = a.pending) == 0) {
4845     if ((a = (s = a).parent) == null) {
4846     s.quietlyComplete();
4847     break;
4848     }
4849     }
4850     else if (U.compareAndSwapInt(a, PENDING, c, c - 1))
4851     break;
4852     }
4853     }
4854    
4855     /**
4856 dl 1.61 * Forces root task to complete.
4857     * @param ex if null, complete normally, else exceptionally
4858     * @return false to simplify use
4859 dl 1.52 */
4860 dl 1.61 final boolean tryCompleteComputation(Throwable ex) {
4861 dl 1.52 for (BulkTask<K,V,?> a = this;;) {
4862     BulkTask<K,V,?> p = a.parent;
4863     if (p == null) {
4864 dl 1.61 if (ex != null)
4865     a.completeExceptionally(ex);
4866     else
4867     a.quietlyComplete();
4868     return false;
4869 dl 1.52 }
4870     a = p;
4871     }
4872     }
4873    
4874 dl 1.61 /**
4875     * Version of tryCompleteComputation for function screening checks
4876     */
4877     final boolean abortOnNullFunction() {
4878     return tryCompleteComputation(new Error("Unexpected null function"));
4879 dl 1.52 }
4880    
4881     // utilities
4882    
4883     /** CompareAndSet pending count */
4884     final boolean casPending(int cmp, int val) {
4885     return U.compareAndSwapInt(this, PENDING, cmp, val);
4886     }
4887    
4888     /**
4889 jsr166 1.56 * Returns approx exp2 of the number of times (minus one) to
4890 dl 1.52 * split task by two before executing leaf action. This value
4891     * is faster to compute and more convenient to use as a guide
4892     * to splitting than is the depth, since it is used while
4893     * dividing by two anyway.
4894     */
4895     final int batch() {
4896     int b = batch;
4897     if (b < 0) {
4898     long n = map.counter.sum();
4899     int sp = getPool().getParallelism() << 3; // slack of 8
4900 jsr166 1.53 b = batch = (n <= 0L) ? 0 : (n < (long)sp) ? (int)n : sp;
4901 dl 1.52 }
4902     return b;
4903     }
4904    
4905     /**
4906 jsr166 1.56 * Returns exportable snapshot entry.
4907 dl 1.52 */
4908     static <K,V> AbstractMap.SimpleEntry<K,V> entryFor(K k, V v) {
4909 dl 1.59 return new AbstractMap.SimpleEntry<K,V>(k, v);
4910 dl 1.52 }
4911    
4912     // Unsafe mechanics
4913     private static final sun.misc.Unsafe U;
4914     private static final long PENDING;
4915     static {
4916     try {
4917 dl 1.59 U = getUnsafe();
4918 dl 1.52 PENDING = U.objectFieldOffset
4919     (BulkTask.class.getDeclaredField("pending"));
4920     } catch (Exception e) {
4921     throw new Error(e);
4922     }
4923     }
4924     }
4925    
4926     /*
4927     * Task classes. Coded in a regular but ugly format/style to
4928     * simplify checks that each variant differs in the right way from
4929     * others.
4930     */
4931    
4932 dl 1.61 @SuppressWarnings("serial") static final class ForEachKeyTask<K,V>
4933 dl 1.52 extends BulkTask<K,V,Void> {
4934     final Action<K> action;
4935     ForEachKeyTask
4936     (ConcurrentHashMapV8<K,V> m,
4937     Action<K> action) {
4938     super(m);
4939     this.action = action;
4940     }
4941     ForEachKeyTask
4942 dl 1.61 (BulkTask<K,V,?> p, int b,
4943 dl 1.52 Action<K> action) {
4944 dl 1.61 super(p, b);
4945 dl 1.52 this.action = action;
4946     }
4947 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
4948 dl 1.52 final Action<K> action = this.action;
4949     if (action == null)
4950 dl 1.61 return abortOnNullFunction();
4951     try {
4952     int b = batch(), c;
4953     while (b > 1 && baseIndex != baseLimit) {
4954     do {} while (!casPending(c = pending, c+1));
4955     new ForEachKeyTask<K,V>(this, b >>>= 1, action).fork();
4956     }
4957     while (advance() != null)
4958     action.apply((K)nextKey);
4959     tryComplete();
4960     } catch (Throwable ex) {
4961     return tryCompleteComputation(ex);
4962 dl 1.52 }
4963 dl 1.61 return false;
4964 dl 1.52 }
4965     }
4966    
4967 dl 1.61 @SuppressWarnings("serial") static final class ForEachValueTask<K,V>
4968 dl 1.52 extends BulkTask<K,V,Void> {
4969     final Action<V> action;
4970     ForEachValueTask
4971     (ConcurrentHashMapV8<K,V> m,
4972     Action<V> action) {
4973     super(m);
4974     this.action = action;
4975     }
4976     ForEachValueTask
4977 dl 1.61 (BulkTask<K,V,?> p, int b,
4978 dl 1.52 Action<V> action) {
4979 dl 1.61 super(p, b);
4980 dl 1.52 this.action = action;
4981     }
4982 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
4983 dl 1.52 final Action<V> action = this.action;
4984     if (action == null)
4985 dl 1.61 return abortOnNullFunction();
4986     try {
4987     int b = batch(), c;
4988     while (b > 1 && baseIndex != baseLimit) {
4989     do {} while (!casPending(c = pending, c+1));
4990     new ForEachValueTask<K,V>(this, b >>>= 1, action).fork();
4991     }
4992     Object v;
4993     while ((v = advance()) != null)
4994     action.apply((V)v);
4995     tryComplete();
4996     } catch (Throwable ex) {
4997     return tryCompleteComputation(ex);
4998 dl 1.52 }
4999 dl 1.61 return false;
5000 dl 1.52 }
5001     }
5002    
5003 dl 1.61 @SuppressWarnings("serial") static final class ForEachEntryTask<K,V>
5004 dl 1.52 extends BulkTask<K,V,Void> {
5005     final Action<Entry<K,V>> action;
5006     ForEachEntryTask
5007     (ConcurrentHashMapV8<K,V> m,
5008     Action<Entry<K,V>> action) {
5009     super(m);
5010     this.action = action;
5011     }
5012     ForEachEntryTask
5013 dl 1.61 (BulkTask<K,V,?> p, int b,
5014 dl 1.52 Action<Entry<K,V>> action) {
5015 dl 1.61 super(p, b);
5016 dl 1.52 this.action = action;
5017     }
5018 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
5019 dl 1.52 final Action<Entry<K,V>> action = this.action;
5020     if (action == null)
5021 dl 1.61 return abortOnNullFunction();
5022     try {
5023     int b = batch(), c;
5024     while (b > 1 && baseIndex != baseLimit) {
5025     do {} while (!casPending(c = pending, c+1));
5026     new ForEachEntryTask<K,V>(this, b >>>= 1, action).fork();
5027     }
5028     Object v;
5029     while ((v = advance()) != null)
5030     action.apply(entryFor((K)nextKey, (V)v));
5031     tryComplete();
5032     } catch (Throwable ex) {
5033     return tryCompleteComputation(ex);
5034 dl 1.52 }
5035 dl 1.61 return false;
5036 dl 1.52 }
5037     }
5038    
5039 dl 1.61 @SuppressWarnings("serial") static final class ForEachMappingTask<K,V>
5040 dl 1.52 extends BulkTask<K,V,Void> {
5041     final BiAction<K,V> action;
5042     ForEachMappingTask
5043     (ConcurrentHashMapV8<K,V> m,
5044     BiAction<K,V> action) {
5045     super(m);
5046     this.action = action;
5047     }
5048     ForEachMappingTask
5049 dl 1.61 (BulkTask<K,V,?> p, int b,
5050 dl 1.52 BiAction<K,V> action) {
5051 dl 1.61 super(p, b);
5052 dl 1.52 this.action = action;
5053     }
5054    
5055 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
5056 dl 1.52 final BiAction<K,V> action = this.action;
5057     if (action == null)
5058 dl 1.61 return abortOnNullFunction();
5059     try {
5060     int b = batch(), c;
5061     while (b > 1 && baseIndex != baseLimit) {
5062     do {} while (!casPending(c = pending, c+1));
5063     new ForEachMappingTask<K,V>(this, b >>>= 1,
5064     action).fork();
5065     }
5066     Object v;
5067     while ((v = advance()) != null)
5068     action.apply((K)nextKey, (V)v);
5069     tryComplete();
5070     } catch (Throwable ex) {
5071     return tryCompleteComputation(ex);
5072 dl 1.52 }
5073 dl 1.61 return false;
5074 dl 1.52 }
5075     }
5076    
5077 dl 1.61 @SuppressWarnings("serial") static final class ForEachTransformedKeyTask<K,V,U>
5078 dl 1.52 extends BulkTask<K,V,Void> {
5079     final Fun<? super K, ? extends U> transformer;
5080     final Action<U> action;
5081     ForEachTransformedKeyTask
5082     (ConcurrentHashMapV8<K,V> m,
5083     Fun<? super K, ? extends U> transformer,
5084     Action<U> action) {
5085     super(m);
5086     this.transformer = transformer;
5087     this.action = action;
5088    
5089     }
5090     ForEachTransformedKeyTask
5091 dl 1.61 (BulkTask<K,V,?> p, int b,
5092 dl 1.52 Fun<? super K, ? extends U> transformer,
5093     Action<U> action) {
5094 dl 1.61 super(p, b);
5095 dl 1.52 this.transformer = transformer;
5096     this.action = action;
5097     }
5098 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
5099 dl 1.52 final Fun<? super K, ? extends U> transformer =
5100     this.transformer;
5101     final Action<U> action = this.action;
5102     if (transformer == null || action == null)
5103 dl 1.61 return abortOnNullFunction();
5104     try {
5105     int b = batch(), c;
5106     while (b > 1 && baseIndex != baseLimit) {
5107     do {} while (!casPending(c = pending, c+1));
5108     new ForEachTransformedKeyTask<K,V,U>
5109     (this, b >>>= 1, transformer, action).fork();
5110     }
5111     U u;
5112     while (advance() != null) {
5113     if ((u = transformer.apply((K)nextKey)) != null)
5114     action.apply(u);
5115     }
5116     tryComplete();
5117     } catch (Throwable ex) {
5118     return tryCompleteComputation(ex);
5119 dl 1.52 }
5120 dl 1.61 return false;
5121 dl 1.52 }
5122     }
5123    
5124 dl 1.61 @SuppressWarnings("serial") static final class ForEachTransformedValueTask<K,V,U>
5125 dl 1.52 extends BulkTask<K,V,Void> {
5126     final Fun<? super V, ? extends U> transformer;
5127     final Action<U> action;
5128     ForEachTransformedValueTask
5129     (ConcurrentHashMapV8<K,V> m,
5130     Fun<? super V, ? extends U> transformer,
5131     Action<U> action) {
5132     super(m);
5133     this.transformer = transformer;
5134     this.action = action;
5135    
5136     }
5137     ForEachTransformedValueTask
5138 dl 1.61 (BulkTask<K,V,?> p, int b,
5139 dl 1.52 Fun<? super V, ? extends U> transformer,
5140     Action<U> action) {
5141 dl 1.61 super(p, b);
5142 dl 1.52 this.transformer = transformer;
5143     this.action = action;
5144     }
5145 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
5146 dl 1.52 final Fun<? super V, ? extends U> transformer =
5147     this.transformer;
5148     final Action<U> action = this.action;
5149     if (transformer == null || action == null)
5150 dl 1.61 return abortOnNullFunction();
5151     try {
5152     int b = batch(), c;
5153     while (b > 1 && baseIndex != baseLimit) {
5154     do {} while (!casPending(c = pending, c+1));
5155     new ForEachTransformedValueTask<K,V,U>
5156     (this, b >>>= 1, transformer, action).fork();
5157     }
5158     Object v; U u;
5159     while ((v = advance()) != null) {
5160     if ((u = transformer.apply((V)v)) != null)
5161     action.apply(u);
5162     }
5163     tryComplete();
5164     } catch (Throwable ex) {
5165     return tryCompleteComputation(ex);
5166 dl 1.52 }
5167 dl 1.61 return false;
5168 dl 1.52 }
5169     }
5170    
5171 dl 1.61 @SuppressWarnings("serial") static final class ForEachTransformedEntryTask<K,V,U>
5172 dl 1.52 extends BulkTask<K,V,Void> {
5173     final Fun<Map.Entry<K,V>, ? extends U> transformer;
5174     final Action<U> action;
5175     ForEachTransformedEntryTask
5176     (ConcurrentHashMapV8<K,V> m,
5177     Fun<Map.Entry<K,V>, ? extends U> transformer,
5178     Action<U> action) {
5179     super(m);
5180     this.transformer = transformer;
5181     this.action = action;
5182    
5183     }
5184     ForEachTransformedEntryTask
5185 dl 1.61 (BulkTask<K,V,?> p, int b,
5186 dl 1.52 Fun<Map.Entry<K,V>, ? extends U> transformer,
5187     Action<U> action) {
5188 dl 1.61 super(p, b);
5189 dl 1.52 this.transformer = transformer;
5190     this.action = action;
5191     }
5192 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
5193 dl 1.52 final Fun<Map.Entry<K,V>, ? extends U> transformer =
5194     this.transformer;
5195     final Action<U> action = this.action;
5196     if (transformer == null || action == null)
5197 dl 1.61 return abortOnNullFunction();
5198     try {
5199     int b = batch(), c;
5200     while (b > 1 && baseIndex != baseLimit) {
5201     do {} while (!casPending(c = pending, c+1));
5202     new ForEachTransformedEntryTask<K,V,U>
5203     (this, b >>>= 1, transformer, action).fork();
5204     }
5205     Object v; U u;
5206     while ((v = advance()) != null) {
5207     if ((u = transformer.apply(entryFor((K)nextKey, (V)v))) != null)
5208     action.apply(u);
5209     }
5210     tryComplete();
5211     } catch (Throwable ex) {
5212     return tryCompleteComputation(ex);
5213 dl 1.52 }
5214 dl 1.61 return false;
5215 dl 1.52 }
5216     }
5217    
5218 dl 1.61 @SuppressWarnings("serial") static final class ForEachTransformedMappingTask<K,V,U>
5219 dl 1.52 extends BulkTask<K,V,Void> {
5220     final BiFun<? super K, ? super V, ? extends U> transformer;
5221     final Action<U> action;
5222     ForEachTransformedMappingTask
5223     (ConcurrentHashMapV8<K,V> m,
5224     BiFun<? super K, ? super V, ? extends U> transformer,
5225     Action<U> action) {
5226     super(m);
5227     this.transformer = transformer;
5228     this.action = action;
5229    
5230     }
5231     ForEachTransformedMappingTask
5232 dl 1.61 (BulkTask<K,V,?> p, int b,
5233 dl 1.52 BiFun<? super K, ? super V, ? extends U> transformer,
5234     Action<U> action) {
5235 dl 1.61 super(p, b);
5236 dl 1.52 this.transformer = transformer;
5237     this.action = action;
5238     }
5239 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
5240 dl 1.52 final BiFun<? super K, ? super V, ? extends U> transformer =
5241     this.transformer;
5242     final Action<U> action = this.action;
5243     if (transformer == null || action == null)
5244 dl 1.61 return abortOnNullFunction();
5245     try {
5246     int b = batch(), c;
5247     while (b > 1 && baseIndex != baseLimit) {
5248     do {} while (!casPending(c = pending, c+1));
5249     new ForEachTransformedMappingTask<K,V,U>
5250     (this, b >>>= 1, transformer, action).fork();
5251     }
5252     Object v; U u;
5253     while ((v = advance()) != null) {
5254     if ((u = transformer.apply((K)nextKey, (V)v)) != null)
5255     action.apply(u);
5256     }
5257     tryComplete();
5258     } catch (Throwable ex) {
5259     return tryCompleteComputation(ex);
5260 dl 1.52 }
5261 dl 1.61 return false;
5262 dl 1.52 }
5263     }
5264    
5265 dl 1.61 @SuppressWarnings("serial") static final class SearchKeysTask<K,V,U>
5266 dl 1.52 extends BulkTask<K,V,U> {
5267     final Fun<? super K, ? extends U> searchFunction;
5268     final AtomicReference<U> result;
5269     SearchKeysTask
5270     (ConcurrentHashMapV8<K,V> m,
5271     Fun<? super K, ? extends U> searchFunction,
5272     AtomicReference<U> result) {
5273     super(m);
5274     this.searchFunction = searchFunction; this.result = result;
5275     }
5276     SearchKeysTask
5277 dl 1.61 (BulkTask<K,V,?> p, int b,
5278 dl 1.52 Fun<? super K, ? extends U> searchFunction,
5279     AtomicReference<U> result) {
5280 dl 1.61 super(p, b);
5281 dl 1.52 this.searchFunction = searchFunction; this.result = result;
5282     }
5283 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
5284 dl 1.52 AtomicReference<U> result = this.result;
5285     final Fun<? super K, ? extends U> searchFunction =
5286     this.searchFunction;
5287     if (searchFunction == null || result == null)
5288 dl 1.61 return abortOnNullFunction();
5289     try {
5290     int b = batch(), c;
5291     while (b > 1 && baseIndex != baseLimit && result.get() == null) {
5292     do {} while (!casPending(c = pending, c+1));
5293     new SearchKeysTask<K,V,U>(this, b >>>= 1,
5294     searchFunction, result).fork();
5295     }
5296     U u;
5297     while (result.get() == null && advance() != null) {
5298     if ((u = searchFunction.apply((K)nextKey)) != null) {
5299     if (result.compareAndSet(null, u))
5300     tryCompleteComputation(null);
5301     break;
5302 dl 1.59 }
5303 dl 1.52 }
5304 dl 1.61 tryComplete();
5305     } catch (Throwable ex) {
5306     return tryCompleteComputation(ex);
5307 dl 1.52 }
5308 dl 1.61 return false;
5309 dl 1.52 }
5310     public final U getRawResult() { return result.get(); }
5311     }
5312    
5313 dl 1.61 @SuppressWarnings("serial") static final class SearchValuesTask<K,V,U>
5314 dl 1.52 extends BulkTask<K,V,U> {
5315     final Fun<? super V, ? extends U> searchFunction;
5316     final AtomicReference<U> result;
5317     SearchValuesTask
5318     (ConcurrentHashMapV8<K,V> m,
5319     Fun<? super V, ? extends U> searchFunction,
5320     AtomicReference<U> result) {
5321     super(m);
5322     this.searchFunction = searchFunction; this.result = result;
5323     }
5324     SearchValuesTask
5325 dl 1.61 (BulkTask<K,V,?> p, int b,
5326 dl 1.52 Fun<? super V, ? extends U> searchFunction,
5327     AtomicReference<U> result) {
5328 dl 1.61 super(p, b);
5329 dl 1.52 this.searchFunction = searchFunction; this.result = result;
5330     }
5331 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
5332 dl 1.52 AtomicReference<U> result = this.result;
5333     final Fun<? super V, ? extends U> searchFunction =
5334     this.searchFunction;
5335     if (searchFunction == null || result == null)
5336 dl 1.61 return abortOnNullFunction();
5337     try {
5338     int b = batch(), c;
5339     while (b > 1 && baseIndex != baseLimit && result.get() == null) {
5340     do {} while (!casPending(c = pending, c+1));
5341     new SearchValuesTask<K,V,U>(this, b >>>= 1,
5342     searchFunction, result).fork();
5343     }
5344     Object v; U u;
5345     while (result.get() == null && (v = advance()) != null) {
5346     if ((u = searchFunction.apply((V)v)) != null) {
5347     if (result.compareAndSet(null, u))
5348     tryCompleteComputation(null);
5349     break;
5350 dl 1.59 }
5351 dl 1.52 }
5352 dl 1.61 tryComplete();
5353     } catch (Throwable ex) {
5354     return tryCompleteComputation(ex);
5355 dl 1.52 }
5356 dl 1.61 return false;
5357 dl 1.52 }
5358     public final U getRawResult() { return result.get(); }
5359     }
5360    
5361 dl 1.61 @SuppressWarnings("serial") static final class SearchEntriesTask<K,V,U>
5362 dl 1.52 extends BulkTask<K,V,U> {
5363     final Fun<Entry<K,V>, ? extends U> searchFunction;
5364     final AtomicReference<U> result;
5365     SearchEntriesTask
5366     (ConcurrentHashMapV8<K,V> m,
5367     Fun<Entry<K,V>, ? extends U> searchFunction,
5368     AtomicReference<U> result) {
5369     super(m);
5370     this.searchFunction = searchFunction; this.result = result;
5371     }
5372     SearchEntriesTask
5373 dl 1.61 (BulkTask<K,V,?> p, int b,
5374 dl 1.52 Fun<Entry<K,V>, ? extends U> searchFunction,
5375     AtomicReference<U> result) {
5376 dl 1.61 super(p, b);
5377 dl 1.52 this.searchFunction = searchFunction; this.result = result;
5378     }
5379 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
5380 dl 1.52 AtomicReference<U> result = this.result;
5381     final Fun<Entry<K,V>, ? extends U> searchFunction =
5382     this.searchFunction;
5383     if (searchFunction == null || result == null)
5384 dl 1.61 return abortOnNullFunction();
5385     try {
5386     int b = batch(), c;
5387     while (b > 1 && baseIndex != baseLimit && result.get() == null) {
5388     do {} while (!casPending(c = pending, c+1));
5389     new SearchEntriesTask<K,V,U>(this, b >>>= 1,
5390     searchFunction, result).fork();
5391     }
5392     Object v; U u;
5393     while (result.get() == null && (v = advance()) != null) {
5394     if ((u = searchFunction.apply(entryFor((K)nextKey, (V)v))) != null) {
5395     if (result.compareAndSet(null, u))
5396     tryCompleteComputation(null);
5397     break;
5398 dl 1.59 }
5399 dl 1.52 }
5400 dl 1.61 tryComplete();
5401     } catch (Throwable ex) {
5402     return tryCompleteComputation(ex);
5403 dl 1.52 }
5404 dl 1.61 return false;
5405 dl 1.52 }
5406     public final U getRawResult() { return result.get(); }
5407     }
5408    
5409 dl 1.61 @SuppressWarnings("serial") static final class SearchMappingsTask<K,V,U>
5410 dl 1.52 extends BulkTask<K,V,U> {
5411     final BiFun<? super K, ? super V, ? extends U> searchFunction;
5412     final AtomicReference<U> result;
5413     SearchMappingsTask
5414     (ConcurrentHashMapV8<K,V> m,
5415     BiFun<? super K, ? super V, ? extends U> searchFunction,
5416     AtomicReference<U> result) {
5417     super(m);
5418     this.searchFunction = searchFunction; this.result = result;
5419     }
5420     SearchMappingsTask
5421 dl 1.61 (BulkTask<K,V,?> p, int b,
5422 dl 1.52 BiFun<? super K, ? super V, ? extends U> searchFunction,
5423     AtomicReference<U> result) {
5424 dl 1.61 super(p, b);
5425 dl 1.52 this.searchFunction = searchFunction; this.result = result;
5426     }
5427 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
5428 dl 1.52 AtomicReference<U> result = this.result;
5429     final BiFun<? super K, ? super V, ? extends U> searchFunction =
5430     this.searchFunction;
5431     if (searchFunction == null || result == null)
5432 dl 1.61 return abortOnNullFunction();
5433     try {
5434     int b = batch(), c;
5435     while (b > 1 && baseIndex != baseLimit && result.get() == null) {
5436     do {} while (!casPending(c = pending, c+1));
5437     new SearchMappingsTask<K,V,U>(this, b >>>= 1,
5438     searchFunction, result).fork();
5439     }
5440     Object v; U u;
5441     while (result.get() == null && (v = advance()) != null) {
5442     if ((u = searchFunction.apply((K)nextKey, (V)v)) != null) {
5443     if (result.compareAndSet(null, u))
5444     tryCompleteComputation(null);
5445     break;
5446 dl 1.59 }
5447 dl 1.52 }
5448 dl 1.61 tryComplete();
5449     } catch (Throwable ex) {
5450     return tryCompleteComputation(ex);
5451 dl 1.52 }
5452 dl 1.61 return false;
5453 dl 1.52 }
5454     public final U getRawResult() { return result.get(); }
5455     }
5456    
5457 dl 1.61 @SuppressWarnings("serial") static final class ReduceKeysTask<K,V>
5458 dl 1.52 extends BulkTask<K,V,K> {
5459     final BiFun<? super K, ? super K, ? extends K> reducer;
5460     K result;
5461 dl 1.61 ReduceKeysTask<K,V> rights, nextRight;
5462 dl 1.52 ReduceKeysTask
5463     (ConcurrentHashMapV8<K,V> m,
5464     BiFun<? super K, ? super K, ? extends K> reducer) {
5465     super(m);
5466     this.reducer = reducer;
5467     }
5468     ReduceKeysTask
5469 dl 1.61 (BulkTask<K,V,?> p, int b,
5470     ReduceKeysTask<K,V> nextRight,
5471 dl 1.52 BiFun<? super K, ? super K, ? extends K> reducer) {
5472 dl 1.61 super(p, b); this.nextRight = nextRight;
5473 dl 1.52 this.reducer = reducer;
5474     }
5475    
5476 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
5477 dl 1.52 final BiFun<? super K, ? super K, ? extends K> reducer =
5478     this.reducer;
5479     if (reducer == null)
5480 dl 1.61 return abortOnNullFunction();
5481     try {
5482     for (int c, b = batch(); b > 1 && baseIndex != baseLimit;) {
5483     do {} while (!casPending(c = pending, c+1));
5484     (rights = new ReduceKeysTask<K,V>
5485     (this, b >>>= 1, rights, reducer)).fork();
5486     }
5487     K r = null;
5488     while (advance() != null) {
5489     K u = (K)nextKey;
5490     r = (r == null) ? u : reducer.apply(r, u);
5491 dl 1.52 }
5492 dl 1.61 result = r;
5493     for (ReduceKeysTask<K,V> t = this, s;;) {
5494     int c; BulkTask<K,V,?> par; K tr, sr;
5495     if ((c = t.pending) == 0) {
5496     for (s = t.rights; s != null; s = t.rights = s.nextRight) {
5497     if ((sr = s.result) != null)
5498     t.result = (tr = t.result) == null? sr : reducer.apply(tr, sr);
5499     }
5500     if ((par = t.parent) == null ||
5501     !(par instanceof ReduceKeysTask)) {
5502     t.quietlyComplete();
5503     break;
5504     }
5505     t = (ReduceKeysTask<K,V>)par;
5506     }
5507     else if (t.casPending(c, c - 1))
5508     break;
5509 dl 1.52 }
5510 dl 1.61 } catch (Throwable ex) {
5511     return tryCompleteComputation(ex);
5512 dl 1.52 }
5513 dl 1.61 return false;
5514 dl 1.52 }
5515     public final K getRawResult() { return result; }
5516     }
5517    
5518 dl 1.61 @SuppressWarnings("serial") static final class ReduceValuesTask<K,V>
5519 dl 1.52 extends BulkTask<K,V,V> {
5520     final BiFun<? super V, ? super V, ? extends V> reducer;
5521     V result;
5522 dl 1.61 ReduceValuesTask<K,V> rights, nextRight;
5523 dl 1.52 ReduceValuesTask
5524     (ConcurrentHashMapV8<K,V> m,
5525     BiFun<? super V, ? super V, ? extends V> reducer) {
5526     super(m);
5527     this.reducer = reducer;
5528     }
5529     ReduceValuesTask
5530 dl 1.61 (BulkTask<K,V,?> p, int b,
5531     ReduceValuesTask<K,V> nextRight,
5532 dl 1.52 BiFun<? super V, ? super V, ? extends V> reducer) {
5533 dl 1.61 super(p, b); this.nextRight = nextRight;
5534 dl 1.52 this.reducer = reducer;
5535     }
5536    
5537 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
5538 dl 1.52 final BiFun<? super V, ? super V, ? extends V> reducer =
5539     this.reducer;
5540     if (reducer == null)
5541 dl 1.61 return abortOnNullFunction();
5542     try {
5543     for (int c, b = batch(); b > 1 && baseIndex != baseLimit;) {
5544     do {} while (!casPending(c = pending, c+1));
5545     (rights = new ReduceValuesTask<K,V>
5546     (this, b >>>= 1, rights, reducer)).fork();
5547     }
5548     V r = null;
5549     Object v;
5550     while ((v = advance()) != null) {
5551     V u = (V)v;
5552     r = (r == null) ? u : reducer.apply(r, u);
5553 dl 1.52 }
5554 dl 1.61 result = r;
5555     for (ReduceValuesTask<K,V> t = this, s;;) {
5556     int c; BulkTask<K,V,?> par; V tr, sr;
5557     if ((c = t.pending) == 0) {
5558     for (s = t.rights; s != null; s = t.rights = s.nextRight) {
5559     if ((sr = s.result) != null)
5560     t.result = (tr = t.result) == null? sr : reducer.apply(tr, sr);
5561     }
5562     if ((par = t.parent) == null ||
5563     !(par instanceof ReduceValuesTask)) {
5564     t.quietlyComplete();
5565     break;
5566     }
5567     t = (ReduceValuesTask<K,V>)par;
5568     }
5569     else if (t.casPending(c, c - 1))
5570     break;
5571 dl 1.52 }
5572 dl 1.61 } catch (Throwable ex) {
5573     return tryCompleteComputation(ex);
5574 dl 1.52 }
5575 dl 1.61 return false;
5576 dl 1.52 }
5577     public final V getRawResult() { return result; }
5578     }
5579    
5580 dl 1.61 @SuppressWarnings("serial") static final class ReduceEntriesTask<K,V>
5581 dl 1.52 extends BulkTask<K,V,Map.Entry<K,V>> {
5582     final BiFun<Map.Entry<K,V>, Map.Entry<K,V>, ? extends Map.Entry<K,V>> reducer;
5583     Map.Entry<K,V> result;
5584 dl 1.61 ReduceEntriesTask<K,V> rights, nextRight;
5585 dl 1.52 ReduceEntriesTask
5586     (ConcurrentHashMapV8<K,V> m,
5587     BiFun<Entry<K,V>, Map.Entry<K,V>, ? extends Map.Entry<K,V>> reducer) {
5588     super(m);
5589     this.reducer = reducer;
5590     }
5591     ReduceEntriesTask
5592 dl 1.61 (BulkTask<K,V,?> p, int b,
5593     ReduceEntriesTask<K,V> nextRight,
5594 dl 1.52 BiFun<Map.Entry<K,V>, Map.Entry<K,V>, ? extends Map.Entry<K,V>> reducer) {
5595 dl 1.61 super(p, b); this.nextRight = nextRight;
5596 dl 1.52 this.reducer = reducer;
5597     }
5598    
5599 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
5600 dl 1.52 final BiFun<Map.Entry<K,V>, Map.Entry<K,V>, ? extends Map.Entry<K,V>> reducer =
5601     this.reducer;
5602     if (reducer == null)
5603 dl 1.61 return abortOnNullFunction();
5604     try {
5605     for (int c, b = batch(); b > 1 && baseIndex != baseLimit;) {
5606     do {} while (!casPending(c = pending, c+1));
5607     (rights = new ReduceEntriesTask<K,V>
5608     (this, b >>>= 1, rights, reducer)).fork();
5609     }
5610     Map.Entry<K,V> r = null;
5611     Object v;
5612     while ((v = advance()) != null) {
5613     Map.Entry<K,V> u = entryFor((K)nextKey, (V)v);
5614     r = (r == null) ? u : reducer.apply(r, u);
5615 dl 1.52 }
5616 dl 1.61 result = r;
5617     for (ReduceEntriesTask<K,V> t = this, s;;) {
5618     int c; BulkTask<K,V,?> par; Map.Entry<K,V> tr, sr;
5619     if ((c = t.pending) == 0) {
5620     for (s = t.rights; s != null; s = t.rights = s.nextRight) {
5621     if ((sr = s.result) != null)
5622     t.result = (tr = t.result) == null? sr : reducer.apply(tr, sr);
5623     }
5624     if ((par = t.parent) == null ||
5625     !(par instanceof ReduceEntriesTask)) {
5626     t.quietlyComplete();
5627     break;
5628     }
5629     t = (ReduceEntriesTask<K,V>)par;
5630     }
5631     else if (t.casPending(c, c - 1))
5632     break;
5633 dl 1.52 }
5634 dl 1.61 } catch (Throwable ex) {
5635     return tryCompleteComputation(ex);
5636 dl 1.52 }
5637 dl 1.61 return false;
5638 dl 1.52 }
5639     public final Map.Entry<K,V> getRawResult() { return result; }
5640     }
5641    
5642 dl 1.61 @SuppressWarnings("serial") static final class MapReduceKeysTask<K,V,U>
5643 dl 1.52 extends BulkTask<K,V,U> {
5644     final Fun<? super K, ? extends U> transformer;
5645     final BiFun<? super U, ? super U, ? extends U> reducer;
5646     U result;
5647 dl 1.61 MapReduceKeysTask<K,V,U> rights, nextRight;
5648 dl 1.52 MapReduceKeysTask
5649     (ConcurrentHashMapV8<K,V> m,
5650     Fun<? super K, ? extends U> transformer,
5651     BiFun<? super U, ? super U, ? extends U> reducer) {
5652     super(m);
5653     this.transformer = transformer;
5654     this.reducer = reducer;
5655     }
5656     MapReduceKeysTask
5657 dl 1.61 (BulkTask<K,V,?> p, int b,
5658     MapReduceKeysTask<K,V,U> nextRight,
5659 dl 1.52 Fun<? super K, ? extends U> transformer,
5660     BiFun<? super U, ? super U, ? extends U> reducer) {
5661 dl 1.61 super(p, b); this.nextRight = nextRight;
5662 dl 1.52 this.transformer = transformer;
5663     this.reducer = reducer;
5664     }
5665 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
5666 dl 1.52 final Fun<? super K, ? extends U> transformer =
5667     this.transformer;
5668     final BiFun<? super U, ? super U, ? extends U> reducer =
5669     this.reducer;
5670     if (transformer == null || reducer == null)
5671 dl 1.61 return abortOnNullFunction();
5672     try {
5673     for (int c, b = batch(); b > 1 && baseIndex != baseLimit;) {
5674     do {} while (!casPending(c = pending, c+1));
5675     (rights = new MapReduceKeysTask<K,V,U>
5676     (this, b >>>= 1, rights, transformer, reducer)).fork();
5677     }
5678     U r = null, u;
5679     while (advance() != null) {
5680     if ((u = transformer.apply((K)nextKey)) != null)
5681     r = (r == null) ? u : reducer.apply(r, u);
5682 dl 1.52 }
5683 dl 1.61 result = r;
5684     for (MapReduceKeysTask<K,V,U> t = this, s;;) {
5685     int c; BulkTask<K,V,?> par; U tr, sr;
5686     if ((c = t.pending) == 0) {
5687     for (s = t.rights; s != null; s = t.rights = s.nextRight) {
5688     if ((sr = s.result) != null)
5689     t.result = (tr = t.result) == null? sr : reducer.apply(tr, sr);
5690     }
5691     if ((par = t.parent) == null ||
5692     !(par instanceof MapReduceKeysTask)) {
5693     t.quietlyComplete();
5694     break;
5695     }
5696     t = (MapReduceKeysTask<K,V,U>)par;
5697     }
5698     else if (t.casPending(c, c - 1))
5699     break;
5700 dl 1.52 }
5701 dl 1.61 } catch (Throwable ex) {
5702     return tryCompleteComputation(ex);
5703 dl 1.52 }
5704 dl 1.61 return false;
5705 dl 1.52 }
5706     public final U getRawResult() { return result; }
5707     }
5708    
5709 dl 1.61 @SuppressWarnings("serial") static final class MapReduceValuesTask<K,V,U>
5710 dl 1.52 extends BulkTask<K,V,U> {
5711     final Fun<? super V, ? extends U> transformer;
5712     final BiFun<? super U, ? super U, ? extends U> reducer;
5713     U result;
5714 dl 1.61 MapReduceValuesTask<K,V,U> rights, nextRight;
5715 dl 1.52 MapReduceValuesTask
5716     (ConcurrentHashMapV8<K,V> m,
5717     Fun<? super V, ? extends U> transformer,
5718     BiFun<? super U, ? super U, ? extends U> reducer) {
5719     super(m);
5720     this.transformer = transformer;
5721     this.reducer = reducer;
5722     }
5723     MapReduceValuesTask
5724 dl 1.61 (BulkTask<K,V,?> p, int b,
5725     MapReduceValuesTask<K,V,U> nextRight,
5726 dl 1.52 Fun<? super V, ? extends U> transformer,
5727     BiFun<? super U, ? super U, ? extends U> reducer) {
5728 dl 1.61 super(p, b); this.nextRight = nextRight;
5729 dl 1.52 this.transformer = transformer;
5730     this.reducer = reducer;
5731     }
5732 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
5733 dl 1.52 final Fun<? super V, ? extends U> transformer =
5734     this.transformer;
5735     final BiFun<? super U, ? super U, ? extends U> reducer =
5736     this.reducer;
5737     if (transformer == null || reducer == null)
5738 dl 1.61 return abortOnNullFunction();
5739     try {
5740     for (int c, b = batch(); b > 1 && baseIndex != baseLimit;) {
5741     do {} while (!casPending(c = pending, c+1));
5742     (rights = new MapReduceValuesTask<K,V,U>
5743     (this, b >>>= 1, rights, transformer, reducer)).fork();
5744     }
5745     U r = null, u;
5746     Object v;
5747     while ((v = advance()) != null) {
5748     if ((u = transformer.apply((V)v)) != null)
5749     r = (r == null) ? u : reducer.apply(r, u);
5750 dl 1.52 }
5751 dl 1.61 result = r;
5752     for (MapReduceValuesTask<K,V,U> t = this, s;;) {
5753     int c; BulkTask<K,V,?> par; U tr, sr;
5754     if ((c = t.pending) == 0) {
5755     for (s = t.rights; s != null; s = t.rights = s.nextRight) {
5756     if ((sr = s.result) != null)
5757     t.result = (tr = t.result) == null? sr : reducer.apply(tr, sr);
5758     }
5759     if ((par = t.parent) == null ||
5760     !(par instanceof MapReduceValuesTask)) {
5761     t.quietlyComplete();
5762     break;
5763     }
5764     t = (MapReduceValuesTask<K,V,U>)par;
5765     }
5766     else if (t.casPending(c, c - 1))
5767     break;
5768 dl 1.52 }
5769 dl 1.61 } catch (Throwable ex) {
5770     return tryCompleteComputation(ex);
5771 dl 1.52 }
5772 dl 1.61 return false;
5773 dl 1.52 }
5774     public final U getRawResult() { return result; }
5775     }
5776    
5777 dl 1.61 @SuppressWarnings("serial") static final class MapReduceEntriesTask<K,V,U>
5778 dl 1.52 extends BulkTask<K,V,U> {
5779     final Fun<Map.Entry<K,V>, ? extends U> transformer;
5780     final BiFun<? super U, ? super U, ? extends U> reducer;
5781     U result;
5782 dl 1.61 MapReduceEntriesTask<K,V,U> rights, nextRight;
5783 dl 1.52 MapReduceEntriesTask
5784     (ConcurrentHashMapV8<K,V> m,
5785     Fun<Map.Entry<K,V>, ? extends U> transformer,
5786     BiFun<? super U, ? super U, ? extends U> reducer) {
5787     super(m);
5788     this.transformer = transformer;
5789     this.reducer = reducer;
5790     }
5791     MapReduceEntriesTask
5792 dl 1.61 (BulkTask<K,V,?> p, int b,
5793     MapReduceEntriesTask<K,V,U> nextRight,
5794 dl 1.52 Fun<Map.Entry<K,V>, ? extends U> transformer,
5795     BiFun<? super U, ? super U, ? extends U> reducer) {
5796 dl 1.61 super(p, b); this.nextRight = nextRight;
5797 dl 1.52 this.transformer = transformer;
5798     this.reducer = reducer;
5799     }
5800 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
5801 dl 1.52 final Fun<Map.Entry<K,V>, ? extends U> transformer =
5802     this.transformer;
5803     final BiFun<? super U, ? super U, ? extends U> reducer =
5804     this.reducer;
5805     if (transformer == null || reducer == null)
5806 dl 1.61 return abortOnNullFunction();
5807     try {
5808     for (int c, b = batch(); b > 1 && baseIndex != baseLimit;) {
5809     do {} while (!casPending(c = pending, c+1));
5810     (rights = new MapReduceEntriesTask<K,V,U>
5811     (this, b >>>= 1, rights, transformer, reducer)).fork();
5812     }
5813     U r = null, u;
5814     Object v;
5815     while ((v = advance()) != null) {
5816     if ((u = transformer.apply(entryFor((K)nextKey, (V)v))) != null)
5817     r = (r == null) ? u : reducer.apply(r, u);
5818 dl 1.52 }
5819 dl 1.61 result = r;
5820     for (MapReduceEntriesTask<K,V,U> t = this, s;;) {
5821     int c; BulkTask<K,V,?> par; U tr, sr;
5822     if ((c = t.pending) == 0) {
5823     for (s = t.rights; s != null; s = t.rights = s.nextRight) {
5824     if ((sr = s.result) != null)
5825     t.result = (tr = t.result) == null? sr : reducer.apply(tr, sr);
5826     }
5827     if ((par = t.parent) == null ||
5828     !(par instanceof MapReduceEntriesTask)) {
5829     t.quietlyComplete();
5830     break;
5831     }
5832     t = (MapReduceEntriesTask<K,V,U>)par;
5833     }
5834     else if (t.casPending(c, c - 1))
5835     break;
5836 dl 1.52 }
5837 dl 1.61 } catch (Throwable ex) {
5838     return tryCompleteComputation(ex);
5839 dl 1.52 }
5840 dl 1.61 return false;
5841 dl 1.52 }
5842     public final U getRawResult() { return result; }
5843     }
5844    
5845 dl 1.61 @SuppressWarnings("serial") static final class MapReduceMappingsTask<K,V,U>
5846 dl 1.52 extends BulkTask<K,V,U> {
5847     final BiFun<? super K, ? super V, ? extends U> transformer;
5848     final BiFun<? super U, ? super U, ? extends U> reducer;
5849     U result;
5850 dl 1.61 MapReduceMappingsTask<K,V,U> rights, nextRight;
5851 dl 1.52 MapReduceMappingsTask
5852     (ConcurrentHashMapV8<K,V> m,
5853     BiFun<? super K, ? super V, ? extends U> transformer,
5854     BiFun<? super U, ? super U, ? extends U> reducer) {
5855     super(m);
5856     this.transformer = transformer;
5857     this.reducer = reducer;
5858     }
5859     MapReduceMappingsTask
5860 dl 1.61 (BulkTask<K,V,?> p, int b,
5861     MapReduceMappingsTask<K,V,U> nextRight,
5862 dl 1.52 BiFun<? super K, ? super V, ? extends U> transformer,
5863     BiFun<? super U, ? super U, ? extends U> reducer) {
5864 dl 1.61 super(p, b); this.nextRight = nextRight;
5865 dl 1.52 this.transformer = transformer;
5866     this.reducer = reducer;
5867     }
5868 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
5869 dl 1.52 final BiFun<? super K, ? super V, ? extends U> transformer =
5870     this.transformer;
5871     final BiFun<? super U, ? super U, ? extends U> reducer =
5872     this.reducer;
5873     if (transformer == null || reducer == null)
5874 dl 1.61 return abortOnNullFunction();
5875     try {
5876     for (int c, b = batch(); b > 1 && baseIndex != baseLimit;) {
5877     do {} while (!casPending(c = pending, c+1));
5878     (rights = new MapReduceMappingsTask<K,V,U>
5879     (this, b >>>= 1, rights, transformer, reducer)).fork();
5880     }
5881     U r = null, u;
5882     Object v;
5883     while ((v = advance()) != null) {
5884     if ((u = transformer.apply((K)nextKey, (V)v)) != null)
5885     r = (r == null) ? u : reducer.apply(r, u);
5886 dl 1.52 }
5887 dl 1.61 result = r;
5888     for (MapReduceMappingsTask<K,V,U> t = this, s;;) {
5889     int c; BulkTask<K,V,?> par; U tr, sr;
5890     if ((c = t.pending) == 0) {
5891     for (s = t.rights; s != null; s = t.rights = s.nextRight) {
5892     if ((sr = s.result) != null)
5893     t.result = (tr = t.result) == null? sr : reducer.apply(tr, sr);
5894     }
5895     if ((par = t.parent) == null ||
5896     !(par instanceof MapReduceMappingsTask)) {
5897     t.quietlyComplete();
5898     break;
5899     }
5900     t = (MapReduceMappingsTask<K,V,U>)par;
5901     }
5902     else if (t.casPending(c, c - 1))
5903     break;
5904 dl 1.52 }
5905 dl 1.61 } catch (Throwable ex) {
5906     return tryCompleteComputation(ex);
5907 dl 1.52 }
5908 dl 1.61 return false;
5909 dl 1.52 }
5910     public final U getRawResult() { return result; }
5911     }
5912    
5913 dl 1.61 @SuppressWarnings("serial") static final class MapReduceKeysToDoubleTask<K,V>
5914 dl 1.52 extends BulkTask<K,V,Double> {
5915     final ObjectToDouble<? super K> transformer;
5916     final DoubleByDoubleToDouble reducer;
5917     final double basis;
5918     double result;
5919 dl 1.61 MapReduceKeysToDoubleTask<K,V> rights, nextRight;
5920 dl 1.52 MapReduceKeysToDoubleTask
5921     (ConcurrentHashMapV8<K,V> m,
5922     ObjectToDouble<? super K> transformer,
5923     double basis,
5924     DoubleByDoubleToDouble reducer) {
5925     super(m);
5926     this.transformer = transformer;
5927     this.basis = basis; this.reducer = reducer;
5928     }
5929     MapReduceKeysToDoubleTask
5930 dl 1.61 (BulkTask<K,V,?> p, int b,
5931     MapReduceKeysToDoubleTask<K,V> nextRight,
5932 dl 1.52 ObjectToDouble<? super K> transformer,
5933     double basis,
5934     DoubleByDoubleToDouble reducer) {
5935 dl 1.61 super(p, b); this.nextRight = nextRight;
5936 dl 1.52 this.transformer = transformer;
5937     this.basis = basis; this.reducer = reducer;
5938     }
5939 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
5940 dl 1.52 final ObjectToDouble<? super K> transformer =
5941     this.transformer;
5942     final DoubleByDoubleToDouble reducer = this.reducer;
5943     if (transformer == null || reducer == null)
5944 dl 1.61 return abortOnNullFunction();
5945     try {
5946     final double id = this.basis;
5947     for (int c, b = batch(); b > 1 && baseIndex != baseLimit;) {
5948     do {} while (!casPending(c = pending, c+1));
5949     (rights = new MapReduceKeysToDoubleTask<K,V>
5950     (this, b >>>= 1, rights, transformer, id, reducer)).fork();
5951     }
5952     double r = id;
5953     while (advance() != null)
5954     r = reducer.apply(r, transformer.apply((K)nextKey));
5955     result = r;
5956     for (MapReduceKeysToDoubleTask<K,V> t = this, s;;) {
5957     int c; BulkTask<K,V,?> par;
5958     if ((c = t.pending) == 0) {
5959     for (s = t.rights; s != null; s = t.rights = s.nextRight) {
5960     t.result = reducer.apply(t.result, s.result);
5961     }
5962     if ((par = t.parent) == null ||
5963     !(par instanceof MapReduceKeysToDoubleTask)) {
5964     t.quietlyComplete();
5965     break;
5966     }
5967     t = (MapReduceKeysToDoubleTask<K,V>)par;
5968     }
5969     else if (t.casPending(c, c - 1))
5970     break;
5971 dl 1.52 }
5972 dl 1.61 } catch (Throwable ex) {
5973     return tryCompleteComputation(ex);
5974 dl 1.52 }
5975 dl 1.61 return false;
5976 dl 1.52 }
5977     public final Double getRawResult() { return result; }
5978     }
5979    
5980 dl 1.61 @SuppressWarnings("serial") static final class MapReduceValuesToDoubleTask<K,V>
5981 dl 1.52 extends BulkTask<K,V,Double> {
5982     final ObjectToDouble<? super V> transformer;
5983     final DoubleByDoubleToDouble reducer;
5984     final double basis;
5985     double result;
5986 dl 1.61 MapReduceValuesToDoubleTask<K,V> rights, nextRight;
5987 dl 1.52 MapReduceValuesToDoubleTask
5988     (ConcurrentHashMapV8<K,V> m,
5989     ObjectToDouble<? super V> transformer,
5990     double basis,
5991     DoubleByDoubleToDouble reducer) {
5992     super(m);
5993     this.transformer = transformer;
5994     this.basis = basis; this.reducer = reducer;
5995     }
5996     MapReduceValuesToDoubleTask
5997 dl 1.61 (BulkTask<K,V,?> p, int b,
5998     MapReduceValuesToDoubleTask<K,V> nextRight,
5999 dl 1.52 ObjectToDouble<? super V> transformer,
6000     double basis,
6001     DoubleByDoubleToDouble reducer) {
6002 dl 1.61 super(p, b); this.nextRight = nextRight;
6003 dl 1.52 this.transformer = transformer;
6004     this.basis = basis; this.reducer = reducer;
6005     }
6006 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
6007 dl 1.52 final ObjectToDouble<? super V> transformer =
6008     this.transformer;
6009     final DoubleByDoubleToDouble reducer = this.reducer;
6010     if (transformer == null || reducer == null)
6011 dl 1.61 return abortOnNullFunction();
6012     try {
6013     final double id = this.basis;
6014     for (int c, b = batch(); b > 1 && baseIndex != baseLimit;) {
6015     do {} while (!casPending(c = pending, c+1));
6016     (rights = new MapReduceValuesToDoubleTask<K,V>
6017     (this, b >>>= 1, rights, transformer, id, reducer)).fork();
6018     }
6019     double r = id;
6020     Object v;
6021     while ((v = advance()) != null)
6022     r = reducer.apply(r, transformer.apply((V)v));
6023     result = r;
6024     for (MapReduceValuesToDoubleTask<K,V> t = this, s;;) {
6025     int c; BulkTask<K,V,?> par;
6026     if ((c = t.pending) == 0) {
6027     for (s = t.rights; s != null; s = t.rights = s.nextRight) {
6028     t.result = reducer.apply(t.result, s.result);
6029     }
6030     if ((par = t.parent) == null ||
6031     !(par instanceof MapReduceValuesToDoubleTask)) {
6032     t.quietlyComplete();
6033     break;
6034     }
6035     t = (MapReduceValuesToDoubleTask<K,V>)par;
6036     }
6037     else if (t.casPending(c, c - 1))
6038     break;
6039 dl 1.52 }
6040 dl 1.61 } catch (Throwable ex) {
6041     return tryCompleteComputation(ex);
6042 dl 1.52 }
6043 dl 1.61 return false;
6044 dl 1.52 }
6045     public final Double getRawResult() { return result; }
6046     }
6047    
6048 dl 1.61 @SuppressWarnings("serial") static final class MapReduceEntriesToDoubleTask<K,V>
6049 dl 1.52 extends BulkTask<K,V,Double> {
6050     final ObjectToDouble<Map.Entry<K,V>> transformer;
6051     final DoubleByDoubleToDouble reducer;
6052     final double basis;
6053     double result;
6054 dl 1.61 MapReduceEntriesToDoubleTask<K,V> rights, nextRight;
6055 dl 1.52 MapReduceEntriesToDoubleTask
6056     (ConcurrentHashMapV8<K,V> m,
6057     ObjectToDouble<Map.Entry<K,V>> transformer,
6058     double basis,
6059     DoubleByDoubleToDouble reducer) {
6060     super(m);
6061     this.transformer = transformer;
6062     this.basis = basis; this.reducer = reducer;
6063     }
6064     MapReduceEntriesToDoubleTask
6065 dl 1.61 (BulkTask<K,V,?> p, int b,
6066     MapReduceEntriesToDoubleTask<K,V> nextRight,
6067 dl 1.52 ObjectToDouble<Map.Entry<K,V>> transformer,
6068     double basis,
6069     DoubleByDoubleToDouble reducer) {
6070 dl 1.61 super(p, b); this.nextRight = nextRight;
6071 dl 1.52 this.transformer = transformer;
6072     this.basis = basis; this.reducer = reducer;
6073     }
6074 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
6075 dl 1.52 final ObjectToDouble<Map.Entry<K,V>> transformer =
6076     this.transformer;
6077     final DoubleByDoubleToDouble reducer = this.reducer;
6078     if (transformer == null || reducer == null)
6079 dl 1.61 return abortOnNullFunction();
6080     try {
6081     final double id = this.basis;
6082     for (int c, b = batch(); b > 1 && baseIndex != baseLimit;) {
6083     do {} while (!casPending(c = pending, c+1));
6084     (rights = new MapReduceEntriesToDoubleTask<K,V>
6085     (this, b >>>= 1, rights, transformer, id, reducer)).fork();
6086     }
6087     double r = id;
6088     Object v;
6089     while ((v = advance()) != null)
6090     r = reducer.apply(r, transformer.apply(entryFor((K)nextKey, (V)v)));
6091     result = r;
6092     for (MapReduceEntriesToDoubleTask<K,V> t = this, s;;) {
6093     int c; BulkTask<K,V,?> par;
6094     if ((c = t.pending) == 0) {
6095     for (s = t.rights; s != null; s = t.rights = s.nextRight) {
6096     t.result = reducer.apply(t.result, s.result);
6097     }
6098     if ((par = t.parent) == null ||
6099     !(par instanceof MapReduceEntriesToDoubleTask)) {
6100     t.quietlyComplete();
6101     break;
6102     }
6103     t = (MapReduceEntriesToDoubleTask<K,V>)par;
6104     }
6105     else if (t.casPending(c, c - 1))
6106     break;
6107 dl 1.52 }
6108 dl 1.61 } catch (Throwable ex) {
6109     return tryCompleteComputation(ex);
6110 dl 1.52 }
6111 dl 1.61 return false;
6112 dl 1.52 }
6113     public final Double getRawResult() { return result; }
6114     }
6115    
6116 dl 1.61 @SuppressWarnings("serial") static final class MapReduceMappingsToDoubleTask<K,V>
6117 dl 1.52 extends BulkTask<K,V,Double> {
6118     final ObjectByObjectToDouble<? super K, ? super V> transformer;
6119     final DoubleByDoubleToDouble reducer;
6120     final double basis;
6121     double result;
6122 dl 1.61 MapReduceMappingsToDoubleTask<K,V> rights, nextRight;
6123 dl 1.52 MapReduceMappingsToDoubleTask
6124     (ConcurrentHashMapV8<K,V> m,
6125     ObjectByObjectToDouble<? super K, ? super V> transformer,
6126     double basis,
6127     DoubleByDoubleToDouble reducer) {
6128     super(m);
6129     this.transformer = transformer;
6130     this.basis = basis; this.reducer = reducer;
6131     }
6132     MapReduceMappingsToDoubleTask
6133 dl 1.61 (BulkTask<K,V,?> p, int b,
6134     MapReduceMappingsToDoubleTask<K,V> nextRight,
6135 dl 1.52 ObjectByObjectToDouble<? super K, ? super V> transformer,
6136     double basis,
6137     DoubleByDoubleToDouble reducer) {
6138 dl 1.61 super(p, b); this.nextRight = nextRight;
6139 dl 1.52 this.transformer = transformer;
6140     this.basis = basis; this.reducer = reducer;
6141     }
6142 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
6143 dl 1.52 final ObjectByObjectToDouble<? super K, ? super V> transformer =
6144     this.transformer;
6145     final DoubleByDoubleToDouble reducer = this.reducer;
6146     if (transformer == null || reducer == null)
6147 dl 1.61 return abortOnNullFunction();
6148     try {
6149     final double id = this.basis;
6150     for (int c, b = batch(); b > 1 && baseIndex != baseLimit;) {
6151     do {} while (!casPending(c = pending, c+1));
6152     (rights = new MapReduceMappingsToDoubleTask<K,V>
6153     (this, b >>>= 1, rights, transformer, id, reducer)).fork();
6154     }
6155     double r = id;
6156     Object v;
6157     while ((v = advance()) != null)
6158     r = reducer.apply(r, transformer.apply((K)nextKey, (V)v));
6159     result = r;
6160     for (MapReduceMappingsToDoubleTask<K,V> t = this, s;;) {
6161     int c; BulkTask<K,V,?> par;
6162     if ((c = t.pending) == 0) {
6163     for (s = t.rights; s != null; s = t.rights = s.nextRight) {
6164     t.result = reducer.apply(t.result, s.result);
6165     }
6166     if ((par = t.parent) == null ||
6167     !(par instanceof MapReduceMappingsToDoubleTask)) {
6168     t.quietlyComplete();
6169     break;
6170     }
6171     t = (MapReduceMappingsToDoubleTask<K,V>)par;
6172     }
6173     else if (t.casPending(c, c - 1))
6174     break;
6175 dl 1.52 }
6176 dl 1.61 } catch (Throwable ex) {
6177     return tryCompleteComputation(ex);
6178 dl 1.52 }
6179 dl 1.61 return false;
6180 dl 1.52 }
6181     public final Double getRawResult() { return result; }
6182     }
6183    
6184 dl 1.61 @SuppressWarnings("serial") static final class MapReduceKeysToLongTask<K,V>
6185 dl 1.52 extends BulkTask<K,V,Long> {
6186     final ObjectToLong<? super K> transformer;
6187     final LongByLongToLong reducer;
6188     final long basis;
6189     long result;
6190 dl 1.61 MapReduceKeysToLongTask<K,V> rights, nextRight;
6191 dl 1.52 MapReduceKeysToLongTask
6192     (ConcurrentHashMapV8<K,V> m,
6193     ObjectToLong<? super K> transformer,
6194     long basis,
6195     LongByLongToLong reducer) {
6196     super(m);
6197     this.transformer = transformer;
6198     this.basis = basis; this.reducer = reducer;
6199     }
6200     MapReduceKeysToLongTask
6201 dl 1.61 (BulkTask<K,V,?> p, int b,
6202     MapReduceKeysToLongTask<K,V> nextRight,
6203 dl 1.52 ObjectToLong<? super K> transformer,
6204     long basis,
6205     LongByLongToLong reducer) {
6206 dl 1.61 super(p, b); this.nextRight = nextRight;
6207 dl 1.52 this.transformer = transformer;
6208     this.basis = basis; this.reducer = reducer;
6209     }
6210 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
6211 dl 1.52 final ObjectToLong<? super K> transformer =
6212     this.transformer;
6213     final LongByLongToLong reducer = this.reducer;
6214     if (transformer == null || reducer == null)
6215 dl 1.61 return abortOnNullFunction();
6216     try {
6217     final long id = this.basis;
6218     for (int c, b = batch(); b > 1 && baseIndex != baseLimit;) {
6219     do {} while (!casPending(c = pending, c+1));
6220     (rights = new MapReduceKeysToLongTask<K,V>
6221     (this, b >>>= 1, rights, transformer, id, reducer)).fork();
6222     }
6223     long r = id;
6224     while (advance() != null)
6225     r = reducer.apply(r, transformer.apply((K)nextKey));
6226     result = r;
6227     for (MapReduceKeysToLongTask<K,V> t = this, s;;) {
6228     int c; BulkTask<K,V,?> par;
6229     if ((c = t.pending) == 0) {
6230     for (s = t.rights; s != null; s = t.rights = s.nextRight) {
6231     t.result = reducer.apply(t.result, s.result);
6232     }
6233     if ((par = t.parent) == null ||
6234     !(par instanceof MapReduceKeysToLongTask)) {
6235     t.quietlyComplete();
6236     break;
6237     }
6238     t = (MapReduceKeysToLongTask<K,V>)par;
6239     }
6240     else if (t.casPending(c, c - 1))
6241     break;
6242 dl 1.52 }
6243 dl 1.61 } catch (Throwable ex) {
6244     return tryCompleteComputation(ex);
6245 dl 1.52 }
6246 dl 1.61 return false;
6247 dl 1.52 }
6248     public final Long getRawResult() { return result; }
6249     }
6250    
6251 dl 1.61 @SuppressWarnings("serial") static final class MapReduceValuesToLongTask<K,V>
6252 dl 1.52 extends BulkTask<K,V,Long> {
6253     final ObjectToLong<? super V> transformer;
6254     final LongByLongToLong reducer;
6255     final long basis;
6256     long result;
6257 dl 1.61 MapReduceValuesToLongTask<K,V> rights, nextRight;
6258 dl 1.52 MapReduceValuesToLongTask
6259     (ConcurrentHashMapV8<K,V> m,
6260     ObjectToLong<? super V> transformer,
6261     long basis,
6262     LongByLongToLong reducer) {
6263     super(m);
6264     this.transformer = transformer;
6265     this.basis = basis; this.reducer = reducer;
6266     }
6267     MapReduceValuesToLongTask
6268 dl 1.61 (BulkTask<K,V,?> p, int b,
6269     MapReduceValuesToLongTask<K,V> nextRight,
6270 dl 1.52 ObjectToLong<? super V> transformer,
6271     long basis,
6272     LongByLongToLong reducer) {
6273 dl 1.61 super(p, b); this.nextRight = nextRight;
6274 dl 1.52 this.transformer = transformer;
6275     this.basis = basis; this.reducer = reducer;
6276     }
6277 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
6278 dl 1.52 final ObjectToLong<? super V> transformer =
6279     this.transformer;
6280     final LongByLongToLong reducer = this.reducer;
6281     if (transformer == null || reducer == null)
6282 dl 1.61 return abortOnNullFunction();
6283     try {
6284     final long id = this.basis;
6285     for (int c, b = batch(); b > 1 && baseIndex != baseLimit;) {
6286     do {} while (!casPending(c = pending, c+1));
6287     (rights = new MapReduceValuesToLongTask<K,V>
6288     (this, b >>>= 1, rights, transformer, id, reducer)).fork();
6289     }
6290     long r = id;
6291     Object v;
6292     while ((v = advance()) != null)
6293     r = reducer.apply(r, transformer.apply((V)v));
6294     result = r;
6295     for (MapReduceValuesToLongTask<K,V> t = this, s;;) {
6296     int c; BulkTask<K,V,?> par;
6297     if ((c = t.pending) == 0) {
6298     for (s = t.rights; s != null; s = t.rights = s.nextRight) {
6299     t.result = reducer.apply(t.result, s.result);
6300     }
6301     if ((par = t.parent) == null ||
6302     !(par instanceof MapReduceValuesToLongTask)) {
6303     t.quietlyComplete();
6304     break;
6305     }
6306     t = (MapReduceValuesToLongTask<K,V>)par;
6307     }
6308     else if (t.casPending(c, c - 1))
6309     break;
6310 dl 1.52 }
6311 dl 1.61 } catch (Throwable ex) {
6312     return tryCompleteComputation(ex);
6313 dl 1.52 }
6314 dl 1.61 return false;
6315 dl 1.52 }
6316     public final Long getRawResult() { return result; }
6317     }
6318    
6319 dl 1.61 @SuppressWarnings("serial") static final class MapReduceEntriesToLongTask<K,V>
6320 dl 1.52 extends BulkTask<K,V,Long> {
6321     final ObjectToLong<Map.Entry<K,V>> transformer;
6322     final LongByLongToLong reducer;
6323     final long basis;
6324     long result;
6325 dl 1.61 MapReduceEntriesToLongTask<K,V> rights, nextRight;
6326 dl 1.52 MapReduceEntriesToLongTask
6327     (ConcurrentHashMapV8<K,V> m,
6328     ObjectToLong<Map.Entry<K,V>> transformer,
6329     long basis,
6330     LongByLongToLong reducer) {
6331     super(m);
6332     this.transformer = transformer;
6333     this.basis = basis; this.reducer = reducer;
6334     }
6335     MapReduceEntriesToLongTask
6336 dl 1.61 (BulkTask<K,V,?> p, int b,
6337     MapReduceEntriesToLongTask<K,V> nextRight,
6338 dl 1.52 ObjectToLong<Map.Entry<K,V>> transformer,
6339     long basis,
6340     LongByLongToLong reducer) {
6341 dl 1.61 super(p, b); this.nextRight = nextRight;
6342 dl 1.52 this.transformer = transformer;
6343     this.basis = basis; this.reducer = reducer;
6344     }
6345 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
6346 dl 1.52 final ObjectToLong<Map.Entry<K,V>> transformer =
6347     this.transformer;
6348     final LongByLongToLong reducer = this.reducer;
6349     if (transformer == null || reducer == null)
6350 dl 1.61 return abortOnNullFunction();
6351     try {
6352     final long id = this.basis;
6353     for (int c, b = batch(); b > 1 && baseIndex != baseLimit;) {
6354     do {} while (!casPending(c = pending, c+1));
6355     (rights = new MapReduceEntriesToLongTask<K,V>
6356     (this, b >>>= 1, rights, transformer, id, reducer)).fork();
6357     }
6358     long r = id;
6359     Object v;
6360     while ((v = advance()) != null)
6361     r = reducer.apply(r, transformer.apply(entryFor((K)nextKey, (V)v)));
6362     result = r;
6363     for (MapReduceEntriesToLongTask<K,V> t = this, s;;) {
6364     int c; BulkTask<K,V,?> par;
6365     if ((c = t.pending) == 0) {
6366     for (s = t.rights; s != null; s = t.rights = s.nextRight) {
6367     t.result = reducer.apply(t.result, s.result);
6368     }
6369     if ((par = t.parent) == null ||
6370     !(par instanceof MapReduceEntriesToLongTask)) {
6371     t.quietlyComplete();
6372     break;
6373     }
6374     t = (MapReduceEntriesToLongTask<K,V>)par;
6375     }
6376     else if (t.casPending(c, c - 1))
6377     break;
6378 dl 1.52 }
6379 dl 1.61 } catch (Throwable ex) {
6380     return tryCompleteComputation(ex);
6381 dl 1.52 }
6382 dl 1.61 return false;
6383 dl 1.52 }
6384     public final Long getRawResult() { return result; }
6385     }
6386    
6387 dl 1.61 @SuppressWarnings("serial") static final class MapReduceMappingsToLongTask<K,V>
6388 dl 1.52 extends BulkTask<K,V,Long> {
6389     final ObjectByObjectToLong<? super K, ? super V> transformer;
6390     final LongByLongToLong reducer;
6391     final long basis;
6392     long result;
6393 dl 1.61 MapReduceMappingsToLongTask<K,V> rights, nextRight;
6394 dl 1.52 MapReduceMappingsToLongTask
6395     (ConcurrentHashMapV8<K,V> m,
6396     ObjectByObjectToLong<? super K, ? super V> transformer,
6397     long basis,
6398     LongByLongToLong reducer) {
6399     super(m);
6400     this.transformer = transformer;
6401     this.basis = basis; this.reducer = reducer;
6402     }
6403     MapReduceMappingsToLongTask
6404 dl 1.61 (BulkTask<K,V,?> p, int b,
6405     MapReduceMappingsToLongTask<K,V> nextRight,
6406 dl 1.52 ObjectByObjectToLong<? super K, ? super V> transformer,
6407     long basis,
6408     LongByLongToLong reducer) {
6409 dl 1.61 super(p, b); this.nextRight = nextRight;
6410 dl 1.52 this.transformer = transformer;
6411     this.basis = basis; this.reducer = reducer;
6412     }
6413 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
6414 dl 1.52 final ObjectByObjectToLong<? super K, ? super V> transformer =
6415     this.transformer;
6416     final LongByLongToLong reducer = this.reducer;
6417     if (transformer == null || reducer == null)
6418 dl 1.61 return abortOnNullFunction();
6419     try {
6420     final long id = this.basis;
6421     for (int c, b = batch(); b > 1 && baseIndex != baseLimit;) {
6422     do {} while (!casPending(c = pending, c+1));
6423     (rights = new MapReduceMappingsToLongTask<K,V>
6424     (this, b >>>= 1, rights, transformer, id, reducer)).fork();
6425     }
6426     long r = id;
6427     Object v;
6428     while ((v = advance()) != null)
6429     r = reducer.apply(r, transformer.apply((K)nextKey, (V)v));
6430     result = r;
6431     for (MapReduceMappingsToLongTask<K,V> t = this, s;;) {
6432     int c; BulkTask<K,V,?> par;
6433     if ((c = t.pending) == 0) {
6434     for (s = t.rights; s != null; s = t.rights = s.nextRight) {
6435     t.result = reducer.apply(t.result, s.result);
6436     }
6437     if ((par = t.parent) == null ||
6438     !(par instanceof MapReduceMappingsToLongTask)) {
6439     t.quietlyComplete();
6440     break;
6441     }
6442     t = (MapReduceMappingsToLongTask<K,V>)par;
6443     }
6444     else if (t.casPending(c, c - 1))
6445     break;
6446 dl 1.52 }
6447 dl 1.61 } catch (Throwable ex) {
6448     return tryCompleteComputation(ex);
6449 dl 1.52 }
6450 dl 1.61 return false;
6451 dl 1.52 }
6452     public final Long getRawResult() { return result; }
6453     }
6454    
6455 dl 1.61 @SuppressWarnings("serial") static final class MapReduceKeysToIntTask<K,V>
6456 dl 1.52 extends BulkTask<K,V,Integer> {
6457     final ObjectToInt<? super K> transformer;
6458     final IntByIntToInt reducer;
6459     final int basis;
6460     int result;
6461 dl 1.61 MapReduceKeysToIntTask<K,V> rights, nextRight;
6462 dl 1.52 MapReduceKeysToIntTask
6463     (ConcurrentHashMapV8<K,V> m,
6464     ObjectToInt<? super K> transformer,
6465     int basis,
6466     IntByIntToInt reducer) {
6467     super(m);
6468     this.transformer = transformer;
6469     this.basis = basis; this.reducer = reducer;
6470     }
6471     MapReduceKeysToIntTask
6472 dl 1.61 (BulkTask<K,V,?> p, int b,
6473     MapReduceKeysToIntTask<K,V> nextRight,
6474 dl 1.52 ObjectToInt<? super K> transformer,
6475     int basis,
6476     IntByIntToInt reducer) {
6477 dl 1.61 super(p, b); this.nextRight = nextRight;
6478 dl 1.52 this.transformer = transformer;
6479     this.basis = basis; this.reducer = reducer;
6480     }
6481 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
6482 dl 1.52 final ObjectToInt<? super K> transformer =
6483     this.transformer;
6484     final IntByIntToInt reducer = this.reducer;
6485     if (transformer == null || reducer == null)
6486 dl 1.61 return abortOnNullFunction();
6487     try {
6488     final int id = this.basis;
6489     for (int c, b = batch(); b > 1 && baseIndex != baseLimit;) {
6490     do {} while (!casPending(c = pending, c+1));
6491     (rights = new MapReduceKeysToIntTask<K,V>
6492     (this, b >>>= 1, rights, transformer, id, reducer)).fork();
6493     }
6494     int r = id;
6495     while (advance() != null)
6496     r = reducer.apply(r, transformer.apply((K)nextKey));
6497     result = r;
6498     for (MapReduceKeysToIntTask<K,V> t = this, s;;) {
6499     int c; BulkTask<K,V,?> par;
6500     if ((c = t.pending) == 0) {
6501     for (s = t.rights; s != null; s = t.rights = s.nextRight) {
6502     t.result = reducer.apply(t.result, s.result);
6503     }
6504     if ((par = t.parent) == null ||
6505     !(par instanceof MapReduceKeysToIntTask)) {
6506     t.quietlyComplete();
6507     break;
6508     }
6509     t = (MapReduceKeysToIntTask<K,V>)par;
6510     }
6511     else if (t.casPending(c, c - 1))
6512     break;
6513 dl 1.52 }
6514 dl 1.61 } catch (Throwable ex) {
6515     return tryCompleteComputation(ex);
6516 dl 1.52 }
6517 dl 1.61 return false;
6518 dl 1.52 }
6519     public final Integer getRawResult() { return result; }
6520     }
6521    
6522 dl 1.61 @SuppressWarnings("serial") static final class MapReduceValuesToIntTask<K,V>
6523 dl 1.52 extends BulkTask<K,V,Integer> {
6524     final ObjectToInt<? super V> transformer;
6525     final IntByIntToInt reducer;
6526     final int basis;
6527     int result;
6528 dl 1.61 MapReduceValuesToIntTask<K,V> rights, nextRight;
6529 dl 1.52 MapReduceValuesToIntTask
6530     (ConcurrentHashMapV8<K,V> m,
6531     ObjectToInt<? super V> transformer,
6532     int basis,
6533     IntByIntToInt reducer) {
6534     super(m);
6535     this.transformer = transformer;
6536     this.basis = basis; this.reducer = reducer;
6537     }
6538     MapReduceValuesToIntTask
6539 dl 1.61 (BulkTask<K,V,?> p, int b,
6540     MapReduceValuesToIntTask<K,V> nextRight,
6541 dl 1.52 ObjectToInt<? super V> transformer,
6542     int basis,
6543     IntByIntToInt reducer) {
6544 dl 1.61 super(p, b); this.nextRight = nextRight;
6545 dl 1.52 this.transformer = transformer;
6546     this.basis = basis; this.reducer = reducer;
6547     }
6548 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
6549 dl 1.52 final ObjectToInt<? super V> transformer =
6550     this.transformer;
6551     final IntByIntToInt reducer = this.reducer;
6552     if (transformer == null || reducer == null)
6553 dl 1.61 return abortOnNullFunction();
6554     try {
6555     final int id = this.basis;
6556     for (int c, b = batch(); b > 1 && baseIndex != baseLimit;) {
6557     do {} while (!casPending(c = pending, c+1));
6558     (rights = new MapReduceValuesToIntTask<K,V>
6559     (this, b >>>= 1, rights, transformer, id, reducer)).fork();
6560     }
6561     int r = id;
6562     Object v;
6563     while ((v = advance()) != null)
6564     r = reducer.apply(r, transformer.apply((V)v));
6565     result = r;
6566     for (MapReduceValuesToIntTask<K,V> t = this, s;;) {
6567     int c; BulkTask<K,V,?> par;
6568     if ((c = t.pending) == 0) {
6569     for (s = t.rights; s != null; s = t.rights = s.nextRight) {
6570     t.result = reducer.apply(t.result, s.result);
6571     }
6572     if ((par = t.parent) == null ||
6573     !(par instanceof MapReduceValuesToIntTask)) {
6574     t.quietlyComplete();
6575     break;
6576     }
6577     t = (MapReduceValuesToIntTask<K,V>)par;
6578     }
6579     else if (t.casPending(c, c - 1))
6580     break;
6581 dl 1.52 }
6582 dl 1.61 } catch (Throwable ex) {
6583     return tryCompleteComputation(ex);
6584 dl 1.52 }
6585 dl 1.61 return false;
6586 dl 1.52 }
6587     public final Integer getRawResult() { return result; }
6588     }
6589    
6590 dl 1.61 @SuppressWarnings("serial") static final class MapReduceEntriesToIntTask<K,V>
6591 dl 1.52 extends BulkTask<K,V,Integer> {
6592     final ObjectToInt<Map.Entry<K,V>> transformer;
6593     final IntByIntToInt reducer;
6594     final int basis;
6595     int result;
6596 dl 1.61 MapReduceEntriesToIntTask<K,V> rights, nextRight;
6597 dl 1.52 MapReduceEntriesToIntTask
6598     (ConcurrentHashMapV8<K,V> m,
6599     ObjectToInt<Map.Entry<K,V>> transformer,
6600     int basis,
6601     IntByIntToInt reducer) {
6602     super(m);
6603     this.transformer = transformer;
6604     this.basis = basis; this.reducer = reducer;
6605     }
6606     MapReduceEntriesToIntTask
6607 dl 1.61 (BulkTask<K,V,?> p, int b,
6608     MapReduceEntriesToIntTask<K,V> nextRight,
6609 dl 1.52 ObjectToInt<Map.Entry<K,V>> transformer,
6610     int basis,
6611     IntByIntToInt reducer) {
6612 dl 1.61 super(p, b); this.nextRight = nextRight;
6613 dl 1.52 this.transformer = transformer;
6614     this.basis = basis; this.reducer = reducer;
6615     }
6616 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
6617 dl 1.52 final ObjectToInt<Map.Entry<K,V>> transformer =
6618     this.transformer;
6619     final IntByIntToInt reducer = this.reducer;
6620     if (transformer == null || reducer == null)
6621 dl 1.61 return abortOnNullFunction();
6622     try {
6623     final int id = this.basis;
6624     for (int c, b = batch(); b > 1 && baseIndex != baseLimit;) {
6625     do {} while (!casPending(c = pending, c+1));
6626     (rights = new MapReduceEntriesToIntTask<K,V>
6627     (this, b >>>= 1, rights, transformer, id, reducer)).fork();
6628     }
6629     int r = id;
6630     Object v;
6631     while ((v = advance()) != null)
6632     r = reducer.apply(r, transformer.apply(entryFor((K)nextKey, (V)v)));
6633     result = r;
6634     for (MapReduceEntriesToIntTask<K,V> t = this, s;;) {
6635     int c; BulkTask<K,V,?> par;
6636     if ((c = t.pending) == 0) {
6637     for (s = t.rights; s != null; s = t.rights = s.nextRight) {
6638     t.result = reducer.apply(t.result, s.result);
6639     }
6640     if ((par = t.parent) == null ||
6641     !(par instanceof MapReduceEntriesToIntTask)) {
6642     t.quietlyComplete();
6643     break;
6644     }
6645     t = (MapReduceEntriesToIntTask<K,V>)par;
6646     }
6647     else if (t.casPending(c, c - 1))
6648     break;
6649 dl 1.52 }
6650 dl 1.61 } catch (Throwable ex) {
6651     return tryCompleteComputation(ex);
6652 dl 1.52 }
6653 dl 1.61 return false;
6654 dl 1.52 }
6655     public final Integer getRawResult() { return result; }
6656     }
6657    
6658 dl 1.61 @SuppressWarnings("serial") static final class MapReduceMappingsToIntTask<K,V>
6659 dl 1.52 extends BulkTask<K,V,Integer> {
6660     final ObjectByObjectToInt<? super K, ? super V> transformer;
6661     final IntByIntToInt reducer;
6662     final int basis;
6663     int result;
6664 dl 1.61 MapReduceMappingsToIntTask<K,V> rights, nextRight;
6665 dl 1.52 MapReduceMappingsToIntTask
6666     (ConcurrentHashMapV8<K,V> m,
6667     ObjectByObjectToInt<? super K, ? super V> transformer,
6668     int basis,
6669     IntByIntToInt reducer) {
6670     super(m);
6671     this.transformer = transformer;
6672     this.basis = basis; this.reducer = reducer;
6673     }
6674     MapReduceMappingsToIntTask
6675 dl 1.61 (BulkTask<K,V,?> p, int b,
6676     MapReduceMappingsToIntTask<K,V> nextRight,
6677 dl 1.52 ObjectByObjectToInt<? super K, ? super V> transformer,
6678     int basis,
6679     IntByIntToInt reducer) {
6680 dl 1.61 super(p, b); this.nextRight = nextRight;
6681 dl 1.52 this.transformer = transformer;
6682     this.basis = basis; this.reducer = reducer;
6683     }
6684 dl 1.61 @SuppressWarnings("unchecked") public final boolean exec() {
6685 dl 1.52 final ObjectByObjectToInt<? super K, ? super V> transformer =
6686     this.transformer;
6687     final IntByIntToInt reducer = this.reducer;
6688     if (transformer == null || reducer == null)
6689 dl 1.61 return abortOnNullFunction();
6690     try {
6691     final int id = this.basis;
6692     for (int c, b = batch(); b > 1 && baseIndex != baseLimit;) {
6693     do {} while (!casPending(c = pending, c+1));
6694     (rights = new MapReduceMappingsToIntTask<K,V>
6695     (this, b >>>= 1, rights, transformer, id, reducer)).fork();
6696     }
6697     int r = id;
6698     Object v;
6699     while ((v = advance()) != null)
6700     r = reducer.apply(r, transformer.apply((K)nextKey, (V)v));
6701     result = r;
6702     for (MapReduceMappingsToIntTask<K,V> t = this, s;;) {
6703     int c; BulkTask<K,V,?> par;
6704     if ((c = t.pending) == 0) {
6705     for (s = t.rights; s != null; s = t.rights = s.nextRight) {
6706     t.result = reducer.apply(t.result, s.result);
6707     }
6708     if ((par = t.parent) == null ||
6709     !(par instanceof MapReduceMappingsToIntTask)) {
6710     t.quietlyComplete();
6711     break;
6712     }
6713     t = (MapReduceMappingsToIntTask<K,V>)par;
6714     }
6715     else if (t.casPending(c, c - 1))
6716     break;
6717 dl 1.52 }
6718 dl 1.61 } catch (Throwable ex) {
6719     return tryCompleteComputation(ex);
6720 dl 1.52 }
6721 dl 1.61 return false;
6722 dl 1.52 }
6723     public final Integer getRawResult() { return result; }
6724     }
6725    
6726    
6727     // Unsafe mechanics
6728     private static final sun.misc.Unsafe UNSAFE;
6729     private static final long counterOffset;
6730     private static final long sizeCtlOffset;
6731     private static final long ABASE;
6732     private static final int ASHIFT;
6733    
6734     static {
6735     int ss;
6736     try {
6737     UNSAFE = getUnsafe();
6738     Class<?> k = ConcurrentHashMapV8.class;
6739     counterOffset = UNSAFE.objectFieldOffset
6740     (k.getDeclaredField("counter"));
6741     sizeCtlOffset = UNSAFE.objectFieldOffset
6742     (k.getDeclaredField("sizeCtl"));
6743     Class<?> sc = Node[].class;
6744     ABASE = UNSAFE.arrayBaseOffset(sc);
6745     ss = UNSAFE.arrayIndexScale(sc);
6746     } catch (Exception e) {
6747     throw new Error(e);
6748     }
6749     if ((ss & (ss-1)) != 0)
6750     throw new Error("data type scale not a power of two");
6751     ASHIFT = 31 - Integer.numberOfLeadingZeros(ss);
6752     }
6753    
6754     /**
6755     * Returns a sun.misc.Unsafe. Suitable for use in a 3rd party package.
6756     * Replace with a simple call to Unsafe.getUnsafe when integrating
6757     * into a jdk.
6758     *
6759     * @return a sun.misc.Unsafe
6760     */
6761     private static sun.misc.Unsafe getUnsafe() {
6762     try {
6763     return sun.misc.Unsafe.getUnsafe();
6764     } catch (SecurityException se) {
6765     try {
6766     return java.security.AccessController.doPrivileged
6767     (new java.security
6768     .PrivilegedExceptionAction<sun.misc.Unsafe>() {
6769     public sun.misc.Unsafe run() throws Exception {
6770     java.lang.reflect.Field f = sun.misc
6771     .Unsafe.class.getDeclaredField("theUnsafe");
6772     f.setAccessible(true);
6773     return (sun.misc.Unsafe) f.get(null);
6774     }});
6775     } catch (java.security.PrivilegedActionException e) {
6776     throw new RuntimeException("Could not initialize intrinsics",
6777     e.getCause());
6778     }
6779     }
6780     }
6781 dl 1.1 }