--- jsr166/src/jsr166y/ForkJoinTask.java 2009/07/24 22:05:22 1.15 +++ jsr166/src/jsr166y/ForkJoinTask.java 2009/07/27 21:41:53 1.24 @@ -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 @@ -22,12 +25,11 @@ import java.lang.reflect.*; *

A "main" ForkJoinTask begins execution when submitted to a * {@link ForkJoinPool}. Once started, it will usually in turn start * other subtasks. As indicated by the name of this class, many - * programs using ForkJoinTasks employ only methods {@code fork} - * and {@code join}, or derivatives such as - * {@code invokeAll}. However, this class also provides a number - * of other methods that can come into play in advanced usages, as - * well as extension mechanics that allow support of new forms of - * fork/join processing. + * programs using ForkJoinTasks employ only methods {@code fork} and + * {@code join}, or derivatives such as {@code invokeAll}. However, + * this class also provides a number of other methods that can come + * into play in advanced usages, as well as extension mechanics that + * allow support of new forms of fork/join processing. * *

A ForkJoinTask is a lightweight form of {@link Future}. The * efficiency of ForkJoinTasks stems from a set of restrictions (that @@ -91,8 +93,8 @@ import java.lang.reflect.*; * lightweight task scheduling framework, and so cannot be overridden. * Developers creating new basic styles of fork/join processing should * minimally implement {@code protected} methods - * {@code exec}, {@code setRawResult}, and - * {@code getRawResult}, while also introducing an abstract + * {@link #exec}, {@link #setRawResult}, and + * {@link #getRawResult}, while also introducing an abstract * computational method that can be implemented in its subclasses, * possibly relying on other {@code protected} methods provided * by this class. @@ -489,10 +491,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 +605,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,22 +647,23 @@ public abstract class ForkJoinTask im } if (ex != null) rethrowException(ex); + return tasks; } /** - * Returns true if the computation performed by this task has - * completed (or has been cancelled). + * Returns {@code true} if the computation performed by this task + * has completed (or has been cancelled). * - * @return true if this computation has completed + * @return {@code true} if this computation has completed */ public final boolean isDone() { return status < 0; } /** - * Returns true if this task was cancelled. + * Returns {@code true} if this task was cancelled. * - * @return true if this task was cancelled + * @return {@code true} if this task was cancelled */ public final boolean isCancelled() { return (status & COMPLETION_MASK) == CANCELLED; @@ -665,13 +672,13 @@ public abstract class ForkJoinTask im /** * Asserts that the results of this task's computation will not be * used. If a cancellation occurs before attempting to execute this - * task, then execution will be suppressed, {@code isCancelled} - * will report true, and {@code join} will result in a + * task, execution will be suppressed, {@link #isCancelled} + * will report true, and {@link #join} will result in a * {@code CancellationException} being thrown. Otherwise, when * cancellation races with completion, there are no guarantees - * about whether {@code isCancelled} will report true, whether - * {@code join} will return normally or via an exception, or - * whether these behaviors will remain consistent upon repeated + * about whether {@code isCancelled} will report {@code true}, + * whether {@code join} will return normally or via an exception, + * or whether these behaviors will remain consistent upon repeated * invocation. * *

This method may be overridden in subclasses, but if so, must @@ -681,13 +688,13 @@ public abstract class ForkJoinTask im *

This method is designed to be invoked by other * tasks. To terminate the current task, you can just return or * throw an unchecked exception from its computation method, or - * invoke {@code completeExceptionally}. + * invoke {@link #completeExceptionally}. * * @param mayInterruptIfRunning this value is ignored in the * default implementation because tasks are not in general * cancelled via interruption * - * @return true if this task is now cancelled + * @return {@code true} if this task is now cancelled */ public boolean cancel(boolean mayInterruptIfRunning) { setCompletion(CANCELLED); @@ -695,9 +702,9 @@ public abstract class ForkJoinTask im } /** - * Returns true if this task threw an exception or was cancelled. + * Returns {@code true} if this task threw an exception or was cancelled. * - * @return true if this task threw an exception or was cancelled + * @return {@code true} if this task threw an exception or was cancelled */ public final boolean isCompletedAbnormally() { return (status & COMPLETION_MASK) < NORMAL; @@ -708,7 +715,7 @@ public abstract class ForkJoinTask im * CancellationException if cancelled, or null if none or if the * method has not yet completed. * - * @return the exception, or null if none + * @return the exception, or {@code null} if none */ public final Throwable getException() { int s = status & COMPLETION_MASK; @@ -871,7 +878,7 @@ public abstract class ForkJoinTask im * Returns the pool hosting the current task execution, or null * if this task is executing outside of any ForkJoinPool. * - * @return the pool, or null if none + * @return the pool, or {@code null} if none */ public static ForkJoinPool getPool() { Thread t = Thread.currentThread(); @@ -902,7 +909,7 @@ public abstract class ForkJoinTask im * result in exceptions or errors, possibly including * ClassCastException. * - * @return true if unforked + * @return {@code true} if unforked */ public boolean tryUnfork() { return ((ForkJoinWorkerThread) Thread.currentThread()) @@ -942,13 +949,13 @@ public abstract class ForkJoinTask im // Extension methods /** - * Returns the result that would be returned by {@code join}, - * even if this task completed abnormally, or null if this task is - * not known to have been completed. This method is designed to - * aid debugging, as well as to support extensions. Its use in any - * other context is discouraged. + * Returns the result that would be returned by {@link #join}, even + * if this task completed abnormally, or {@code null} if this task + * is not known to have been completed. This method is designed + * to aid debugging, as well as to support extensions. Its use in + * any other context is discouraged. * - * @return the result, or null if not completed + * @return the result, or {@code null} if not completed */ public abstract V getRawResult(); @@ -967,10 +974,10 @@ public abstract class ForkJoinTask im * called otherwise. The return value controls whether this task * is considered to be done normally. It may return false in * asynchronous actions that require explicit invocations of - * {@code complete} to become joinable. It may throw exceptions + * {@link #complete} to become joinable. It may throw exceptions * to indicate abnormal exit. * - * @return true if completed normally + * @return {@code true} if completed normally * @throws Error or RuntimeException if encountered during computation */ protected abstract boolean exec(); @@ -986,7 +993,7 @@ public abstract class ForkJoinTask im * #inForkJoinPool}). Attempts to invoke in other contexts result * in exceptions or errors, possibly including ClassCastException. * - * @return the next task, or null if none are available + * @return the next task, or {@code null} if none are available */ protected static ForkJoinTask peekNextLocalTask() { return ((ForkJoinWorkerThread) Thread.currentThread()) @@ -1003,7 +1010,7 @@ public abstract class ForkJoinTask im * contexts result in exceptions or errors, possibly including * ClassCastException. * - * @return the next task, or null if none are available + * @return the next task, or {@code null} if none are available */ protected static ForkJoinTask pollNextLocalTask() { return ((ForkJoinWorkerThread) Thread.currentThread()) @@ -1024,13 +1031,53 @@ public abstract class ForkJoinTask im * result in exceptions or errors, possibly including * ClassCastException. * - * @return a task, or null if none are available + * @return a task, or {@code null} if none are available */ protected static ForkJoinTask pollTask() { return ((ForkJoinWorkerThread) Thread.currentThread()) .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; @@ -1039,7 +1086,7 @@ public abstract class ForkJoinTask im * Save the state to a stream. * * @serialData the current run status and the exception thrown - * during execution, or null if none + * during execution, or {@code null} if none * @param s the stream */ private void writeObject(java.io.ObjectOutputStream s) @@ -1063,46 +1110,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); - } - } - }