--- jsr166/src/jsr166e/ConcurrentHashMapV8.java 2012/07/03 23:25:57 1.41 +++ jsr166/src/jsr166e/ConcurrentHashMapV8.java 2012/08/13 15:52:33 1.52 @@ -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; /** @@ -88,7 +94,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 +104,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;}
@@ -2513,7 +2610,7 @@ public class ConcurrentHashMapV8 {@code
- * map.computeIfAbsent(key, new MappingFunction
*
* @param key key with which the specified value is to be associated
@@ -2529,18 +2626,59 @@ 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
+ */
+ 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
@@ -2560,8 +2698,8 @@ public class ConcurrentHashMapV8
{@code
* Map
*
* @param key key with which the specified value is to be associated
@@ -2576,11 +2714,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);
}
/**
@@ -2593,7 +2763,7 @@ public class ConcurrentHashMapV8
+ *
+ *
+ *
+ *
+ *
+ *