ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jsr166y/ForkJoinTask.java
(Generate patch)

Comparing jsr166/src/jsr166y/ForkJoinTask.java (file contents):
Revision 1.18 by dl, Sat Jul 25 15:50:57 2009 UTC vs.
Revision 1.27 by dl, Sun Aug 2 11:54:31 2009 UTC

# Line 16 | Line 16 | import java.util.Map;
16   import java.util.WeakHashMap;
17  
18   /**
19 < * Abstract base class for tasks that run within a {@link
20 < * ForkJoinPool}.  A ForkJoinTask is a thread-like entity that is much
19 > * Abstract base class for tasks that run within a {@link ForkJoinPool}.
20 > * A {@code ForkJoinTask} is a thread-like entity that is much
21   * lighter weight than a normal thread.  Huge numbers of tasks and
22   * subtasks may be hosted by a small number of actual threads in a
23   * ForkJoinPool, at the price of some usage limitations.
# Line 25 | Line 25 | import java.util.WeakHashMap;
25   * <p> A "main" ForkJoinTask begins execution when submitted to a
26   * {@link ForkJoinPool}. Once started, it will usually in turn start
27   * other subtasks.  As indicated by the name of this class, many
28 < * programs using ForkJoinTasks employ only methods {@code fork}
29 < * and {@code join}, or derivatives such as
30 < * {@code invokeAll}.  However, this class also provides a number
31 < * of other methods that can come into play in advanced usages, as
32 < * well as extension mechanics that allow support of new forms of
33 < * fork/join processing.
28 > * programs using ForkJoinTasks employ only methods {@code fork} and
29 > * {@code join}, or derivatives such as {@code invokeAll}.  However,
30 > * this class also provides a number of other methods that can come
31 > * into play in advanced usages, as well as extension mechanics that
32 > * allow support of new forms of fork/join processing.
33   *
34   * <p>A ForkJoinTask is a lightweight form of {@link Future}.  The
35   * efficiency of ForkJoinTasks stems from a set of restrictions (that
# Line 77 | Line 76 | import java.util.WeakHashMap;
76   *
77   * <p> The ForkJoinTask class is not usually directly subclassed.
78   * Instead, you subclass one of the abstract classes that support a
79 < * particular style of fork/join processing.  Normally, a concrete
79 > * particular style of fork/join processing, typically {@link
80 > * RecursiveAction} for computations that do not return results, or
81 > * {@link RecursiveTask} for those that do.  Normally, a concrete
82   * ForkJoinTask subclass declares fields comprising its parameters,
83   * established in a constructor, and then defines a {@code compute}
84   * method that somehow uses the control methods supplied by this base
# Line 94 | Line 95 | import java.util.WeakHashMap;
95   * lightweight task scheduling framework, and so cannot be overridden.
96   * Developers creating new basic styles of fork/join processing should
97   * minimally implement {@code protected} methods
98 < * {@code exec}, {@code setRawResult}, and
99 < * {@code getRawResult}, while also introducing an abstract
98 > * {@link #exec}, {@link #setRawResult}, and
99 > * {@link #getRawResult}, while also introducing an abstract
100   * computational method that can be implemented in its subclasses,
101   * possibly relying on other {@code protected} methods provided
102   * by this class.
# Line 107 | Line 108 | import java.util.WeakHashMap;
108   * parallelism cannot improve throughput. If too small, then memory
109   * and internal task maintenance overhead may overwhelm processing.
110   *
111 + * <p>This class provides {@code adapt} methods for {@link
112 + * java.lang.Runnable} and {@link java.util.concurrent.Callable}, that
113 + * may be of use when mixing execution of ForkJoinTasks with other
114 + * kinds of tasks. When all tasks are of this form, consider using a
115 + * pool in {@link ForkJoinPool#setAsyncMode}.
116 + *
117   * <p>ForkJoinTasks are {@code Serializable}, which enables them
118   * to be used in extensions such as remote execution frameworks. It is
119   * in general sensible to serialize tasks only before or after, but
# Line 248 | Line 255 | public abstract class ForkJoinTask<V> im
255          synchronized (this) {
256              try {
257                  while (status >= 0) {
258 <                    long nt = nanos - System.nanoTime() - startTime;
258 >                    long nt = nanos - (System.nanoTime() - startTime);
259                      if (nt <= 0)
260                          break;
261                      wait(nt / 1000000, (int) (nt % 1000000));
# Line 493 | Line 500 | public abstract class ForkJoinTask<V> im
500       * #inForkJoinPool}). Attempts to invoke in other contexts result
501       * in exceptions or errors, possibly including ClassCastException.
502       *
503 <     * @return <code>this</code>, to simplify usage.
503 >     * @return {@code this}, to simplify usage.
504       */
505      public final ForkJoinTask<V> fork() {
506          ((ForkJoinWorkerThread) Thread.currentThread())
# Line 532 | Line 539 | public abstract class ForkJoinTask<V> im
539      }
540  
541      /**
542 <     * Forks both tasks, returning when {@code isDone} holds for
543 <     * both of them or an exception is encountered. This method may be
542 >     * Forks the given tasks, returning when {@code isDone} holds for
543 >     * each task or an exception is encountered. This method may be
544       * invoked only from within ForkJoinTask computations (as may be
545       * determined using method {@link #inForkJoinPool}). Attempts to
546       * invoke in other contexts result in exceptions or errors,
547       * possibly including ClassCastException.
548       *
549 <     * @param t1 one task
550 <     * @param t2 the other task
551 <     * @throws NullPointerException if t1 or t2 are null
552 <     * @throws RuntimeException or Error if either task did so
549 >     * @param t1 the first task
550 >     * @param t2 the second task
551 >     * @throws NullPointerException if any task is null
552 >     * @throws RuntimeException or Error if a task did so
553       */
554      public static void invokeAll(ForkJoinTask<?>t1, ForkJoinTask<?> t2) {
555          t2.fork();
# Line 551 | Line 558 | public abstract class ForkJoinTask<V> im
558      }
559  
560      /**
561 <     * Forks the given tasks, returning when {@code isDone} holds
562 <     * for all of them. If any task encounters an exception, others
563 <     * may be cancelled.  This method may be invoked only from within
561 >     * Forks the given tasks, returning when {@code isDone} holds for
562 >     * each task or an exception is encountered. If any task
563 >     * encounters an exception, others may be, but are not guaranteed
564 >     * to be, cancelled.  This method may be invoked only from within
565       * ForkJoinTask computations (as may be determined using method
566       * {@link #inForkJoinPool}). Attempts to invoke in other contexts
567       * result in exceptions or errors, possibly including
568       * ClassCastException.
569       *
570 <     * @param tasks the array of tasks
570 >     * Overloadings of this method exist for the special cases
571 >     * of one to four arguments.
572 >     *
573 >     * @param tasks the tasks
574       * @throws NullPointerException if tasks or any element are null
575       * @throws RuntimeException or Error if any task did so
576       */
# Line 597 | Line 608 | public abstract class ForkJoinTask<V> im
608      }
609  
610      /**
611 <     * Forks all tasks in the collection, returning when
612 <     * {@code isDone} holds for all of them. If any task
613 <     * encounters an exception, others may be cancelled.  This method
614 <     * may be invoked only from within ForkJoinTask computations (as
615 <     * may be determined using method {@link
616 <     * #inForkJoinPool}). Attempts to invoke in other contexts result
617 <     * in exceptions or errors, possibly including ClassCastException.
611 >     * Forks all tasks in the collection, returning when {@code
612 >     * isDone} holds for each task or an exception is encountered. If
613 >     * any task encounters an exception, others may be, but are not
614 >     * guaranteed to be, cancelled.  This method may be invoked only
615 >     * from within ForkJoinTask computations (as may be determined
616 >     * using method {@link #inForkJoinPool}). Attempts to invoke in
617 >     * other contexts result in exceptions or errors, possibly
618 >     * including ClassCastException.
619       *
620       * @param tasks the collection of tasks
621 +     * @return the tasks argument, to simplify usage
622       * @throws NullPointerException if tasks or any element are null
623       * @throws RuntimeException or Error if any task did so
624       */
625 <    public static void invokeAll(Collection<? extends ForkJoinTask<?>> tasks) {
625 >    public static <T extends ForkJoinTask<?>> Collection<T> invokeAll(Collection<T> tasks) {
626          if (!(tasks instanceof List<?>)) {
627              invokeAll(tasks.toArray(new ForkJoinTask<?>[tasks.size()]));
628 <            return;
628 >            return tasks;
629          }
630          @SuppressWarnings("unchecked")
631          List<? extends ForkJoinTask<?>> ts =
# Line 647 | Line 660 | public abstract class ForkJoinTask<V> im
660          }
661          if (ex != null)
662              rethrowException(ex);
663 +        return tasks;
664      }
665  
666      /**
667 <     * Returns true if the computation performed by this task has
668 <     * completed (or has been cancelled).
667 >     * Returns {@code true} if the computation performed by this task
668 >     * has completed (or has been cancelled).
669       *
670 <     * @return true if this computation has completed
670 >     * @return {@code true} if this computation has completed
671       */
672      public final boolean isDone() {
673          return status < 0;
674      }
675  
676      /**
677 <     * Returns true if this task was cancelled.
677 >     * Returns {@code true} if this task was cancelled.
678       *
679 <     * @return true if this task was cancelled
679 >     * @return {@code true} if this task was cancelled
680       */
681      public final boolean isCancelled() {
682          return (status & COMPLETION_MASK) == CANCELLED;
# Line 671 | Line 685 | public abstract class ForkJoinTask<V> im
685      /**
686       * Asserts that the results of this task's computation will not be
687       * used. If a cancellation occurs before attempting to execute this
688 <     * task, then execution will be suppressed, {@code isCancelled}
689 <     * will report true, and {@code join} will result in a
688 >     * task, execution will be suppressed, {@link #isCancelled}
689 >     * will report true, and {@link #join} will result in a
690       * {@code CancellationException} being thrown. Otherwise, when
691       * cancellation races with completion, there are no guarantees
692 <     * about whether {@code isCancelled} will report true, whether
693 <     * {@code join} will return normally or via an exception, or
694 <     * whether these behaviors will remain consistent upon repeated
692 >     * about whether {@code isCancelled} will report {@code true},
693 >     * whether {@code join} will return normally or via an exception,
694 >     * or whether these behaviors will remain consistent upon repeated
695       * invocation.
696       *
697       * <p>This method may be overridden in subclasses, but if so, must
# Line 687 | Line 701 | public abstract class ForkJoinTask<V> im
701       * <p> This method is designed to be invoked by <em>other</em>
702       * tasks. To terminate the current task, you can just return or
703       * throw an unchecked exception from its computation method, or
704 <     * invoke {@code completeExceptionally}.
704 >     * invoke {@link #completeExceptionally}.
705       *
706       * @param mayInterruptIfRunning this value is ignored in the
707       * default implementation because tasks are not in general
708       * cancelled via interruption
709       *
710 <     * @return true if this task is now cancelled
710 >     * @return {@code true} if this task is now cancelled
711       */
712      public boolean cancel(boolean mayInterruptIfRunning) {
713          setCompletion(CANCELLED);
# Line 701 | Line 715 | public abstract class ForkJoinTask<V> im
715      }
716  
717      /**
718 <     * Returns true if this task threw an exception or was cancelled.
718 >     * Returns {@code true} if this task threw an exception or was cancelled.
719       *
720 <     * @return true if this task threw an exception or was cancelled
720 >     * @return {@code true} if this task threw an exception or was cancelled
721       */
722      public final boolean isCompletedAbnormally() {
723          return (status & COMPLETION_MASK) < NORMAL;
# Line 714 | Line 728 | public abstract class ForkJoinTask<V> im
728       * CancellationException if cancelled, or null if none or if the
729       * method has not yet completed.
730       *
731 <     * @return the exception, or null if none
731 >     * @return the exception, or {@code null} if none
732       */
733      public final Throwable getException() {
734          int s = status & COMPLETION_MASK;
# Line 731 | Line 745 | public abstract class ForkJoinTask<V> im
745       * {@code join} and related operations. This method may be used
746       * to induce exceptions in asynchronous tasks, or to force
747       * completion of tasks that would not otherwise complete.  Its use
748 <     * in other situations is likely to be wrong.  This method is
748 >     * in other situations is discouraged.  This method is
749       * overridable, but overridden versions must invoke {@code super}
750       * implementation to maintain guarantees.
751       *
# Line 751 | Line 765 | public abstract class ForkJoinTask<V> im
765       * operations. This method may be used to provide results for
766       * asynchronous tasks, or to provide alternative handling for
767       * tasks that would not otherwise complete normally. Its use in
768 <     * other situations is likely to be wrong. This method is
768 >     * other situations is discouraged. This method is
769       * overridable, but overridden versions must invoke {@code super}
770       * implementation to maintain guarantees.
771       *
# Line 776 | Line 790 | public abstract class ForkJoinTask<V> im
790  
791      public final V get(long timeout, TimeUnit unit)
792          throws InterruptedException, ExecutionException, TimeoutException {
793 +        long nanos = unit.toNanos(timeout);
794          ForkJoinWorkerThread w = getWorker();
795          if (w == null || status < 0 || !w.unpushTask(this) || !tryQuietlyInvoke())
796 <            awaitDone(w, unit.toNanos(timeout));
796 >            awaitDone(w, nanos);
797          return reportTimedFutureResult();
798      }
799  
# Line 850 | Line 865 | public abstract class ForkJoinTask<V> im
865       * Possibly executes tasks until the pool hosting the current task
866       * {@link ForkJoinPool#isQuiescent}. This method may be of use in
867       * designs in which many tasks are forked, but none are explicitly
868 <     * joined, instead executing them until all are processed.
868 >     * joined, instead executing them until all are processed.  This
869 >     * method may be invoked only from within ForkJoinTask
870 >     * computations (as may be determined using method {@link
871 >     * #inForkJoinPool}). Attempts to invoke in other contexts result
872 >     * in exceptions or errors, possibly including ClassCastException.
873       */
874      public static void helpQuiesce() {
875          ((ForkJoinWorkerThread) Thread.currentThread())
# Line 864 | Line 883 | public abstract class ForkJoinTask<V> im
883       * never been forked, or has been forked, then completed and all
884       * outstanding joins of this task have also completed. Effects
885       * under any other usage conditions are not guaranteed, and are
886 <     * almost surely wrong. This method may be useful when executing
886 >     * discouraged. This method may be useful when executing
887       * pre-constructed trees of subtasks in loops.
888       */
889      public void reinitialize() {
# Line 877 | Line 896 | public abstract class ForkJoinTask<V> im
896       * Returns the pool hosting the current task execution, or null
897       * if this task is executing outside of any ForkJoinPool.
898       *
899 <     * @return the pool, or null if none
899 >     * @see #inForkJoinPool
900 >     * @return the pool, or {@code null} if none
901       */
902      public static ForkJoinPool getPool() {
903          Thread t = Thread.currentThread();
# Line 908 | Line 928 | public abstract class ForkJoinTask<V> im
928       * result in exceptions or errors, possibly including
929       * ClassCastException.
930       *
931 <     * @return true if unforked
931 >     * @return {@code true} if unforked
932       */
933      public boolean tryUnfork() {
934          return ((ForkJoinWorkerThread) Thread.currentThread())
# Line 919 | Line 939 | public abstract class ForkJoinTask<V> im
939       * Returns an estimate of the number of tasks that have been
940       * forked by the current worker thread but not yet executed. This
941       * value may be useful for heuristic decisions about whether to
942 <     * fork other tasks.
943 <     *
942 >     * fork other tasks.  This method may be invoked only from within
943 >     * ForkJoinTask computations (as may be determined using method
944 >     * {@link #inForkJoinPool}). Attempts to invoke in other contexts
945 >     * result in exceptions or errors, possibly including
946 >     * ClassCastException.
947       * @return the number of tasks
948       */
949      public static int getQueuedTaskCount() {
# Line 936 | Line 959 | public abstract class ForkJoinTask<V> im
959       * usages of ForkJoinTasks, at steady state, each worker should
960       * aim to maintain a small constant surplus (for example, 3) of
961       * tasks, and to process computations locally if this threshold is
962 <     * exceeded.
963 <     *
962 >     * exceeded.  This method may be invoked only from within
963 >     * ForkJoinTask computations (as may be determined using method
964 >     * {@link #inForkJoinPool}). Attempts to invoke in other contexts
965 >     * result in exceptions or errors, possibly including
966 >     * ClassCastException.  *
967       * @return the surplus number of tasks, which may be negative
968       */
969      public static int getSurplusQueuedTaskCount() {
# Line 948 | Line 974 | public abstract class ForkJoinTask<V> im
974      // Extension methods
975  
976      /**
977 <     * Returns the result that would be returned by {@code join},
978 <     * even if this task completed abnormally, or null if this task is
979 <     * not known to have been completed.  This method is designed to
980 <     * aid debugging, as well as to support extensions. Its use in any
981 <     * other context is discouraged.
977 >     * Returns the result that would be returned by {@link #join}, even
978 >     * if this task completed abnormally, or {@code null} if this task
979 >     * is not known to have been completed.  This method is designed
980 >     * to aid debugging, as well as to support extensions. Its use in
981 >     * any other context is discouraged.
982       *
983 <     * @return the result, or null if not completed
983 >     * @return the result, or {@code null} if not completed
984       */
985      public abstract V getRawResult();
986  
# Line 973 | Line 999 | public abstract class ForkJoinTask<V> im
999       * called otherwise. The return value controls whether this task
1000       * is considered to be done normally. It may return false in
1001       * asynchronous actions that require explicit invocations of
1002 <     * {@code complete} to become joinable. It may throw exceptions
1002 >     * {@link #complete} to become joinable. It may throw exceptions
1003       * to indicate abnormal exit.
1004       *
1005 <     * @return true if completed normally
1005 >     * @return {@code true} if completed normally
1006       * @throws Error or RuntimeException if encountered during computation
1007       */
1008      protected abstract boolean exec();
1009  
1010      /**
1011 <     * Returns, but does not unschedule or execute, the task queued by
1012 <     * the current thread but not yet executed, if one is
1011 >     * Returns, but does not unschedule or execute, a task queued by
1012 >     * the current thread but not yet executed, if one is immediately
1013       * available. There is no guarantee that this task will actually
1014 <     * be polled or executed next.  This method is designed primarily
1015 <     * to support extensions, and is unlikely to be useful otherwise.
1016 <     * This method may be invoked only from within ForkJoinTask
1017 <     * computations (as may be determined using method {@link
1018 <     * #inForkJoinPool}). Attempts to invoke in other contexts result
1019 <     * in exceptions or errors, possibly including ClassCastException.
1014 >     * be polled or executed next. Conversely, this method may return
1015 >     * null even if a task exists but cannot be accessed without
1016 >     * contention with other threads.  This method is designed
1017 >     * primarily to support extensions, and is unlikely to be useful
1018 >     * otherwise.  This method may be invoked only from within
1019 >     * ForkJoinTask computations (as may be determined using method
1020 >     * {@link #inForkJoinPool}). Attempts to invoke in other contexts
1021 >     * result in exceptions or errors, possibly including
1022 >     * ClassCastException.
1023       *
1024 <     * @return the next task, or null if none are available
1024 >     * @return the next task, or {@code null} if none are available
1025       */
1026      protected static ForkJoinTask<?> peekNextLocalTask() {
1027          return ((ForkJoinWorkerThread) Thread.currentThread())
# Line 1009 | Line 1038 | public abstract class ForkJoinTask<V> im
1038       * contexts result in exceptions or errors, possibly including
1039       * ClassCastException.
1040       *
1041 <     * @return the next task, or null if none are available
1041 >     * @return the next task, or {@code null} if none are available
1042       */
1043      protected static ForkJoinTask<?> pollNextLocalTask() {
1044          return ((ForkJoinWorkerThread) Thread.currentThread())
# Line 1030 | Line 1059 | public abstract class ForkJoinTask<V> im
1059       * result in exceptions or errors, possibly including
1060       * ClassCastException.
1061       *
1062 <     * @return a task, or null if none are available
1062 >     * @return a task, or {@code null} if none are available
1063       */
1064      protected static ForkJoinTask<?> pollTask() {
1065          return ((ForkJoinWorkerThread) Thread.currentThread())
1066              .pollTask();
1067      }
1068  
1069 <    // adaptors
1069 >    /**
1070 >     * Adaptor for Runnables. This implements RunnableFuture
1071 >     * to be compliant with AbstractExecutorService constraints
1072 >     * when used in ForkJoinPool.
1073 >     */
1074 >    static final class AdaptedRunnable<T> extends ForkJoinTask<T>
1075 >        implements RunnableFuture<T> {
1076 >        final Runnable runnable;
1077 >        final T resultOnCompletion;
1078 >        T result;
1079 >        AdaptedRunnable(Runnable runnable, T result) {
1080 >            if (runnable == null) throw new NullPointerException();
1081 >            this.runnable = runnable;
1082 >            this.resultOnCompletion = result;
1083 >        }
1084 >        public T getRawResult() { return result; }
1085 >        public void setRawResult(T v) { result = v; }
1086 >        public boolean exec() {
1087 >            runnable.run();
1088 >            result = resultOnCompletion;
1089 >            return true;
1090 >        }
1091 >        public void run() { invoke(); }
1092 >        private static final long serialVersionUID = 5232453952276885070L;
1093 >    }
1094  
1095      /**
1096 <     * Returns a new ForkJoinTask that performs the <code>run</code>
1096 >     * Adaptor for Callables
1097 >     */
1098 >    static final class AdaptedCallable<T> extends ForkJoinTask<T>
1099 >        implements RunnableFuture<T> {
1100 >        final Callable<? extends T> callable;
1101 >        T result;
1102 >        AdaptedCallable(Callable<? extends T> callable) {
1103 >            if (callable == null) throw new NullPointerException();
1104 >            this.callable = callable;
1105 >        }
1106 >        public T getRawResult() { return result; }
1107 >        public void setRawResult(T v) { result = v; }
1108 >        public boolean exec() {
1109 >            try {
1110 >                result = callable.call();
1111 >                return true;
1112 >            } catch (Error err) {
1113 >                throw err;
1114 >            } catch (RuntimeException rex) {
1115 >                throw rex;
1116 >            } catch (Exception ex) {
1117 >                throw new RuntimeException(ex);
1118 >            }
1119 >        }
1120 >        public void run() { invoke(); }
1121 >        private static final long serialVersionUID = 2838392045355241008L;
1122 >    }
1123 >
1124 >    /**
1125 >     * Returns a new ForkJoinTask that performs the {@code run}
1126       * method of the given Runnable as its action, and returns a null
1127 <     * result upon <code>join</code>.
1127 >     * result upon {@code join}.
1128       *
1129       * @param runnable the runnable action
1130       * @return the task
1131       */
1132 <    public static ForkJoinTask<Void> adapt(Runnable runnable) {
1133 <        return new ForkJoinPool.AdaptedRunnable<Void>(runnable, null);
1132 >    public static ForkJoinTask<?> adapt(Runnable runnable) {
1133 >        return new AdaptedRunnable<Void>(runnable, null);
1134      }
1135  
1136      /**
1137 <     * Returns a new ForkJoinTask that performs the <code>run</code>
1137 >     * Returns a new ForkJoinTask that performs the {@code run}
1138       * method of the given Runnable as its action, and returns the
1139 <     * given result upon <code>join</code>.
1139 >     * given result upon {@code join}.
1140       *
1141       * @param runnable the runnable action
1142       * @param result the result upon completion
1143       * @return the task
1144       */
1145      public static <T> ForkJoinTask<T> adapt(Runnable runnable, T result) {
1146 <        return new ForkJoinPool.AdaptedRunnable<T>(runnable, result);
1146 >        return new AdaptedRunnable<T>(runnable, result);
1147      }
1148  
1149      /**
1150 <     * Returns a new ForkJoinTask that performs the <code>call</code>
1150 >     * Returns a new ForkJoinTask that performs the {@code call}
1151       * method of the given Callable as its action, and returns its
1152 <     * result upon <code>join</code>, translating any checked
1153 <     * exceptions encountered into <code>RuntimeException<code>.
1152 >     * result upon {@code join}, translating any checked
1153 >     * exceptions encountered into {@code RuntimeException}.
1154       *
1155       * @param callable the callable action
1156       * @return the task
1157       */
1158 <    public static <T> ForkJoinTask<T> adapt(Callable<T> callable) {
1159 <        return new ForkJoinPool.AdaptedCallable<T>(callable);
1158 >    public static <T> ForkJoinTask<T> adapt(Callable<? extends T> callable) {
1159 >        return new AdaptedCallable<T>(callable);
1160      }
1161  
1162      // Serialization support
# Line 1085 | Line 1167 | public abstract class ForkJoinTask<V> im
1167       * Save the state to a stream.
1168       *
1169       * @serialData the current run status and the exception thrown
1170 <     * during execution, or null if none
1170 >     * during execution, or {@code null} if none
1171       * @param s the stream
1172       */
1173      private void writeObject(java.io.ObjectOutputStream s)
# Line 1109 | Line 1191 | public abstract class ForkJoinTask<V> im
1191              setDoneExceptionally((Throwable) ex);
1192      }
1193  
1194 <    // Unsafe mechanics for jsr166y 3rd party package.
1194 >    // Unsafe mechanics
1195 >
1196 >    private static final sun.misc.Unsafe UNSAFE = getUnsafe();
1197 >    private static final long statusOffset =
1198 >        objectFieldOffset("status", ForkJoinTask.class);
1199 >
1200 >    private static long objectFieldOffset(String field, Class<?> klazz) {
1201 >        try {
1202 >            return UNSAFE.objectFieldOffset(klazz.getDeclaredField(field));
1203 >        } catch (NoSuchFieldException e) {
1204 >            // Convert Exception to corresponding Error
1205 >            NoSuchFieldError error = new NoSuchFieldError(field);
1206 >            error.initCause(e);
1207 >            throw error;
1208 >        }
1209 >    }
1210 >
1211 >    /**
1212 >     * Returns a sun.misc.Unsafe.  Suitable for use in a 3rd party package.
1213 >     * Replace with a simple call to Unsafe.getUnsafe when integrating
1214 >     * into a jdk.
1215 >     *
1216 >     * @return a sun.misc.Unsafe
1217 >     */
1218      private static sun.misc.Unsafe getUnsafe() {
1219          try {
1220              return sun.misc.Unsafe.getUnsafe();
1221          } catch (SecurityException se) {
1222              try {
1223                  return java.security.AccessController.doPrivileged
1224 <                    (new java.security.PrivilegedExceptionAction<sun.misc.Unsafe>() {
1224 >                    (new java.security
1225 >                     .PrivilegedExceptionAction<sun.misc.Unsafe>() {
1226                          public sun.misc.Unsafe run() throws Exception {
1227 <                            return getUnsafeByReflection();
1227 >                            java.lang.reflect.Field f = sun.misc
1228 >                                .Unsafe.class.getDeclaredField("theUnsafe");
1229 >                            f.setAccessible(true);
1230 >                            return (sun.misc.Unsafe) f.get(null);
1231                          }});
1232              } catch (java.security.PrivilegedActionException e) {
1233                  throw new RuntimeException("Could not initialize intrinsics",
# Line 1126 | Line 1235 | public abstract class ForkJoinTask<V> im
1235              }
1236          }
1237      }
1129
1130    private static sun.misc.Unsafe getUnsafeByReflection()
1131            throws NoSuchFieldException, IllegalAccessException {
1132        java.lang.reflect.Field f =
1133            sun.misc.Unsafe.class.getDeclaredField("theUnsafe");
1134        f.setAccessible(true);
1135        return (sun.misc.Unsafe) f.get(null);
1136    }
1137
1138    private static long fieldOffset(String fieldName, Class<?> klazz) {
1139        try {
1140            return UNSAFE.objectFieldOffset(klazz.getDeclaredField(fieldName));
1141        } catch (NoSuchFieldException e) {
1142            // Convert Exception to Error
1143            NoSuchFieldError error = new NoSuchFieldError(fieldName);
1144            error.initCause(e);
1145            throw error;
1146        }
1147    }
1148
1149    private static final sun.misc.Unsafe UNSAFE = getUnsafe();
1150    static final long statusOffset =
1151        fieldOffset("status", ForkJoinTask.class);
1152
1238   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines