--- jsr166/src/jsr166e/ConcurrentHashMapV8.java 2012/07/07 13:01:53 1.50 +++ jsr166/src/jsr166e/ConcurrentHashMapV8.java 2012/10/21 03:26:47 1.66 @@ -6,6 +6,10 @@ package jsr166e; import jsr166e.LongAdder; +import jsr166e.ForkJoinPool; +import jsr166e.ForkJoinTask; + +import java.util.Comparator; import java.util.Arrays; import java.util.Map; import java.util.Set; @@ -23,6 +27,8 @@ import java.util.concurrent.ConcurrentMa import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.locks.LockSupport; import java.util.concurrent.locks.AbstractQueuedSynchronizer; +import java.util.concurrent.atomic.AtomicReference; + import java.io.Serializable; /** @@ -41,19 +47,22 @@ import java.io.Serializable; * 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 - * onset. For aggregate operations such as {@code putAll} and {@code - * clear}, concurrent retrievals may reflect insertion or removal of - * only some entries. Similarly, Iterators and Enumerations return - * elements reflecting the state of the hash table at some point at or - * since the creation of the iterator/enumeration. They do - * not throw {@link ConcurrentModificationException}. - * However, iterators are designed to be used by only one thread at a - * time. Bear in mind that the results of aggregate status methods - * including {@code size}, {@code isEmpty}, and {@code containsValue} - * are typically useful only when a map is not undergoing concurrent - * updates in other threads. Otherwise the results of these methods - * reflect transient states that may be adequate for monitoring - * or estimation purposes, but not for program control. + * onset. (More formally, an update operation for a given key bears a + * happens-before relation with any (non-null) retrieval for + * that key reporting the updated value.) For aggregate operations + * such as {@code putAll} and {@code clear}, concurrent retrievals may + * reflect insertion or removal of only some entries. Similarly, + * Iterators and Enumerations return elements reflecting the state of + * the hash table at some point at or since the creation of the + * iterator/enumeration. They do not throw {@link + * ConcurrentModificationException}. However, iterators are designed + * to be used by only one thread at a time. Bear in mind that the + * results of aggregate status methods including {@code size}, {@code + * isEmpty}, and {@code containsValue} are typically useful only when + * a map is not undergoing concurrent updates in other threads. + * Otherwise the results of these methods reflect transient states + * that may be adequate for monitoring or estimation purposes, but not + * for program control. * *
The table is dynamically expanded when there are too many * collisions (i.e., keys that have distinct hash codes but fall into @@ -88,7 +97,9 @@ import java.io.Serializable; * Java Collections Framework. * *
jsr166e note: This class is a candidate replacement for
- * java.util.concurrent.ConcurrentHashMap.
+ * java.util.concurrent.ConcurrentHashMap. During transition, this
+ * class declares and uses nested functional interfaces with different
+ * names but the same forms as those expected for JDK8.
*
* @since 1.5
* @author Doug Lea
@@ -96,41 +107,10 @@ import java.io.Serializable;
* @param The concurrency properties of the bulk operations follow
+ * from those of ConcurrentHashMap: Any non-null result returned
+ * from {@code get(key)} and related access methods bears a
+ * happens-before relation with the associated insertion or
+ * update. The result of any bulk operation reflects the
+ * composition of these per-element relations (but is not
+ * necessarily atomic with respect to the map as a whole unless it
+ * is somehow known to be quiescent). Conversely, because keys
+ * and values in the map are never null, null serves as a reliable
+ * atomic indicator of the current lack of any result. To
+ * maintain this property, null serves as an implicit basis for
+ * all non-scalar reduction operations. For the double, long, and
+ * int versions, the basis should be one that, when combined with
+ * any other value, returns that other value (more formally, it
+ * should be the identity element for the reduction). Most common
+ * reductions have these properties; for example, computing a sum
+ * with basis 0 or a minimum with basis MAX_VALUE.
+ *
+ * Search and transformation functions provided as arguments
+ * should similarly return null to indicate the lack of any result
+ * (in which case it is not used). In the case of mapped
+ * reductions, this also enables transformations to serve as
+ * filters, returning null (or, in the case of primitive
+ * specializations, the identity basis) if the element should not
+ * be combined. You can create compound transformations and
+ * filterings by composing them yourself under this "null means
+ * there is nothing there now" rule before using them in search or
+ * reduce operations.
+ *
+ * Methods accepting and/or returning Entry arguments maintain
+ * key-value associations. They may be useful for example when
+ * finding the key for the greatest value. Note that "plain" Entry
+ * arguments can be supplied using {@code new
+ * AbstractMap.SimpleEntry(k,v)}.
+ *
+ * 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
+ * exceptions, or would have done so if the first exception had
+ * not occurred.
+ *
+ * Parallel speedups compared to sequential 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.
+ *
+ * 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.
+ */
+ public class Parallel {
+ final ForkJoinPool fjp;
+
+ /**
+ * Returns an extended view of this map using the given
+ * executor for bulk parallel operations.
+ *
+ * @param executor the executor
+ */
+ public Parallel(ForkJoinPool executor) {
+ this.fjp = executor;
+ }
+
+ /**
+ * Performs the given action for each (key, value).
+ *
+ * @param action the action
+ */
+ public void forEach(BiAction
* {@code ConcurrentHashMapV8
{@code
* if (map.containsKey(key))
* return map.get(key);
- * value = mappingFunction.map(key);
+ * value = mappingFunction.apply(key);
* if (value != null)
* map.put(key, value);
* return value;}
@@ -2501,7 +2644,7 @@ public class ConcurrentHashMapV8 {@code
- * map.computeIfAbsent(key, new MappingFunction
*
* @param key key with which the specified value is to be associated
@@ -2516,19 +2659,60 @@ public class ConcurrentHashMapV8 {@code
+ * if (map.containsKey(key)) {
+ * value = remappingFunction.apply(key, map.get(key));
+ * if (value != null)
+ * map.put(key, value);
+ * else
+ * map.remove(key);
+ * }
+ * }
+ *
+ * except that the action is performed atomically. If the
+ * function returns {@code null}, the mapping is removed. If the
+ * function itself throws an (unchecked) exception, the exception
+ * is rethrown to its caller, and the current mapping is left
+ * unchanged. Some attempted update operations on this map by
+ * other threads may be blocked while computation is in progress,
+ * so the computation should be short and simple, and must not
+ * attempt to update any other mappings of this Map. For example,
+ * to either create or append new messages to a value mapping:
+ *
+ * @param key key with which the specified value is to be associated
+ * @param remappingFunction the function to compute a value
+ * @return the new value associated with the specified key, or null if none
+ * @throws NullPointerException if the specified key or remappingFunction
+ * is null
+ * @throws IllegalStateException if the computation detectably
+ * attempts a recursive update to this map that would
+ * otherwise never complete
+ * @throws RuntimeException or Error if the remappingFunction does so,
+ * in which case the mapping is unchanged
+ */
+ @SuppressWarnings("unchecked") public V computeIfPresent
+ (K key, BiFun super K, ? super V, ? extends V> remappingFunction) {
+ if (key == null || remappingFunction == null)
+ throw new NullPointerException();
+ return (V)internalCompute(key, true, remappingFunction);
+ }
+
+ /**
* Computes a new mapping value given a key and
* its current mapped value (or {@code null} if there is no current
* mapping). This is equivalent to
* {@code
- * value = remappingFunction.remap(key, map.get(key));
+ * value = remappingFunction.apply(key, map.get(key));
* if (value != null)
* map.put(key, value);
* else
@@ -2548,14 +2732,13 @@ public class ConcurrentHashMapV8
{@code
* Map
*
* @param key key with which the specified value is to be associated
* @param remappingFunction the function to compute a value
- * @return the new value associated with
- * the specified key, or null if none.
+ * @return the new value associated with the specified key, or null if none
* @throws NullPointerException if the specified key or remappingFunction
* is null
* @throws IllegalStateException if the computation detectably
@@ -2564,11 +2747,43 @@ public class ConcurrentHashMapV8 {@code
+ * if (!map.containsKey(key))
+ * map.put(value);
+ * else {
+ * newValue = remappingFunction.apply(map.get(key), value);
+ * if (value != null)
+ * map.put(key, value);
+ * else
+ * map.remove(key);
+ * }
+ * }
+ * except that the action is performed atomically. If the
+ * function returns {@code null}, the mapping is removed. If the
+ * function itself throws an (unchecked) exception, the exception
+ * is rethrown to its caller, and the current mapping is left
+ * unchanged. Some attempted update operations on this map by
+ * other threads may be blocked while computation is in progress,
+ * so the computation should be short and simple, and must not
+ * attempt to update any other mappings of this Map.
+ */
+ @SuppressWarnings("unchecked") public V merge
+ (K key, V value, BiFun super V, ? super V, ? extends V> remappingFunction) {
+ if (key == null || value == null || remappingFunction == null)
+ throw new NullPointerException();
+ return (V)internalMerge(key, value, remappingFunction);
}
/**
@@ -2580,8 +2795,7 @@ public class ConcurrentHashMapV8
+ *
+ *
+ *
+ *
+ *
+ *