--- jsr166/src/jsr166e/ConcurrentHashMapV8.java 2012/10/28 22:35:45 1.70 +++ jsr166/src/jsr166e/ConcurrentHashMapV8.java 2012/11/18 18:03:10 1.78 @@ -5,9 +5,7 @@ */ package jsr166e; -import jsr166e.LongAdder; -import jsr166e.ForkJoinPool; -import jsr166e.ForkJoinTask; + import java.util.Comparator; import java.util.Arrays; import java.util.Map; @@ -42,7 +40,7 @@ import java.io.Serializable; * interoperable with {@code Hashtable} in programs that rely on its * thread safety but not on its synchronization details. * - *

Retrieval operations (including {@code get}) generally do not + *

Retrieval operations (including {@code get}) generally do not * block, so may overlap with update operations (including {@code put} * and {@code remove}). Retrievals reflect the results of the most * recently completed update operations holding upon their @@ -63,7 +61,7 @@ import java.io.Serializable; * that may be adequate for monitoring or estimation purposes, but not * for program control. * - *

The table is dynamically expanded when there are too many + *

The table is dynamically expanded when there are too many * collisions (i.e., keys that have distinct hash codes but fall into * the same slot modulo the table size), with the expected average * effect of maintaining roughly two bins per mapping (corresponding @@ -84,13 +82,13 @@ import java.io.Serializable; * {@code hashCode()} is a sure way to slow down performance of any * hash table. * - *

A {@link Set} projection of a ConcurrentHashMap may be created + *

A {@link Set} projection of a ConcurrentHashMapV8 may be created * (using {@link #newKeySet()} or {@link #newKeySet(int)}), or viewed * (using {@link #keySet(Object)} when only keys are of interest, and the * mapped values are (perhaps transiently) not used or all take the * same mapping value. * - *

A ConcurrentHashMapV8 can be used as scalable frequency map (a + *

A ConcurrentHashMapV8 can be used as scalable frequency map (a * form of histogram or multiset) by using {@link LongAdder} values * and initializing via {@link #computeIfAbsent}. For example, to add * a count to a {@code ConcurrentHashMapV8 freqs}, you @@ -101,18 +99,20 @@ import java.io.Serializable; * optional methods of the {@link Map} and {@link Iterator} * interfaces. * - *

Like {@link Hashtable} but unlike {@link HashMap}, this class + *

Like {@link Hashtable} but unlike {@link HashMap}, this class * does not allow {@code null} to be used as a key or value. * *

ConcurrentHashMapV8s support parallel operations using the {@link - * ForkJoinPool#commonPool}. (Task that may be used in other contexts + * ForkJoinPool#commonPool}. (Tasks that may be used in other contexts * are available in class {@link ForkJoinTasks}). These operations are * designed to be safely, and often sensibly, applied even with maps * that are being concurrently updated by other threads; for example, * when computing a snapshot summary of the values in a shared * registry. There are three kinds of operation, each with four * forms, accepting functions with Keys, Values, Entries, and (Key, - * Value) arguments and/or return values. Because the elements of a + * Value) arguments and/or return values. (The first three forms are + * also available via the {@link #keySet()}, {@link #values()} and + * {@link #entrySet()} views). Because the elements of a * ConcurrentHashMapV8 are not ordered in any particular way, and may be * processed in different orders in different parallel executions, the * correctness of supplied functions should not depend on any @@ -184,7 +184,7 @@ import java.io.Serializable; * arguments can be supplied using {@code new * AbstractMap.SimpleEntry(k,v)}. * - *

Bulk operations may complete abruptly, throwing an + *

Bulk operations may complete abruptly, throwing an * exception encountered in the application of a supplied * function. Bear in mind when handling such exceptions that other * concurrently executing functions could also have thrown @@ -195,15 +195,15 @@ import java.io.Serializable; * processing are common but not guaranteed. Operations involving * brief functions on small maps may execute more slowly than * sequential loops if the underlying work to parallelize the - * computation is more expensive than the computation - * itself. Similarly, parallelization may not lead to much actual - * parallelism if all processors are busy performing unrelated tasks. + * computation is more expensive than the computation itself. + * Similarly, parallelization may not lead to much actual parallelism + * if all processors are busy performing unrelated tasks. * - *

All arguments to all task methods must be non-null. + *

All arguments to all task methods must be non-null. * *

jsr166e note: During transition, this class * uses nested functional interfaces with different names but the - * same forms as those expected for JDK8. + * same forms as those expected for JDK8. * *

This class is a member of the * @@ -225,7 +225,7 @@ public class ConcurrentHashMapV8 * portion of the elements, and so may be amenable to parallel * execution. * - *

This interface exports a subset of expected JDK8 + *

This interface exports a subset of expected JDK8 * functionality. * *

Sample usage: Here is one (of the several) ways to compute @@ -287,76 +287,6 @@ public class ConcurrentHashMapV8 Spliterator split(); } - /** - * A view of a ConcurrentHashMapV8 as a {@link Set} of keys, in - * which additions may optionally be enabled by mapping to a - * common value. This class cannot be directly instantiated. See - * {@link #keySet}, {@link #keySet(Object)}, {@link #newKeySet()}, - * {@link #newKeySet(int)}. - * - *

The view's {@code iterator} is a "weakly consistent" iterator - * that will never throw {@link ConcurrentModificationException}, - * and guarantees to traverse elements as they existed upon - * construction of the iterator, and may (but is not guaranteed to) - * reflect any modifications subsequent to construction. - */ - public static class KeySetView extends CHMView implements Set, java.io.Serializable { - private static final long serialVersionUID = 7249069246763182397L; - private final V value; - KeySetView(ConcurrentHashMapV8 map, V value) { // non-public - super(map); - this.value = value; - } - - /** - * Returns the map backing this view. - * - * @return the map backing this view - */ - public ConcurrentHashMapV8 getMap() { return map; } - - /** - * Returns the default mapped value for additions, - * or {@code null} if additions are not supported. - * - * @return the default mapped value for additions, or {@code null} - * if not supported. - */ - public V getMappedValue() { return value; } - - // implement Set API - - public boolean contains(Object o) { return map.containsKey(o); } - public boolean remove(Object o) { return map.remove(o) != null; } - public Iterator iterator() { return new KeyIterator(map); } - public boolean add(K e) { - V v; - if ((v = value) == null) - throw new UnsupportedOperationException(); - if (e == null) - throw new NullPointerException(); - return map.internalPutIfAbsent(e, v) == null; - } - public boolean addAll(Collection c) { - boolean added = false; - V v; - if ((v = value) == null) - throw new UnsupportedOperationException(); - for (K e : c) { - if (e == null) - throw new NullPointerException(); - if (map.internalPutIfAbsent(e, v) == null) - added = true; - } - return added; - } - public boolean equals(Object o) { - Set c; - return ((o instanceof Set) && - ((c = (Set)o) == this || - (containsAll(c) && c.containsAll(this)))); - } - } /* * Overview: @@ -641,8 +571,8 @@ public class ConcurrentHashMapV8 // views private transient KeySetView keySet; - private transient Values values; - private transient EntrySet entrySet; + private transient ValuesView values; + private transient EntrySetView entrySet; /** For serialization compatibility. Null unless serialized; see below */ private Segment[] segments; @@ -2783,7 +2713,7 @@ public class ConcurrentHashMapV8 * Maps the specified key to the specified value in this table. * Neither the key nor the value can be null. * - *

The value can be retrieved by calling the {@code get} method + *

The value can be retrieved by calling the {@code get} method * with a key that is equal to the original key. * * @param key key with which the specified value is to be associated @@ -3080,22 +3010,11 @@ public class ConcurrentHashMapV8 /** * Returns a {@link Collection} view of the values contained in this map. * The collection is backed by the map, so changes to the map are - * reflected in the collection, and vice-versa. The collection - * supports element removal, which removes the corresponding - * mapping from this map, via the {@code Iterator.remove}, - * {@code Collection.remove}, {@code removeAll}, - * {@code retainAll}, and {@code clear} operations. It does not - * support the {@code add} or {@code addAll} operations. - * - *

The view's {@code iterator} is a "weakly consistent" iterator - * that will never throw {@link ConcurrentModificationException}, - * and guarantees to traverse elements as they existed upon - * construction of the iterator, and may (but is not guaranteed to) - * reflect any modifications subsequent to construction. + * reflected in the collection, and vice-versa. */ - public Collection values() { - Values vs = values; - return (vs != null) ? vs : (values = new Values(this)); + public ValuesView values() { + ValuesView vs = values; + return (vs != null) ? vs : (values = new ValuesView(this)); } /** @@ -3115,8 +3034,8 @@ public class ConcurrentHashMapV8 * reflect any modifications subsequent to construction. */ public Set> entrySet() { - EntrySet es = entrySet; - return (es != null) ? es : (entrySet = new EntrySet(this)); + EntrySetView es = entrySet; + return (es != null) ? es : (entrySet = new EntrySetView(this)); } /** @@ -3359,199 +3278,6 @@ public class ConcurrentHashMapV8 } } - /* ----------------Views -------------- */ - - /** - * Base class for views. - */ - static abstract class CHMView { - final ConcurrentHashMapV8 map; - CHMView(ConcurrentHashMapV8 map) { this.map = map; } - public final int size() { return map.size(); } - public final boolean isEmpty() { return map.isEmpty(); } - public final void clear() { map.clear(); } - - // implementations below rely on concrete classes supplying these - abstract public Iterator iterator(); - abstract public boolean contains(Object o); - abstract public boolean remove(Object o); - - private static final String oomeMsg = "Required array size too large"; - - public final Object[] toArray() { - long sz = map.mappingCount(); - if (sz > (long)(MAX_ARRAY_SIZE)) - throw new OutOfMemoryError(oomeMsg); - int n = (int)sz; - Object[] r = new Object[n]; - int i = 0; - Iterator it = iterator(); - while (it.hasNext()) { - if (i == n) { - if (n >= MAX_ARRAY_SIZE) - throw new OutOfMemoryError(oomeMsg); - if (n >= MAX_ARRAY_SIZE - (MAX_ARRAY_SIZE >>> 1) - 1) - n = MAX_ARRAY_SIZE; - else - n += (n >>> 1) + 1; - r = Arrays.copyOf(r, n); - } - r[i++] = it.next(); - } - return (i == n) ? r : Arrays.copyOf(r, i); - } - - @SuppressWarnings("unchecked") public final T[] toArray(T[] a) { - long sz = map.mappingCount(); - if (sz > (long)(MAX_ARRAY_SIZE)) - throw new OutOfMemoryError(oomeMsg); - int m = (int)sz; - T[] r = (a.length >= m) ? a : - (T[])java.lang.reflect.Array - .newInstance(a.getClass().getComponentType(), m); - int n = r.length; - int i = 0; - Iterator it = iterator(); - while (it.hasNext()) { - if (i == n) { - if (n >= MAX_ARRAY_SIZE) - throw new OutOfMemoryError(oomeMsg); - if (n >= MAX_ARRAY_SIZE - (MAX_ARRAY_SIZE >>> 1) - 1) - n = MAX_ARRAY_SIZE; - else - n += (n >>> 1) + 1; - r = Arrays.copyOf(r, n); - } - r[i++] = (T)it.next(); - } - if (a == r && i < n) { - r[i] = null; // null-terminate - return r; - } - return (i == n) ? r : Arrays.copyOf(r, i); - } - - public final int hashCode() { - int h = 0; - for (Iterator it = iterator(); it.hasNext();) - h += it.next().hashCode(); - return h; - } - - public final String toString() { - StringBuilder sb = new StringBuilder(); - sb.append('['); - Iterator it = iterator(); - if (it.hasNext()) { - for (;;) { - Object e = it.next(); - sb.append(e == this ? "(this Collection)" : e); - if (!it.hasNext()) - break; - sb.append(',').append(' '); - } - } - return sb.append(']').toString(); - } - - public final boolean containsAll(Collection c) { - if (c != this) { - for (Iterator it = c.iterator(); it.hasNext();) { - Object e = it.next(); - if (e == null || !contains(e)) - return false; - } - } - return true; - } - - public final boolean removeAll(Collection c) { - boolean modified = false; - for (Iterator it = iterator(); it.hasNext();) { - if (c.contains(it.next())) { - it.remove(); - modified = true; - } - } - return modified; - } - - public final boolean retainAll(Collection c) { - boolean modified = false; - for (Iterator it = iterator(); it.hasNext();) { - if (!c.contains(it.next())) { - it.remove(); - modified = true; - } - } - return modified; - } - - } - - static final class Values extends CHMView - implements Collection { - Values(ConcurrentHashMapV8 map) { super(map); } - public final boolean contains(Object o) { return map.containsValue(o); } - public final boolean remove(Object o) { - if (o != null) { - Iterator it = new ValueIterator(map); - while (it.hasNext()) { - if (o.equals(it.next())) { - it.remove(); - return true; - } - } - } - return false; - } - public final Iterator iterator() { - return new ValueIterator(map); - } - public final boolean add(V e) { - throw new UnsupportedOperationException(); - } - public final boolean addAll(Collection c) { - throw new UnsupportedOperationException(); - } - - } - - static final class EntrySet extends CHMView - implements Set> { - EntrySet(ConcurrentHashMapV8 map) { super(map); } - public final boolean contains(Object o) { - Object k, v, r; Map.Entry e; - return ((o instanceof Map.Entry) && - (k = (e = (Map.Entry)o).getKey()) != null && - (r = map.get(k)) != null && - (v = e.getValue()) != null && - (v == r || v.equals(r))); - } - public final boolean remove(Object o) { - Object k, v; Map.Entry e; - return ((o instanceof Map.Entry) && - (k = (e = (Map.Entry)o).getKey()) != null && - (v = e.getValue()) != null && - map.remove(k, v)); - } - public final Iterator> iterator() { - return new EntryIterator(map); - } - public final boolean add(Entry e) { - throw new UnsupportedOperationException(); - } - public final boolean addAll(Collection> c) { - throw new UnsupportedOperationException(); - } - public boolean equals(Object o) { - Set c; - return ((o instanceof Set) && - ((c = (Set)o) == this || - (containsAll(c) && c.containsAll(this)))); - } - } - /* ---------------- Serialization Support -------------- */ /** @@ -3860,6 +3586,23 @@ public class ConcurrentHashMapV8 } /** + * Returns a non-null result from applying the given search + * function on each key, or null if none. Upon success, + * further element processing is suppressed and the results of + * any other parallel invocations of the search function are + * ignored. + * + * @param searchFunction a function returning a non-null + * result on success, else null + * @return a non-null result from applying the given search + * function on each key, or null if none + */ + public U searchKeys(Fun searchFunction) { + return ForkJoinTasks.searchKeys + (this, searchFunction).invoke(); + } + + /** * Returns the result of accumulating all keys using the given * reducer to combine values, or null if none. * @@ -4205,6 +3948,697 @@ public class ConcurrentHashMapV8 (this, transformer, basis, reducer).invoke(); } + /* ----------------Views -------------- */ + + /** + * Base class for views. + */ + static abstract class CHMView { + final ConcurrentHashMapV8 map; + CHMView(ConcurrentHashMapV8 map) { this.map = map; } + + /** + * Returns the map backing this view. + * + * @return the map backing this view + */ + public ConcurrentHashMapV8 getMap() { return map; } + + public final int size() { return map.size(); } + public final boolean isEmpty() { return map.isEmpty(); } + public final void clear() { map.clear(); } + + // implementations below rely on concrete classes supplying these + abstract public Iterator iterator(); + abstract public boolean contains(Object o); + abstract public boolean remove(Object o); + + private static final String oomeMsg = "Required array size too large"; + + public final Object[] toArray() { + long sz = map.mappingCount(); + if (sz > (long)(MAX_ARRAY_SIZE)) + throw new OutOfMemoryError(oomeMsg); + int n = (int)sz; + Object[] r = new Object[n]; + int i = 0; + Iterator it = iterator(); + while (it.hasNext()) { + if (i == n) { + if (n >= MAX_ARRAY_SIZE) + throw new OutOfMemoryError(oomeMsg); + if (n >= MAX_ARRAY_SIZE - (MAX_ARRAY_SIZE >>> 1) - 1) + n = MAX_ARRAY_SIZE; + else + n += (n >>> 1) + 1; + r = Arrays.copyOf(r, n); + } + r[i++] = it.next(); + } + return (i == n) ? r : Arrays.copyOf(r, i); + } + + @SuppressWarnings("unchecked") public final T[] toArray(T[] a) { + long sz = map.mappingCount(); + if (sz > (long)(MAX_ARRAY_SIZE)) + throw new OutOfMemoryError(oomeMsg); + int m = (int)sz; + T[] r = (a.length >= m) ? a : + (T[])java.lang.reflect.Array + .newInstance(a.getClass().getComponentType(), m); + int n = r.length; + int i = 0; + Iterator it = iterator(); + while (it.hasNext()) { + if (i == n) { + if (n >= MAX_ARRAY_SIZE) + throw new OutOfMemoryError(oomeMsg); + if (n >= MAX_ARRAY_SIZE - (MAX_ARRAY_SIZE >>> 1) - 1) + n = MAX_ARRAY_SIZE; + else + n += (n >>> 1) + 1; + r = Arrays.copyOf(r, n); + } + r[i++] = (T)it.next(); + } + if (a == r && i < n) { + r[i] = null; // null-terminate + return r; + } + return (i == n) ? r : Arrays.copyOf(r, i); + } + + public final int hashCode() { + int h = 0; + for (Iterator it = iterator(); it.hasNext();) + h += it.next().hashCode(); + return h; + } + + public final String toString() { + StringBuilder sb = new StringBuilder(); + sb.append('['); + Iterator it = iterator(); + if (it.hasNext()) { + for (;;) { + Object e = it.next(); + sb.append(e == this ? "(this Collection)" : e); + if (!it.hasNext()) + break; + sb.append(',').append(' '); + } + } + return sb.append(']').toString(); + } + + public final boolean containsAll(Collection c) { + if (c != this) { + for (Iterator it = c.iterator(); it.hasNext();) { + Object e = it.next(); + if (e == null || !contains(e)) + return false; + } + } + return true; + } + + public final boolean removeAll(Collection c) { + boolean modified = false; + for (Iterator it = iterator(); it.hasNext();) { + if (c.contains(it.next())) { + it.remove(); + modified = true; + } + } + return modified; + } + + public final boolean retainAll(Collection c) { + boolean modified = false; + for (Iterator it = iterator(); it.hasNext();) { + if (!c.contains(it.next())) { + it.remove(); + modified = true; + } + } + return modified; + } + + } + + /** + * A view of a ConcurrentHashMapV8 as a {@link Set} of keys, in + * which additions may optionally be enabled by mapping to a + * common value. This class cannot be directly instantiated. See + * {@link #keySet}, {@link #keySet(Object)}, {@link #newKeySet()}, + * {@link #newKeySet(int)}. + */ + public static class KeySetView extends CHMView implements Set, java.io.Serializable { + private static final long serialVersionUID = 7249069246763182397L; + private final V value; + KeySetView(ConcurrentHashMapV8 map, V value) { // non-public + super(map); + this.value = value; + } + + /** + * Returns the default mapped value for additions, + * or {@code null} if additions are not supported. + * + * @return the default mapped value for additions, or {@code null} + * if not supported. + */ + public V getMappedValue() { return value; } + + // implement Set API + + public boolean contains(Object o) { return map.containsKey(o); } + public boolean remove(Object o) { return map.remove(o) != null; } + + /** + * Returns a "weakly consistent" iterator that will never + * throw {@link ConcurrentModificationException}, and + * guarantees to traverse elements as they existed upon + * construction of the iterator, and may (but is not + * guaranteed to) reflect any modifications subsequent to + * construction. + * + * @return an iterator over the keys of this map + */ + public Iterator iterator() { return new KeyIterator(map); } + public boolean add(K e) { + V v; + if ((v = value) == null) + throw new UnsupportedOperationException(); + if (e == null) + throw new NullPointerException(); + return map.internalPutIfAbsent(e, v) == null; + } + public boolean addAll(Collection c) { + boolean added = false; + V v; + if ((v = value) == null) + throw new UnsupportedOperationException(); + for (K e : c) { + if (e == null) + throw new NullPointerException(); + if (map.internalPutIfAbsent(e, v) == null) + added = true; + } + return added; + } + public boolean equals(Object o) { + Set c; + return ((o instanceof Set) && + ((c = (Set)o) == this || + (containsAll(c) && c.containsAll(this)))); + } + + /** + * Performs the given action for each key. + * + * @param action the action + */ + public void forEach(Action action) { + ForkJoinTasks.forEachKey + (map, action).invoke(); + } + + /** + * Performs the given action for each non-null transformation + * of each key. + * + * @param transformer a function returning the transformation + * for an element, or null of there is no transformation (in + * which case the action is not applied). + * @param action the action + */ + public void forEach(Fun transformer, + Action action) { + ForkJoinTasks.forEachKey + (map, transformer, action).invoke(); + } + + /** + * Returns a non-null result from applying the given search + * function on each key, or null if none. Upon success, + * further element processing is suppressed and the results of + * any other parallel invocations of the search function are + * ignored. + * + * @param searchFunction a function returning a non-null + * result on success, else null + * @return a non-null result from applying the given search + * function on each key, or null if none + */ + public U search(Fun searchFunction) { + return ForkJoinTasks.searchKeys + (map, searchFunction).invoke(); + } + + /** + * Returns the result of accumulating all keys using the given + * reducer to combine values, or null if none. + * + * @param reducer a commutative associative combining function + * @return the result of accumulating all keys using the given + * reducer to combine values, or null if none + */ + public K reduce(BiFun reducer) { + return ForkJoinTasks.reduceKeys + (map, reducer).invoke(); + } + + /** + * Returns the result of accumulating the given transformation + * of all keys using the given reducer to combine values, and + * the given basis as an identity value. + * + * @param transformer a function returning the transformation + * for an element + * @param basis the identity (initial default value) for the reduction + * @param reducer a commutative associative combining function + * @return the result of accumulating the given transformation + * of all keys + */ + public double reduceToDouble(ObjectToDouble transformer, + double basis, + DoubleByDoubleToDouble reducer) { + return ForkJoinTasks.reduceKeysToDouble + (map, transformer, basis, reducer).invoke(); + } + + + /** + * Returns the result of accumulating the given transformation + * of all keys using the given reducer to combine values, and + * the given basis as an identity value. + * + * @param transformer a function returning the transformation + * for an element + * @param basis the identity (initial default value) for the reduction + * @param reducer a commutative associative combining function + * @return the result of accumulating the given transformation + * of all keys + */ + public long reduceToLong(ObjectToLong transformer, + long basis, + LongByLongToLong reducer) { + return ForkJoinTasks.reduceKeysToLong + (map, transformer, basis, reducer).invoke(); + } + + /** + * Returns the result of accumulating the given transformation + * of all keys using the given reducer to combine values, and + * the given basis as an identity value. + * + * @param transformer a function returning the transformation + * for an element + * @param basis the identity (initial default value) for the reduction + * @param reducer a commutative associative combining function + * @return the result of accumulating the given transformation + * of all keys + */ + public int reduceToInt(ObjectToInt transformer, + int basis, + IntByIntToInt reducer) { + return ForkJoinTasks.reduceKeysToInt + (map, transformer, basis, reducer).invoke(); + } + + } + + /** + * A view of a ConcurrentHashMapV8 as a {@link Collection} of + * values, in which additions are disabled. This class cannot be + * directly instantiated. See {@link #values}, + * + *

The view's {@code iterator} is a "weakly consistent" iterator + * that will never throw {@link ConcurrentModificationException}, + * and guarantees to traverse elements as they existed upon + * construction of the iterator, and may (but is not guaranteed to) + * reflect any modifications subsequent to construction. + */ + public static final class ValuesView extends CHMView + implements Collection { + ValuesView(ConcurrentHashMapV8 map) { super(map); } + public final boolean contains(Object o) { return map.containsValue(o); } + public final boolean remove(Object o) { + if (o != null) { + Iterator it = new ValueIterator(map); + while (it.hasNext()) { + if (o.equals(it.next())) { + it.remove(); + return true; + } + } + } + return false; + } + + /** + * Returns a "weakly consistent" iterator that will never + * throw {@link ConcurrentModificationException}, and + * guarantees to traverse elements as they existed upon + * construction of the iterator, and may (but is not + * guaranteed to) reflect any modifications subsequent to + * construction. + * + * @return an iterator over the values of this map + */ + public final Iterator iterator() { + return new ValueIterator(map); + } + public final boolean add(V e) { + throw new UnsupportedOperationException(); + } + public final boolean addAll(Collection c) { + throw new UnsupportedOperationException(); + } + + /** + * Performs the given action for each value. + * + * @param action the action + */ + public void forEach(Action action) { + ForkJoinTasks.forEachValue + (map, action).invoke(); + } + + /** + * Performs the given action for each non-null transformation + * of each value. + * + * @param transformer a function returning the transformation + * for an element, or null of there is no transformation (in + * which case the action is not applied). + */ + public void forEach(Fun transformer, + Action action) { + ForkJoinTasks.forEachValue + (map, transformer, action).invoke(); + } + + /** + * Returns a non-null result from applying the given search + * function on each value, or null if none. Upon success, + * further element processing is suppressed and the results of + * any other parallel invocations of the search function are + * ignored. + * + * @param searchFunction a function returning a non-null + * result on success, else null + * @return a non-null result from applying the given search + * function on each value, or null if none + * + */ + public U search(Fun searchFunction) { + return ForkJoinTasks.searchValues + (map, searchFunction).invoke(); + } + + /** + * Returns the result of accumulating all values using the + * given reducer to combine values, or null if none. + * + * @param reducer a commutative associative combining function + * @return the result of accumulating all values + */ + public V reduce(BiFun reducer) { + return ForkJoinTasks.reduceValues + (map, reducer).invoke(); + } + + /** + * Returns the result of accumulating the given transformation + * of all values using the given reducer to combine values, or + * null if none. + * + * @param transformer a function returning the transformation + * for an element, or null of there is no transformation (in + * which case it is not combined). + * @param reducer a commutative associative combining function + * @return the result of accumulating the given transformation + * of all values + */ + public U reduce(Fun transformer, + BiFun reducer) { + return ForkJoinTasks.reduceValues + (map, transformer, reducer).invoke(); + } + + /** + * Returns the result of accumulating the given transformation + * of all values using the given reducer to combine values, + * and the given basis as an identity value. + * + * @param transformer a function returning the transformation + * for an element + * @param basis the identity (initial default value) for the reduction + * @param reducer a commutative associative combining function + * @return the result of accumulating the given transformation + * of all values + */ + public double reduceToDouble(ObjectToDouble transformer, + double basis, + DoubleByDoubleToDouble reducer) { + return ForkJoinTasks.reduceValuesToDouble + (map, transformer, basis, reducer).invoke(); + } + + /** + * Returns the result of accumulating the given transformation + * of all values using the given reducer to combine values, + * and the given basis as an identity value. + * + * @param transformer a function returning the transformation + * for an element + * @param basis the identity (initial default value) for the reduction + * @param reducer a commutative associative combining function + * @return the result of accumulating the given transformation + * of all values + */ + public long reduceToLong(ObjectToLong transformer, + long basis, + LongByLongToLong reducer) { + return ForkJoinTasks.reduceValuesToLong + (map, transformer, basis, reducer).invoke(); + } + + /** + * Returns the result of accumulating the given transformation + * of all values using the given reducer to combine values, + * and the given basis as an identity value. + * + * @param transformer a function returning the transformation + * for an element + * @param basis the identity (initial default value) for the reduction + * @param reducer a commutative associative combining function + * @return the result of accumulating the given transformation + * of all values + */ + public int reduceToInt(ObjectToInt transformer, + int basis, + IntByIntToInt reducer) { + return ForkJoinTasks.reduceValuesToInt + (map, transformer, basis, reducer).invoke(); + } + + } + + /** + * A view of a ConcurrentHashMapV8 as a {@link Set} of (key, value) + * entries. This class cannot be directly instantiated. See + * {@link #entrySet}. + */ + public static final class EntrySetView extends CHMView + implements Set> { + EntrySetView(ConcurrentHashMapV8 map) { super(map); } + public final boolean contains(Object o) { + Object k, v, r; Map.Entry e; + return ((o instanceof Map.Entry) && + (k = (e = (Map.Entry)o).getKey()) != null && + (r = map.get(k)) != null && + (v = e.getValue()) != null && + (v == r || v.equals(r))); + } + public final boolean remove(Object o) { + Object k, v; Map.Entry e; + return ((o instanceof Map.Entry) && + (k = (e = (Map.Entry)o).getKey()) != null && + (v = e.getValue()) != null && + map.remove(k, v)); + } + + /** + * Returns a "weakly consistent" iterator that will never + * throw {@link ConcurrentModificationException}, and + * guarantees to traverse elements as they existed upon + * construction of the iterator, and may (but is not + * guaranteed to) reflect any modifications subsequent to + * construction. + * + * @return an iterator over the entries of this map + */ + public final Iterator> iterator() { + return new EntryIterator(map); + } + + public final boolean add(Entry e) { + K key = e.getKey(); + V value = e.getValue(); + if (key == null || value == null) + throw new NullPointerException(); + return map.internalPut(key, value) == null; + } + public final boolean addAll(Collection> c) { + boolean added = false; + for (Entry e : c) { + if (add(e)) + added = true; + } + return added; + } + public boolean equals(Object o) { + Set c; + return ((o instanceof Set) && + ((c = (Set)o) == this || + (containsAll(c) && c.containsAll(this)))); + } + + /** + * Performs the given action for each entry. + * + * @param action the action + */ + public void forEach(Action> action) { + ForkJoinTasks.forEachEntry + (map, action).invoke(); + } + + /** + * Performs the given action for each non-null transformation + * of each entry. + * + * @param transformer a function returning the transformation + * for an element, or null of there is no transformation (in + * which case the action is not applied). + * @param action the action + */ + public void forEach(Fun, ? extends U> transformer, + Action action) { + ForkJoinTasks.forEachEntry + (map, transformer, action).invoke(); + } + + /** + * Returns a non-null result from applying the given search + * function on each entry, or null if none. Upon success, + * further element processing is suppressed and the results of + * any other parallel invocations of the search function are + * ignored. + * + * @param searchFunction a function returning a non-null + * result on success, else null + * @return a non-null result from applying the given search + * function on each entry, or null if none + */ + public U search(Fun, ? extends U> searchFunction) { + return ForkJoinTasks.searchEntries + (map, searchFunction).invoke(); + } + + /** + * Returns the result of accumulating all entries using the + * given reducer to combine values, or null if none. + * + * @param reducer a commutative associative combining function + * @return the result of accumulating all entries + */ + public Map.Entry reduce(BiFun, Map.Entry, ? extends Map.Entry> reducer) { + return ForkJoinTasks.reduceEntries + (map, reducer).invoke(); + } + + /** + * Returns the result of accumulating the given transformation + * of all entries using the given reducer to combine values, + * or null if none. + * + * @param transformer a function returning the transformation + * for an element, or null of there is no transformation (in + * which case it is not combined). + * @param reducer a commutative associative combining function + * @return the result of accumulating the given transformation + * of all entries + */ + public U reduce(Fun, ? extends U> transformer, + BiFun reducer) { + return ForkJoinTasks.reduceEntries + (map, transformer, reducer).invoke(); + } + + /** + * Returns the result of accumulating the given transformation + * of all entries using the given reducer to combine values, + * and the given basis as an identity value. + * + * @param transformer a function returning the transformation + * for an element + * @param basis the identity (initial default value) for the reduction + * @param reducer a commutative associative combining function + * @return the result of accumulating the given transformation + * of all entries + */ + public double reduceToDouble(ObjectToDouble> transformer, + double basis, + DoubleByDoubleToDouble reducer) { + return ForkJoinTasks.reduceEntriesToDouble + (map, transformer, basis, reducer).invoke(); + } + + /** + * Returns the result of accumulating the given transformation + * of all entries using the given reducer to combine values, + * and the given basis as an identity value. + * + * @param transformer a function returning the transformation + * for an element + * @param basis the identity (initial default value) for the reduction + * @param reducer a commutative associative combining function + * @return the result of accumulating the given transformation + * of all entries + */ + public long reduceToLong(ObjectToLong> transformer, + long basis, + LongByLongToLong reducer) { + return ForkJoinTasks.reduceEntriesToLong + (map, transformer, basis, reducer).invoke(); + } + + /** + * Returns the result of accumulating the given transformation + * of all entries using the given reducer to combine values, + * and the given basis as an identity value. + * + * @param transformer a function returning the transformation + * for an element + * @param basis the identity (initial default value) for the reduction + * @param reducer a commutative associative combining function + * @return the result of accumulating the given transformation + * of all entries + */ + public int reduceToInt(ObjectToInt> transformer, + int basis, + IntByIntToInt reducer) { + return ForkJoinTasks.reduceEntriesToInt + (map, transformer, basis, reducer).invoke(); + } + + } + // --------------------------------------------------------------------- /** @@ -4906,26 +5340,6 @@ public class ConcurrentHashMapV8 } } - // FJ methods - - /** - * Propagates completion. Note that all reduce actions - * bypass this method to combine while completing. - */ - final void tryComplete() { - BulkTask a = this, s = a; - for (int c;;) { - if ((c = a.pending) == 0) { - if ((a = (s = a).parent) == null) { - s.quietlyComplete(); - break; - } - } - else if (U.compareAndSwapInt(a, PENDING, c, c - 1)) - break; - } - } - /** * Forces root task to complete. * @param ex if null, complete normally, else exceptionally @@ -4973,7 +5387,7 @@ public class ConcurrentHashMapV8 baseLimit = baseSize = t.length; if (t != null) { long n = m.counter.sum(); - int par = (pool = getPool()) == null? + int par = ((pool = getPool()) == null) ? ForkJoinPool.getCommonPoolParallelism() : pool.getParallelism(); int sp = par << 3; // slack of 8 @@ -5004,6 +5418,50 @@ public class ConcurrentHashMapV8 } } + /** + * Base class for non-reductive actions + */ + @SuppressWarnings("serial") static abstract class BulkAction extends BulkTask { + BulkAction nextTask; + BulkAction(ConcurrentHashMapV8 map, BulkTask parent, + int batch, BulkAction nextTask) { + super(map, parent, batch); + this.nextTask = nextTask; + } + + /** + * Try to complete task and upward parents. Upon hitting + * non-completed parent, if a non-FJ task, try to help out the + * computation. + */ + final void tryComplete(BulkAction subtasks) { + BulkTask a = this, s = a; + for (int c;;) { + if ((c = a.pending) == 0) { + if ((a = (s = a).parent) == null) { + s.quietlyComplete(); + break; + } + } + else if (a.casPending(c, c - 1)) { + if (subtasks != null && !inForkJoinPool()) { + while ((s = a.parent) != null) + a = s; + while (!a.isDone()) { + BulkAction next = subtasks.nextTask; + if (subtasks.tryUnfork()) + subtasks.exec(); + if ((subtasks = next) == null) + break; + } + } + break; + } + } + } + + } + /* * Task classes. Coded in a regular but ugly format/style to * simplify checks that each variant differs in the right way from @@ -5011,172 +5469,146 @@ public class ConcurrentHashMapV8 */ @SuppressWarnings("serial") static final class ForEachKeyTask - extends BulkTask { + extends BulkAction { final Action action; - ForEachKeyTask nextRight; ForEachKeyTask (ConcurrentHashMapV8 m, BulkTask p, int b, - ForEachKeyTask nextRight, + ForEachKeyTask nextTask, Action action) { - super(m, p, b); - this.nextRight = nextRight; + super(m, p, b, nextTask); this.action = action; } @SuppressWarnings("unchecked") public final boolean exec() { final Action action = this.action; if (action == null) return abortOnNullFunction(); - ForEachKeyTask rights = null; + ForEachKeyTask subtasks = null; try { int b = batch(), c; while (b > 1 && baseIndex != baseLimit) { do {} while (!casPending(c = pending, c+1)); - (rights = new ForEachKeyTask - (map, this, b >>>= 1, rights, action)).fork(); + (subtasks = new ForEachKeyTask + (map, this, b >>>= 1, subtasks, action)).fork(); } while (advance() != null) action.apply((K)nextKey); - tryComplete(); } catch (Throwable ex) { return tryCompleteComputation(ex); } - while (rights != null && rights.tryUnfork()) { - rights.exec(); - rights = rights.nextRight; - } + tryComplete(subtasks); return false; } } @SuppressWarnings("serial") static final class ForEachValueTask - extends BulkTask { - ForEachValueTask nextRight; + extends BulkAction { final Action action; ForEachValueTask (ConcurrentHashMapV8 m, BulkTask p, int b, - ForEachValueTask nextRight, + ForEachValueTask nextTask, Action action) { - super(m, p, b); - this.nextRight = nextRight; + super(m, p, b, nextTask); this.action = action; } @SuppressWarnings("unchecked") public final boolean exec() { final Action action = this.action; if (action == null) return abortOnNullFunction(); - ForEachValueTask rights = null; + ForEachValueTask subtasks = null; try { int b = batch(), c; while (b > 1 && baseIndex != baseLimit) { do {} while (!casPending(c = pending, c+1)); - (rights = new ForEachValueTask - (map, this, b >>>= 1, rights, action)).fork(); + (subtasks = new ForEachValueTask + (map, this, b >>>= 1, subtasks, action)).fork(); } Object v; while ((v = advance()) != null) action.apply((V)v); - tryComplete(); } catch (Throwable ex) { return tryCompleteComputation(ex); } - while (rights != null && rights.tryUnfork()) { - rights.exec(); - rights = rights.nextRight; - } + tryComplete(subtasks); return false; } } @SuppressWarnings("serial") static final class ForEachEntryTask - extends BulkTask { - ForEachEntryTask nextRight; + extends BulkAction { final Action> action; ForEachEntryTask (ConcurrentHashMapV8 m, BulkTask p, int b, - ForEachEntryTask nextRight, + ForEachEntryTask nextTask, Action> action) { - super(m, p, b); - this.nextRight = nextRight; + super(m, p, b, nextTask); this.action = action; } @SuppressWarnings("unchecked") public final boolean exec() { final Action> action = this.action; if (action == null) return abortOnNullFunction(); - ForEachEntryTask rights = null; + ForEachEntryTask subtasks = null; try { int b = batch(), c; while (b > 1 && baseIndex != baseLimit) { do {} while (!casPending(c = pending, c+1)); - (rights = new ForEachEntryTask - (map, this, b >>>= 1, rights, action)).fork(); + (subtasks = new ForEachEntryTask + (map, this, b >>>= 1, subtasks, action)).fork(); } Object v; while ((v = advance()) != null) action.apply(entryFor((K)nextKey, (V)v)); - tryComplete(); } catch (Throwable ex) { return tryCompleteComputation(ex); } - while (rights != null && rights.tryUnfork()) { - rights.exec(); - rights = rights.nextRight; - } + tryComplete(subtasks); return false; } } @SuppressWarnings("serial") static final class ForEachMappingTask - extends BulkTask { - ForEachMappingTask nextRight; + extends BulkAction { final BiAction action; ForEachMappingTask (ConcurrentHashMapV8 m, BulkTask p, int b, - ForEachMappingTask nextRight, + ForEachMappingTask nextTask, BiAction action) { - super(m, p, b); - this.nextRight = nextRight; + super(m, p, b, nextTask); this.action = action; } @SuppressWarnings("unchecked") public final boolean exec() { final BiAction action = this.action; if (action == null) return abortOnNullFunction(); - ForEachMappingTask rights = null; + ForEachMappingTask subtasks = null; try { int b = batch(), c; while (b > 1 && baseIndex != baseLimit) { do {} while (!casPending(c = pending, c+1)); - (rights = new ForEachMappingTask - (map, this, b >>>= 1, rights, action)).fork(); + (subtasks = new ForEachMappingTask + (map, this, b >>>= 1, subtasks, action)).fork(); } Object v; while ((v = advance()) != null) action.apply((K)nextKey, (V)v); - tryComplete(); } catch (Throwable ex) { return tryCompleteComputation(ex); } - while (rights != null && rights.tryUnfork()) { - rights.exec(); - rights = rights.nextRight; - } + tryComplete(subtasks); return false; } } @SuppressWarnings("serial") static final class ForEachTransformedKeyTask - extends BulkTask { - ForEachTransformedKeyTask nextRight; + extends BulkAction { final Fun transformer; final Action action; ForEachTransformedKeyTask (ConcurrentHashMapV8 m, BulkTask p, int b, - ForEachTransformedKeyTask nextRight, + ForEachTransformedKeyTask nextTask, Fun transformer, Action action) { - super(m, p, b); - this.nextRight = nextRight; + super(m, p, b, nextTask); this.transformer = transformer; this.action = action; @@ -5187,43 +5619,37 @@ public class ConcurrentHashMapV8 final Action action = this.action; if (transformer == null || action == null) return abortOnNullFunction(); - ForEachTransformedKeyTask rights = null; + ForEachTransformedKeyTask subtasks = null; try { int b = batch(), c; while (b > 1 && baseIndex != baseLimit) { do {} while (!casPending(c = pending, c+1)); - (rights = new ForEachTransformedKeyTask - (map, this, b >>>= 1, rights, transformer, action)).fork(); + (subtasks = new ForEachTransformedKeyTask + (map, this, b >>>= 1, subtasks, transformer, action)).fork(); } U u; while (advance() != null) { if ((u = transformer.apply((K)nextKey)) != null) action.apply(u); } - tryComplete(); } catch (Throwable ex) { return tryCompleteComputation(ex); } - while (rights != null && rights.tryUnfork()) { - rights.exec(); - rights = rights.nextRight; - } + tryComplete(subtasks); return false; } } @SuppressWarnings("serial") static final class ForEachTransformedValueTask - extends BulkTask { - ForEachTransformedValueTask nextRight; + extends BulkAction { final Fun transformer; final Action action; ForEachTransformedValueTask (ConcurrentHashMapV8 m, BulkTask p, int b, - ForEachTransformedValueTask nextRight, + ForEachTransformedValueTask nextTask, Fun transformer, Action action) { - super(m, p, b); - this.nextRight = nextRight; + super(m, p, b, nextTask); this.transformer = transformer; this.action = action; @@ -5234,43 +5660,37 @@ public class ConcurrentHashMapV8 final Action action = this.action; if (transformer == null || action == null) return abortOnNullFunction(); - ForEachTransformedValueTask rights = null; + ForEachTransformedValueTask subtasks = null; try { int b = batch(), c; while (b > 1 && baseIndex != baseLimit) { do {} while (!casPending(c = pending, c+1)); - (rights = new ForEachTransformedValueTask - (map, this, b >>>= 1, rights, transformer, action)).fork(); + (subtasks = new ForEachTransformedValueTask + (map, this, b >>>= 1, subtasks, transformer, action)).fork(); } Object v; U u; while ((v = advance()) != null) { if ((u = transformer.apply((V)v)) != null) action.apply(u); } - tryComplete(); } catch (Throwable ex) { return tryCompleteComputation(ex); } - while (rights != null && rights.tryUnfork()) { - rights.exec(); - rights = rights.nextRight; - } + tryComplete(subtasks); return false; } } @SuppressWarnings("serial") static final class ForEachTransformedEntryTask - extends BulkTask { - ForEachTransformedEntryTask nextRight; + extends BulkAction { final Fun, ? extends U> transformer; final Action action; ForEachTransformedEntryTask (ConcurrentHashMapV8 m, BulkTask p, int b, - ForEachTransformedEntryTask nextRight, + ForEachTransformedEntryTask nextTask, Fun, ? extends U> transformer, Action action) { - super(m, p, b); - this.nextRight = nextRight; + super(m, p, b, nextTask); this.transformer = transformer; this.action = action; @@ -5281,43 +5701,37 @@ public class ConcurrentHashMapV8 final Action action = this.action; if (transformer == null || action == null) return abortOnNullFunction(); - ForEachTransformedEntryTask rights = null; + ForEachTransformedEntryTask subtasks = null; try { int b = batch(), c; while (b > 1 && baseIndex != baseLimit) { do {} while (!casPending(c = pending, c+1)); - (rights = new ForEachTransformedEntryTask - (map, this, b >>>= 1, rights, transformer, action)).fork(); + (subtasks = new ForEachTransformedEntryTask + (map, this, b >>>= 1, subtasks, transformer, action)).fork(); } Object v; U u; while ((v = advance()) != null) { if ((u = transformer.apply(entryFor((K)nextKey, (V)v))) != null) action.apply(u); } - tryComplete(); } catch (Throwable ex) { return tryCompleteComputation(ex); } - while (rights != null && rights.tryUnfork()) { - rights.exec(); - rights = rights.nextRight; - } + tryComplete(subtasks); return false; } } @SuppressWarnings("serial") static final class ForEachTransformedMappingTask - extends BulkTask { - ForEachTransformedMappingTask nextRight; + extends BulkAction { final BiFun transformer; final Action action; ForEachTransformedMappingTask (ConcurrentHashMapV8 m, BulkTask p, int b, - ForEachTransformedMappingTask nextRight, + ForEachTransformedMappingTask nextTask, BiFun transformer, Action action) { - super(m, p, b); - this.nextRight = nextRight; + super(m, p, b, nextTask); this.transformer = transformer; this.action = action; @@ -5328,43 +5742,37 @@ public class ConcurrentHashMapV8 final Action action = this.action; if (transformer == null || action == null) return abortOnNullFunction(); - ForEachTransformedMappingTask rights = null; + ForEachTransformedMappingTask subtasks = null; try { int b = batch(), c; while (b > 1 && baseIndex != baseLimit) { do {} while (!casPending(c = pending, c+1)); - (rights = new ForEachTransformedMappingTask - (map, this, b >>>= 1, rights, transformer, action)).fork(); + (subtasks = new ForEachTransformedMappingTask + (map, this, b >>>= 1, subtasks, transformer, action)).fork(); } Object v; U u; while ((v = advance()) != null) { if ((u = transformer.apply((K)nextKey, (V)v)) != null) action.apply(u); } - tryComplete(); } catch (Throwable ex) { return tryCompleteComputation(ex); } - while (rights != null && rights.tryUnfork()) { - rights.exec(); - rights = rights.nextRight; - } + tryComplete(subtasks); return false; } } @SuppressWarnings("serial") static final class SearchKeysTask - extends BulkTask { - SearchKeysTask nextRight; + extends BulkAction { final Fun searchFunction; final AtomicReference result; SearchKeysTask (ConcurrentHashMapV8 m, BulkTask p, int b, - SearchKeysTask nextRight, + SearchKeysTask nextTask, Fun searchFunction, AtomicReference result) { - super(m, p, b); - this.nextRight = nextRight; + super(m, p, b, nextTask); this.searchFunction = searchFunction; this.result = result; } @SuppressWarnings("unchecked") public final boolean exec() { @@ -5373,13 +5781,13 @@ public class ConcurrentHashMapV8 this.searchFunction; if (searchFunction == null || result == null) return abortOnNullFunction(); - SearchKeysTask rights = null; + SearchKeysTask subtasks = null; try { int b = batch(), c; while (b > 1 && baseIndex != baseLimit && result.get() == null) { do {} while (!casPending(c = pending, c+1)); - (rights = new SearchKeysTask - (map, this, b >>>= 1, rights, searchFunction, result)).fork(); + (subtasks = new SearchKeysTask + (map, this, b >>>= 1, subtasks, searchFunction, result)).fork(); } U u; while (result.get() == null && advance() != null) { @@ -5389,31 +5797,25 @@ public class ConcurrentHashMapV8 break; } } - tryComplete(); } catch (Throwable ex) { return tryCompleteComputation(ex); } - while (rights != null && result.get() == null && rights.tryUnfork()) { - rights.exec(); - rights = rights.nextRight; - } + tryComplete(subtasks); return false; } public final U getRawResult() { return result.get(); } } @SuppressWarnings("serial") static final class SearchValuesTask - extends BulkTask { - SearchValuesTask nextRight; + extends BulkAction { final Fun searchFunction; final AtomicReference result; SearchValuesTask (ConcurrentHashMapV8 m, BulkTask p, int b, - SearchValuesTask nextRight, + SearchValuesTask nextTask, Fun searchFunction, AtomicReference result) { - super(m, p, b); - this.nextRight = nextRight; + super(m, p, b, nextTask); this.searchFunction = searchFunction; this.result = result; } @SuppressWarnings("unchecked") public final boolean exec() { @@ -5422,13 +5824,13 @@ public class ConcurrentHashMapV8 this.searchFunction; if (searchFunction == null || result == null) return abortOnNullFunction(); - SearchValuesTask rights = null; + SearchValuesTask subtasks = null; try { int b = batch(), c; while (b > 1 && baseIndex != baseLimit && result.get() == null) { do {} while (!casPending(c = pending, c+1)); - (rights = new SearchValuesTask - (map, this, b >>>= 1, rights, searchFunction, result)).fork(); + (subtasks = new SearchValuesTask + (map, this, b >>>= 1, subtasks, searchFunction, result)).fork(); } Object v; U u; while (result.get() == null && (v = advance()) != null) { @@ -5438,31 +5840,25 @@ public class ConcurrentHashMapV8 break; } } - tryComplete(); } catch (Throwable ex) { return tryCompleteComputation(ex); } - while (rights != null && result.get() == null && rights.tryUnfork()) { - rights.exec(); - rights = rights.nextRight; - } + tryComplete(subtasks); return false; } public final U getRawResult() { return result.get(); } } @SuppressWarnings("serial") static final class SearchEntriesTask - extends BulkTask { - SearchEntriesTask nextRight; + extends BulkAction { final Fun, ? extends U> searchFunction; final AtomicReference result; SearchEntriesTask (ConcurrentHashMapV8 m, BulkTask p, int b, - SearchEntriesTask nextRight, + SearchEntriesTask nextTask, Fun, ? extends U> searchFunction, AtomicReference result) { - super(m, p, b); - this.nextRight = nextRight; + super(m, p, b, nextTask); this.searchFunction = searchFunction; this.result = result; } @SuppressWarnings("unchecked") public final boolean exec() { @@ -5471,13 +5867,13 @@ public class ConcurrentHashMapV8 this.searchFunction; if (searchFunction == null || result == null) return abortOnNullFunction(); - SearchEntriesTask rights = null; + SearchEntriesTask subtasks = null; try { int b = batch(), c; while (b > 1 && baseIndex != baseLimit && result.get() == null) { do {} while (!casPending(c = pending, c+1)); - (rights = new SearchEntriesTask - (map, this, b >>>= 1, rights, searchFunction, result)).fork(); + (subtasks = new SearchEntriesTask + (map, this, b >>>= 1, subtasks, searchFunction, result)).fork(); } Object v; U u; while (result.get() == null && (v = advance()) != null) { @@ -5487,31 +5883,25 @@ public class ConcurrentHashMapV8 break; } } - tryComplete(); } catch (Throwable ex) { return tryCompleteComputation(ex); } - while (rights != null && result.get() == null && rights.tryUnfork()) { - rights.exec(); - rights = rights.nextRight; - } + tryComplete(subtasks); return false; } public final U getRawResult() { return result.get(); } } @SuppressWarnings("serial") static final class SearchMappingsTask - extends BulkTask { - SearchMappingsTask nextRight; + extends BulkAction { final BiFun searchFunction; final AtomicReference result; SearchMappingsTask (ConcurrentHashMapV8 m, BulkTask p, int b, - SearchMappingsTask nextRight, + SearchMappingsTask nextTask, BiFun searchFunction, AtomicReference result) { - super(m, p, b); - this.nextRight = nextRight; + super(m, p, b, nextTask); this.searchFunction = searchFunction; this.result = result; } @SuppressWarnings("unchecked") public final boolean exec() { @@ -5520,13 +5910,13 @@ public class ConcurrentHashMapV8 this.searchFunction; if (searchFunction == null || result == null) return abortOnNullFunction(); - SearchMappingsTask rights = null; + SearchMappingsTask subtasks = null; try { int b = batch(), c; while (b > 1 && baseIndex != baseLimit && result.get() == null) { do {} while (!casPending(c = pending, c+1)); - (rights = new SearchMappingsTask - (map, this, b >>>= 1, rights, searchFunction, result)).fork(); + (subtasks = new SearchMappingsTask + (map, this, b >>>= 1, subtasks, searchFunction, result)).fork(); } Object v; U u; while (result.get() == null && (v = advance()) != null) { @@ -5536,14 +5926,10 @@ public class ConcurrentHashMapV8 break; } } - tryComplete(); } catch (Throwable ex) { return tryCompleteComputation(ex); } - while (rights != null && result.get() == null && rights.tryUnfork()) { - rights.exec(); - rights = rights.nextRight; - } + tryComplete(subtasks); return false; } public final U getRawResult() { return result.get(); } @@ -5598,8 +5984,13 @@ public class ConcurrentHashMapV8 } catch (Throwable ex) { return tryCompleteComputation(ex); } - for (ReduceKeysTask s = rights; s != null && s.tryUnfork(); s = s.nextRight) - s.exec(); + ReduceKeysTask s = rights; + if (s != null && !inForkJoinPool()) { + do { + if (s.tryUnfork()) + s.exec(); + } while ((s = s.nextRight) != null); + } return false; } public final K getRawResult() { return result; } @@ -5655,8 +6046,13 @@ public class ConcurrentHashMapV8 } catch (Throwable ex) { return tryCompleteComputation(ex); } - for (ReduceValuesTask s = rights; s != null && s.tryUnfork(); s = s.nextRight) - s.exec(); + ReduceValuesTask s = rights; + if (s != null && !inForkJoinPool()) { + do { + if (s.tryUnfork()) + s.exec(); + } while ((s = s.nextRight) != null); + } return false; } public final V getRawResult() { return result; } @@ -5712,8 +6108,13 @@ public class ConcurrentHashMapV8 } catch (Throwable ex) { return tryCompleteComputation(ex); } - for (ReduceEntriesTask s = rights; s != null && s.tryUnfork(); s = s.nextRight) - s.exec(); + ReduceEntriesTask s = rights; + if (s != null && !inForkJoinPool()) { + do { + if (s.tryUnfork()) + s.exec(); + } while ((s = s.nextRight) != null); + } return false; } public final Map.Entry getRawResult() { return result; } @@ -5773,8 +6174,13 @@ public class ConcurrentHashMapV8 } catch (Throwable ex) { return tryCompleteComputation(ex); } - for (MapReduceKeysTask s = rights; s != null && s.tryUnfork(); s = s.nextRight) - s.exec(); + MapReduceKeysTask s = rights; + if (s != null && !inForkJoinPool()) { + do { + if (s.tryUnfork()) + s.exec(); + } while ((s = s.nextRight) != null); + } return false; } public final U getRawResult() { return result; } @@ -5835,8 +6241,13 @@ public class ConcurrentHashMapV8 } catch (Throwable ex) { return tryCompleteComputation(ex); } - for (MapReduceValuesTask s = rights; s != null && s.tryUnfork(); s = s.nextRight) - s.exec(); + MapReduceValuesTask s = rights; + if (s != null && !inForkJoinPool()) { + do { + if (s.tryUnfork()) + s.exec(); + } while ((s = s.nextRight) != null); + } return false; } public final U getRawResult() { return result; } @@ -5897,8 +6308,13 @@ public class ConcurrentHashMapV8 } catch (Throwable ex) { return tryCompleteComputation(ex); } - for (MapReduceEntriesTask s = rights; s != null && s.tryUnfork(); s = s.nextRight) - s.exec(); + MapReduceEntriesTask s = rights; + if (s != null && !inForkJoinPool()) { + do { + if (s.tryUnfork()) + s.exec(); + } while ((s = s.nextRight) != null); + } return false; } public final U getRawResult() { return result; } @@ -5959,8 +6375,13 @@ public class ConcurrentHashMapV8 } catch (Throwable ex) { return tryCompleteComputation(ex); } - for (MapReduceMappingsTask s = rights; s != null && s.tryUnfork(); s = s.nextRight) - s.exec(); + MapReduceMappingsTask s = rights; + if (s != null && !inForkJoinPool()) { + do { + if (s.tryUnfork()) + s.exec(); + } while ((s = s.nextRight) != null); + } return false; } public final U getRawResult() { return result; } @@ -6019,8 +6440,13 @@ public class ConcurrentHashMapV8 } catch (Throwable ex) { return tryCompleteComputation(ex); } - for (MapReduceKeysToDoubleTask s = rights; s != null && s.tryUnfork(); s = s.nextRight) - s.exec(); + MapReduceKeysToDoubleTask s = rights; + if (s != null && !inForkJoinPool()) { + do { + if (s.tryUnfork()) + s.exec(); + } while ((s = s.nextRight) != null); + } return false; } public final Double getRawResult() { return result; } @@ -6080,8 +6506,13 @@ public class ConcurrentHashMapV8 } catch (Throwable ex) { return tryCompleteComputation(ex); } - for (MapReduceValuesToDoubleTask s = rights; s != null && s.tryUnfork(); s = s.nextRight) - s.exec(); + MapReduceValuesToDoubleTask s = rights; + if (s != null && !inForkJoinPool()) { + do { + if (s.tryUnfork()) + s.exec(); + } while ((s = s.nextRight) != null); + } return false; } public final Double getRawResult() { return result; } @@ -6141,8 +6572,13 @@ public class ConcurrentHashMapV8 } catch (Throwable ex) { return tryCompleteComputation(ex); } - for (MapReduceEntriesToDoubleTask s = rights; s != null && s.tryUnfork(); s = s.nextRight) - s.exec(); + MapReduceEntriesToDoubleTask s = rights; + if (s != null && !inForkJoinPool()) { + do { + if (s.tryUnfork()) + s.exec(); + } while ((s = s.nextRight) != null); + } return false; } public final Double getRawResult() { return result; } @@ -6202,8 +6638,13 @@ public class ConcurrentHashMapV8 } catch (Throwable ex) { return tryCompleteComputation(ex); } - for (MapReduceMappingsToDoubleTask s = rights; s != null && s.tryUnfork(); s = s.nextRight) - s.exec(); + MapReduceMappingsToDoubleTask s = rights; + if (s != null && !inForkJoinPool()) { + do { + if (s.tryUnfork()) + s.exec(); + } while ((s = s.nextRight) != null); + } return false; } public final Double getRawResult() { return result; } @@ -6262,8 +6703,13 @@ public class ConcurrentHashMapV8 } catch (Throwable ex) { return tryCompleteComputation(ex); } - for (MapReduceKeysToLongTask s = rights; s != null && s.tryUnfork(); s = s.nextRight) - s.exec(); + MapReduceKeysToLongTask s = rights; + if (s != null && !inForkJoinPool()) { + do { + if (s.tryUnfork()) + s.exec(); + } while ((s = s.nextRight) != null); + } return false; } public final Long getRawResult() { return result; } @@ -6323,8 +6769,13 @@ public class ConcurrentHashMapV8 } catch (Throwable ex) { return tryCompleteComputation(ex); } - for (MapReduceValuesToLongTask s = rights; s != null && s.tryUnfork(); s = s.nextRight) - s.exec(); + MapReduceValuesToLongTask s = rights; + if (s != null && !inForkJoinPool()) { + do { + if (s.tryUnfork()) + s.exec(); + } while ((s = s.nextRight) != null); + } return false; } public final Long getRawResult() { return result; } @@ -6384,8 +6835,13 @@ public class ConcurrentHashMapV8 } catch (Throwable ex) { return tryCompleteComputation(ex); } - for (MapReduceEntriesToLongTask s = rights; s != null && s.tryUnfork(); s = s.nextRight) - s.exec(); + MapReduceEntriesToLongTask s = rights; + if (s != null && !inForkJoinPool()) { + do { + if (s.tryUnfork()) + s.exec(); + } while ((s = s.nextRight) != null); + } return false; } public final Long getRawResult() { return result; } @@ -6445,8 +6901,13 @@ public class ConcurrentHashMapV8 } catch (Throwable ex) { return tryCompleteComputation(ex); } - for (MapReduceMappingsToLongTask s = rights; s != null && s.tryUnfork(); s = s.nextRight) - s.exec(); + MapReduceMappingsToLongTask s = rights; + if (s != null && !inForkJoinPool()) { + do { + if (s.tryUnfork()) + s.exec(); + } while ((s = s.nextRight) != null); + } return false; } public final Long getRawResult() { return result; } @@ -6505,8 +6966,13 @@ public class ConcurrentHashMapV8 } catch (Throwable ex) { return tryCompleteComputation(ex); } - for (MapReduceKeysToIntTask s = rights; s != null && s.tryUnfork(); s = s.nextRight) - s.exec(); + MapReduceKeysToIntTask s = rights; + if (s != null && !inForkJoinPool()) { + do { + if (s.tryUnfork()) + s.exec(); + } while ((s = s.nextRight) != null); + } return false; } public final Integer getRawResult() { return result; } @@ -6566,8 +7032,13 @@ public class ConcurrentHashMapV8 } catch (Throwable ex) { return tryCompleteComputation(ex); } - for (MapReduceValuesToIntTask s = rights; s != null && s.tryUnfork(); s = s.nextRight) - s.exec(); + MapReduceValuesToIntTask s = rights; + if (s != null && !inForkJoinPool()) { + do { + if (s.tryUnfork()) + s.exec(); + } while ((s = s.nextRight) != null); + } return false; } public final Integer getRawResult() { return result; } @@ -6627,8 +7098,13 @@ public class ConcurrentHashMapV8 } catch (Throwable ex) { return tryCompleteComputation(ex); } - for (MapReduceEntriesToIntTask s = rights; s != null && s.tryUnfork(); s = s.nextRight) - s.exec(); + MapReduceEntriesToIntTask s = rights; + if (s != null && !inForkJoinPool()) { + do { + if (s.tryUnfork()) + s.exec(); + } while ((s = s.nextRight) != null); + } return false; } public final Integer getRawResult() { return result; } @@ -6688,8 +7164,13 @@ public class ConcurrentHashMapV8 } catch (Throwable ex) { return tryCompleteComputation(ex); } - for (MapReduceMappingsToIntTask s = rights; s != null && s.tryUnfork(); s = s.nextRight) - s.exec(); + MapReduceMappingsToIntTask s = rights; + if (s != null && !inForkJoinPool()) { + do { + if (s.tryUnfork()) + s.exec(); + } while ((s = s.nextRight) != null); + } return false; } public final Integer getRawResult() { return result; }