ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jsr166y/RecursiveAction.java
Revision: 1.12
Committed: Tue Aug 4 22:47:08 2009 UTC (14 years, 9 months ago) by dl
Branch: MAIN
Changes since 1.11: +1 -1 lines
Log Message:
Doc fixes

File Contents

# Content
1 /*
2 * Written by Doug Lea with assistance from members of JCP JSR-166
3 * Expert Group and released to the public domain, as explained at
4 * http://creativecommons.org/licenses/publicdomain
5 */
6
7 package jsr166y;
8
9 /**
10 * A recursive resultless {@link ForkJoinTask}. This class
11 * establishes conventions to parameterize resultless actions as
12 * {@code Void} {@code ForkJoinTask}s. Because {@code null} is the
13 * only valid value of type {@code Void}, methods such as join always
14 * return {@code null} upon completion.
15 *
16 * <p><b>Sample Usages.</b> Here is a sketch of a ForkJoin sort that
17 * sorts a given {@code long[]} array:
18 *
19 * <pre> {@code
20 * class SortTask extends RecursiveAction {
21 * final long[] array; final int lo; final int hi;
22 * SortTask(long[] array, int lo, int hi) {
23 * this.array = array; this.lo = lo; this.hi = hi;
24 * }
25 * protected void compute() {
26 * if (hi - lo < THRESHOLD)
27 * sequentiallySort(array, lo, hi);
28 * else {
29 * int mid = (lo + hi) >>> 1;
30 * invokeAll(new SortTask(array, lo, mid),
31 * new SortTask(array, mid, hi));
32 * merge(array, lo, hi);
33 * }
34 * }
35 * }}</pre>
36 *
37 * You could then sort {@code anArray} by creating {@code new
38 * SortTask(anArray, 0, anArray.length-1) } and invoking it in a
39 * ForkJoinPool. As a more concrete simple example, the following
40 * task increments each element of an array:
41 * <pre> {@code
42 * class IncrementTask extends RecursiveAction {
43 * final long[] array; final int lo; final int hi;
44 * IncrementTask(long[] array, int lo, int hi) {
45 * this.array = array; this.lo = lo; this.hi = hi;
46 * }
47 * protected void compute() {
48 * if (hi - lo < THRESHOLD) {
49 * for (int i = lo; i < hi; ++i)
50 * array[i]++;
51 * }
52 * else {
53 * int mid = (lo + hi) >>> 1;
54 * invokeAll(new IncrementTask(array, lo, mid),
55 * new IncrementTask(array, mid, hi));
56 * }
57 * }
58 * }}</pre>
59 *
60 * <p>The following example illustrates some refinements and idioms
61 * that may lead to better performance: RecursiveActions need not be
62 * fully recursive, so long as they maintain the basic
63 * divide-and-conquer approach. Here is a class that sums the squares
64 * of each element of a double array, by subdividing out only the
65 * right-hand-sides of repeated divisions by two, and keeping track of
66 * them with a chain of {@code next} references. It uses a dynamic
67 * threshold based on method {@code getSurplusQueuedTaskCount}, but
68 * counterbalances potential excess partitioning by directly
69 * performing leaf actions on unstolen tasks rather than further
70 * subdividing.
71 *
72 * <pre> {@code
73 * double sumOfSquares(ForkJoinPool pool, double[] array) {
74 * int n = array.length;
75 * int seqSize = 1 + n / (8 * pool.getParallelism());
76 * Applyer a = new Applyer(array, 0, n, seqSize, null);
77 * pool.invoke(a);
78 * return a.result;
79 * }
80 *
81 * class Applyer extends RecursiveAction {
82 * final double[] array;
83 * final int lo, hi, seqSize;
84 * double result;
85 * Applyer next; // keeps track of right-hand-side tasks
86 * Applyer(double[] array, int lo, int hi, int seqSize, Applyer next) {
87 * this.array = array; this.lo = lo; this.hi = hi;
88 * this.seqSize = seqSize; this.next = next;
89 * }
90 *
91 * double atLeaf(int l, int r) {
92 * double sum = 0;
93 * for (int i = l; i < h; ++i) // perform leftmost base step
94 * sum += array[i] * array[i];
95 * return sum;
96 * }
97 *
98 * protected void compute() {
99 * int l = lo;
100 * int h = hi;
101 * Applyer right = null;
102 * while (h - l > 1 && getSurplusQueuedTaskCount() <= 3) {
103 * int mid = (l + h) >>> 1;
104 * right = new Applyer(array, mid, h, seqSize, right);
105 * right.fork();
106 * h = mid;
107 * }
108 * double sum = atLeaf(l, h);
109 * while (right != null) {
110 * if (right.tryUnfork()) // directly calculate if not stolen
111 * sum += right.atLeaf(right.lo, right.hi);
112 * else {
113 * right.helpJoin();
114 * sum += right.result;
115 * }
116 * right = right.next;
117 * }
118 * result = sum;
119 * }
120 * }}</pre>
121 *
122 * @since 1.7
123 * @author Doug Lea
124 */
125 public abstract class RecursiveAction extends ForkJoinTask<Void> {
126 private static final long serialVersionUID = 5232453952276485070L;
127
128 /**
129 * The main computation performed by this task.
130 */
131 protected abstract void compute();
132
133 /**
134 * Always returns null.
135 */
136 public final Void getRawResult() { return null; }
137
138 /**
139 * Requires null completion value.
140 */
141 protected final void setRawResult(Void mustBeNull) { }
142
143 /**
144 * Implements execution conventions for RecursiveActions.
145 */
146 protected final boolean exec() {
147 compute();
148 return true;
149 }
150
151 }