1/*
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3 *
4 * This code is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 2 only, as
6 * published by the Free Software Foundation.  Oracle designates this
7 * particular file as subject to the "Classpath" exception as provided
8 * by Oracle in the LICENSE file that accompanied this code.
9 *
10 * This code is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13 * version 2 for more details (a copy is included in the LICENSE file that
14 * accompanied this code).
15 *
16 * You should have received a copy of the GNU General Public License version
17 * 2 along with this work; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21 * or visit www.oracle.com if you need additional information or have any
22 * questions.
23 */
24
25/*
26 * This file is available under and governed by the GNU General Public
27 * License version 2 only, as published by the Free Software Foundation.
28 * However, the following notice accompanied the original version of this
29 * file:
30 *
31 * Written by Doug Lea with assistance from members of JCP JSR-166
32 * Expert Group and released to the public domain, as explained at
33 * http://creativecommons.org/publicdomain/zero/1.0/
34 */
35
36package java.util.concurrent;
37
38/**
39 * A recursive resultless {@link ForkJoinTask}.  This class
40 * establishes conventions to parameterize resultless actions as
41 * {@code Void} {@code ForkJoinTask}s. Because {@code null} is the
42 * only valid value of type {@code Void}, methods such as {@code join}
43 * always return {@code null} upon completion.
44 *
45 * <p><b>Sample Usages.</b> Here is a simple but complete ForkJoin
46 * sort that sorts a given {@code long[]} array:
47 *
48 * <pre> {@code
49 * static class SortTask extends RecursiveAction {
50 *   final long[] array; final int lo, hi;
51 *   SortTask(long[] array, int lo, int hi) {
52 *     this.array = array; this.lo = lo; this.hi = hi;
53 *   }
54 *   SortTask(long[] array) { this(array, 0, array.length); }
55 *   protected void compute() {
56 *     if (hi - lo < THRESHOLD)
57 *       sortSequentially(lo, hi);
58 *     else {
59 *       int mid = (lo + hi) >>> 1;
60 *       invokeAll(new SortTask(array, lo, mid),
61 *                 new SortTask(array, mid, hi));
62 *       merge(lo, mid, hi);
63 *     }
64 *   }
65 *   // implementation details follow:
66 *   static final int THRESHOLD = 1000;
67 *   void sortSequentially(int lo, int hi) {
68 *     Arrays.sort(array, lo, hi);
69 *   }
70 *   void merge(int lo, int mid, int hi) {
71 *     long[] buf = Arrays.copyOfRange(array, lo, mid);
72 *     for (int i = 0, j = lo, k = mid; i < buf.length; j++)
73 *       array[j] = (k == hi || buf[i] < array[k]) ?
74 *         buf[i++] : array[k++];
75 *   }
76 * }}</pre>
77 *
78 * You could then sort {@code anArray} by creating {@code new
79 * SortTask(anArray)} and invoking it in a ForkJoinPool.  As a more
80 * concrete simple example, the following task increments each element
81 * of an array:
82 * <pre> {@code
83 * class IncrementTask extends RecursiveAction {
84 *   final long[] array; final int lo, hi;
85 *   IncrementTask(long[] array, int lo, int hi) {
86 *     this.array = array; this.lo = lo; this.hi = hi;
87 *   }
88 *   protected void compute() {
89 *     if (hi - lo < THRESHOLD) {
90 *       for (int i = lo; i < hi; ++i)
91 *         array[i]++;
92 *     }
93 *     else {
94 *       int mid = (lo + hi) >>> 1;
95 *       invokeAll(new IncrementTask(array, lo, mid),
96 *                 new IncrementTask(array, mid, hi));
97 *     }
98 *   }
99 * }}</pre>
100 *
101 * <p>The following example illustrates some refinements and idioms
102 * that may lead to better performance: RecursiveActions need not be
103 * fully recursive, so long as they maintain the basic
104 * divide-and-conquer approach. Here is a class that sums the squares
105 * of each element of a double array, by subdividing out only the
106 * right-hand-sides of repeated divisions by two, and keeping track of
107 * them with a chain of {@code next} references. It uses a dynamic
108 * threshold based on method {@code getSurplusQueuedTaskCount}, but
109 * counterbalances potential excess partitioning by directly
110 * performing leaf actions on unstolen tasks rather than further
111 * subdividing.
112 *
113 * <pre> {@code
114 * double sumOfSquares(ForkJoinPool pool, double[] array) {
115 *   int n = array.length;
116 *   Applyer a = new Applyer(array, 0, n, null);
117 *   pool.invoke(a);
118 *   return a.result;
119 * }
120 *
121 * class Applyer extends RecursiveAction {
122 *   final double[] array;
123 *   final int lo, hi;
124 *   double result;
125 *   Applyer next; // keeps track of right-hand-side tasks
126 *   Applyer(double[] array, int lo, int hi, Applyer next) {
127 *     this.array = array; this.lo = lo; this.hi = hi;
128 *     this.next = next;
129 *   }
130 *
131 *   double atLeaf(int l, int h) {
132 *     double sum = 0;
133 *     for (int i = l; i < h; ++i) // perform leftmost base step
134 *       sum += array[i] * array[i];
135 *     return sum;
136 *   }
137 *
138 *   protected void compute() {
139 *     int l = lo;
140 *     int h = hi;
141 *     Applyer right = null;
142 *     while (h - l > 1 && getSurplusQueuedTaskCount() <= 3) {
143 *       int mid = (l + h) >>> 1;
144 *       right = new Applyer(array, mid, h, right);
145 *       right.fork();
146 *       h = mid;
147 *     }
148 *     double sum = atLeaf(l, h);
149 *     while (right != null) {
150 *       if (right.tryUnfork()) // directly calculate if not stolen
151 *         sum += right.atLeaf(right.lo, right.hi);
152 *       else {
153 *         right.join();
154 *         sum += right.result;
155 *       }
156 *       right = right.next;
157 *     }
158 *     result = sum;
159 *   }
160 * }}</pre>
161 *
162 * @since 1.7
163 * @author Doug Lea
164 */
165public abstract class RecursiveAction extends ForkJoinTask<Void> {
166    private static final long serialVersionUID = 5232453952276485070L;
167
168    /**
169     * The main computation performed by this task.
170     */
171    protected abstract void compute();
172
173    /**
174     * Always returns {@code null}.
175     *
176     * @return {@code null} always
177     */
178    public final Void getRawResult() { return null; }
179
180    /**
181     * Requires null completion value.
182     */
183    protected final void setRawResult(Void mustBeNull) { }
184
185    /**
186     * Implements execution conventions for RecursiveActions.
187     */
188    protected final boolean exec() {
189        compute();
190        return true;
191    }
192
193}
194