--- jsr166/src/jsr166y/ForkJoinTask.java 2009/07/24 22:05:22 1.15 +++ jsr166/src/jsr166y/ForkJoinTask.java 2009/07/26 17:33:37 1.22 @@ -5,12 +5,15 @@ */ package jsr166y; -import java.io.Serializable; -import java.util.*; + import java.util.concurrent.*; -import java.util.concurrent.atomic.*; -import sun.misc.Unsafe; -import java.lang.reflect.*; + +import java.io.Serializable; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.WeakHashMap; /** * Abstract base class for tasks that run within a {@link @@ -489,10 +492,13 @@ public abstract class ForkJoinTask im * computations (as may be determined using method {@link * #inForkJoinPool}). Attempts to invoke in other contexts result * in exceptions or errors, possibly including ClassCastException. + * + * @return {@code this}, to simplify usage. */ - public final void fork() { + public final ForkJoinTask fork() { ((ForkJoinWorkerThread) Thread.currentThread()) .pushTask(this); + return this; } /** @@ -600,13 +606,14 @@ public abstract class ForkJoinTask im * in exceptions or errors, possibly including ClassCastException. * * @param tasks the collection of tasks + * @return the tasks argument, to simplify usage * @throws NullPointerException if tasks or any element are null * @throws RuntimeException or Error if any task did so */ - public static void invokeAll(Collection> tasks) { + public static > Collection invokeAll(Collection tasks) { if (!(tasks instanceof List)) { invokeAll(tasks.toArray(new ForkJoinTask[tasks.size()])); - return; + return tasks; } @SuppressWarnings("unchecked") List> ts = @@ -641,6 +648,7 @@ public abstract class ForkJoinTask im } if (ex != null) rethrowException(ex); + return tasks; } /** @@ -1031,6 +1039,46 @@ public abstract class ForkJoinTask im .pollTask(); } + // adaptors + + /** + * Returns a new ForkJoinTask that performs the {@code run} + * method of the given Runnable as its action, and returns a null + * result upon {@code join}. + * + * @param runnable the runnable action + * @return the task + */ + public static ForkJoinTask adapt(Runnable runnable) { + return new ForkJoinPool.AdaptedRunnable(runnable, null); + } + + /** + * Returns a new ForkJoinTask that performs the {@code run} + * method of the given Runnable as its action, and returns the + * given result upon {@code join}. + * + * @param runnable the runnable action + * @param result the result upon completion + * @return the task + */ + public static ForkJoinTask adapt(Runnable runnable, T result) { + return new ForkJoinPool.AdaptedRunnable(runnable, result); + } + + /** + * Returns a new ForkJoinTask that performs the {@code call} + * method of the given Callable as its action, and returns its + * result upon {@code join}, translating any checked + * exceptions encountered into {@code RuntimeException}. + * + * @param callable the callable action + * @return the task + */ + public static ForkJoinTask adapt(Callable callable) { + return new ForkJoinPool.AdaptedCallable(callable); + } + // Serialization support private static final long serialVersionUID = -7721805057305804111L; @@ -1063,46 +1111,48 @@ public abstract class ForkJoinTask im setDoneExceptionally((Throwable) ex); } - // Temporary Unsafe mechanics for preliminary release - private static Unsafe getUnsafe() throws Throwable { + // Unsafe mechanics + + private static final sun.misc.Unsafe UNSAFE = getUnsafe(); + private static final long statusOffset = + objectFieldOffset("status", ForkJoinTask.class); + + private static long objectFieldOffset(String field, Class klazz) { + try { + return UNSAFE.objectFieldOffset(klazz.getDeclaredField(field)); + } catch (NoSuchFieldException e) { + // Convert Exception to corresponding Error + NoSuchFieldError error = new NoSuchFieldError(field); + error.initCause(e); + throw error; + } + } + + /** + * Returns a sun.misc.Unsafe. Suitable for use in a 3rd party package. + * Replace with a simple call to Unsafe.getUnsafe when integrating + * into a jdk. + * + * @return a sun.misc.Unsafe + */ + private static sun.misc.Unsafe getUnsafe() { try { - return Unsafe.getUnsafe(); + return sun.misc.Unsafe.getUnsafe(); } catch (SecurityException se) { try { return java.security.AccessController.doPrivileged - (new java.security.PrivilegedExceptionAction() { - public Unsafe run() throws Exception { - return getUnsafePrivileged(); + (new java.security + .PrivilegedExceptionAction() { + public sun.misc.Unsafe run() throws Exception { + java.lang.reflect.Field f = sun.misc + .Unsafe.class.getDeclaredField("theUnsafe"); + f.setAccessible(true); + return (sun.misc.Unsafe) f.get(null); }}); } catch (java.security.PrivilegedActionException e) { - throw e.getCause(); + throw new RuntimeException("Could not initialize intrinsics", + e.getCause()); } } } - - private static Unsafe getUnsafePrivileged() - throws NoSuchFieldException, IllegalAccessException { - Field f = Unsafe.class.getDeclaredField("theUnsafe"); - f.setAccessible(true); - return (Unsafe) f.get(null); - } - - private static long fieldOffset(String fieldName) - throws NoSuchFieldException { - return UNSAFE.objectFieldOffset - (ForkJoinTask.class.getDeclaredField(fieldName)); - } - - static final Unsafe UNSAFE; - static final long statusOffset; - - static { - try { - UNSAFE = getUnsafe(); - statusOffset = fieldOffset("status"); - } catch (Throwable e) { - throw new RuntimeException("Could not initialize intrinsics", e); - } - } - }