ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jsr166e/ConcurrentHashMapV8.java
Revision: 1.77
Committed: Sun Nov 18 03:07:22 2012 UTC (11 years, 5 months ago) by jsr166
Branch: MAIN
Changes since 1.76: +1 -1 lines
Log Message:
properly close <em> javadoc tags

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