ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/ArrayPrefixHelpers.java
Revision: 1.12
Committed: Thu Oct 10 16:53:08 2019 UTC (4 years, 6 months ago) by jsr166
Branch: MAIN
Changes since 1.11: +8 -1 lines
Log Message:
8231202: Suppress warnings on non-serializable non-transient instance fields in serializable classes

File Contents

# User Rev Content
1 dl 1.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/publicdomain/zero/1.0/
5     */
6    
7     package java.util;
8 jsr166 1.4
9     import java.util.concurrent.CountedCompleter;
10 jsr166 1.9 import java.util.concurrent.ForkJoinPool;
11 dl 1.1 import java.util.function.BinaryOperator;
12 jsr166 1.4 import java.util.function.DoubleBinaryOperator;
13 dl 1.1 import java.util.function.IntBinaryOperator;
14     import java.util.function.LongBinaryOperator;
15    
16     /**
17     * ForkJoin tasks to perform Arrays.parallelPrefix operations.
18     *
19     * @author Doug Lea
20     * @since 1.8
21     */
22     class ArrayPrefixHelpers {
23 jsr166 1.3 private ArrayPrefixHelpers() {} // non-instantiable
24 dl 1.1
25     /*
26     * Parallel prefix (aka cumulate, scan) task classes
27     * are based loosely on Guy Blelloch's original
28     * algorithm (http://www.cs.cmu.edu/~scandal/alg/scan.html):
29     * Keep dividing by two to threshold segment size, and then:
30     * Pass 1: Create tree of partial sums for each segment
31     * Pass 2: For each segment, cumulate with offset of left sibling
32     *
33     * This version improves performance within FJ framework mainly by
34     * allowing the second pass of ready left-hand sides to proceed
35     * even if some right-hand side first passes are still executing.
36     * It also combines first and second pass for leftmost segment,
37     * and skips the first pass for rightmost segment (whose result is
38     * not needed for second pass). It similarly manages to avoid
39     * requiring that users supply an identity basis for accumulations
40     * by tracking those segments/subtasks for which the first
41     * existing element is used as base.
42     *
43     * Managing this relies on ORing some bits in the pendingCount for
44     * phases/states: CUMULATE, SUMMED, and FINISHED. CUMULATE is the
45     * main phase bit. When false, segments compute only their sum.
46     * When true, they cumulate array elements. CUMULATE is set at
47     * root at beginning of second pass and then propagated down. But
48     * it may also be set earlier for subtrees with lo==0 (the left
49     * spine of tree). SUMMED is a one bit join count. For leafs, it
50     * is set when summed. For internal nodes, it becomes true when
51     * one child is summed. When the second child finishes summing,
52     * we then moves up tree to trigger the cumulate phase. FINISHED
53     * is also a one bit join count. For leafs, it is set when
54     * cumulated. For internal nodes, it becomes true when one child
55     * is cumulated. When the second child finishes cumulating, it
56     * then moves up tree, completing at the root.
57     *
58     * To better exploit locality and reduce overhead, the compute
59     * method loops starting with the current task, moving if possible
60     * to one of its subtasks rather than forking.
61     *
62     * As usual for this sort of utility, there are 4 versions, that
63     * are simple copy/paste/adapt variants of each other. (The
64     * double and int versions differ from long version solely by
65     * replacing "long" (with case-matching)).
66     */
67    
68     // see above
69     static final int CUMULATE = 1;
70     static final int SUMMED = 2;
71     static final int FINISHED = 4;
72    
73     /** The smallest subtask array partition size to use as threshold */
74     static final int MIN_PARTITION = 16;
75    
76 jsr166 1.8 static final class CumulateTask<T> extends CountedCompleter<Void> {
77 jsr166 1.12 @SuppressWarnings("serial") // Not statically typed as Serializable
78 dl 1.1 final T[] array;
79     final BinaryOperator<T> function;
80     CumulateTask<T> left, right;
81 jsr166 1.12 @SuppressWarnings("serial") // Not statically typed as Serializable
82     T in;
83     @SuppressWarnings("serial") // Not statically typed as Serializable
84     T out;
85 dl 1.1 final int lo, hi, origin, fence, threshold;
86    
87 jsr166 1.9 /** Root task constructor */
88     public CumulateTask(CumulateTask<T> parent,
89     BinaryOperator<T> function,
90     T[] array, int lo, int hi) {
91     super(parent);
92     this.function = function; this.array = array;
93     this.lo = this.origin = lo; this.hi = this.fence = hi;
94     int p;
95     this.threshold =
96     (p = (hi - lo) / (ForkJoinPool.getCommonPoolParallelism() << 3))
97     <= MIN_PARTITION ? MIN_PARTITION : p;
98     }
99    
100     /** Subtask constructor */
101 dl 1.1 CumulateTask(CumulateTask<T> parent, BinaryOperator<T> function,
102     T[] array, int origin, int fence, int threshold,
103     int lo, int hi) {
104     super(parent);
105     this.function = function; this.array = array;
106     this.origin = origin; this.fence = fence;
107     this.threshold = threshold;
108     this.lo = lo; this.hi = hi;
109     }
110    
111     public final void compute() {
112     final BinaryOperator<T> fn;
113     final T[] a;
114     if ((fn = this.function) == null || (a = this.array) == null)
115     throw new NullPointerException(); // hoist checks
116     int th = threshold, org = origin, fnc = fence, l, h;
117     CumulateTask<T> t = this;
118     outer: while ((l = t.lo) >= 0 && (h = t.hi) <= a.length) {
119     if (h - l > th) {
120     CumulateTask<T> lt = t.left, rt = t.right, f;
121     if (lt == null) { // first pass
122     int mid = (l + h) >>> 1;
123     f = rt = t.right =
124     new CumulateTask<T>(t, fn, a, org, fnc, th, mid, h);
125 jsr166 1.10 t = lt = t.left =
126 dl 1.1 new CumulateTask<T>(t, fn, a, org, fnc, th, l, mid);
127     }
128     else { // possibly refork
129     T pin = t.in;
130     lt.in = pin;
131     f = t = null;
132     if (rt != null) {
133     T lout = lt.out;
134     rt.in = (l == org ? lout :
135     fn.apply(pin, lout));
136     for (int c;;) {
137     if (((c = rt.getPendingCount()) & CUMULATE) != 0)
138     break;
139     if (rt.compareAndSetPendingCount(c, c|CUMULATE)){
140     t = rt;
141     break;
142     }
143     }
144     }
145     for (int c;;) {
146     if (((c = lt.getPendingCount()) & CUMULATE) != 0)
147     break;
148     if (lt.compareAndSetPendingCount(c, c|CUMULATE)) {
149     if (t != null)
150     f = t;
151     t = lt;
152     break;
153     }
154     }
155     if (t == null)
156     break;
157     }
158     if (f != null)
159     f.fork();
160     }
161     else {
162     int state; // Transition to sum, cumulate, or both
163     for (int b;;) {
164     if (((b = t.getPendingCount()) & FINISHED) != 0)
165     break outer; // already done
166     state = ((b & CUMULATE) != 0 ? FINISHED :
167     (l > org) ? SUMMED : (SUMMED|FINISHED));
168     if (t.compareAndSetPendingCount(b, b|state))
169     break;
170     }
171    
172     T sum;
173     if (state != SUMMED) {
174     int first;
175     if (l == org) { // leftmost; no in
176     sum = a[org];
177     first = org + 1;
178     }
179     else {
180     sum = t.in;
181     first = l;
182     }
183     for (int i = first; i < h; ++i) // cumulate
184     a[i] = sum = fn.apply(sum, a[i]);
185     }
186     else if (h < fnc) { // skip rightmost
187     sum = a[l];
188     for (int i = l + 1; i < h; ++i) // sum only
189     sum = fn.apply(sum, a[i]);
190     }
191     else
192     sum = t.in;
193     t.out = sum;
194     for (CumulateTask<T> par;;) { // propagate
195 jsr166 1.2 @SuppressWarnings("unchecked") CumulateTask<T> partmp
196     = (CumulateTask<T>)t.getCompleter();
197     if ((par = partmp) == null) {
198 dl 1.1 if ((state & FINISHED) != 0) // enable join
199     t.quietlyComplete();
200     break outer;
201     }
202     int b = par.getPendingCount();
203     if ((b & state & FINISHED) != 0)
204     t = par; // both done
205     else if ((b & state & SUMMED) != 0) { // both summed
206     int nextState; CumulateTask<T> lt, rt;
207     if ((lt = par.left) != null &&
208     (rt = par.right) != null) {
209     T lout = lt.out;
210     par.out = (rt.hi == fnc ? lout :
211     fn.apply(lout, rt.out));
212     }
213     int refork = (((b & CUMULATE) == 0 &&
214     par.lo == org) ? CUMULATE : 0);
215     if ((nextState = b|state|refork) == b ||
216     par.compareAndSetPendingCount(b, nextState)) {
217     state = SUMMED; // drop finished
218     t = par;
219     if (refork != 0)
220     par.fork();
221     }
222     }
223     else if (par.compareAndSetPendingCount(b, b|state))
224     break outer; // sib not ready
225     }
226     }
227     }
228     }
229 jsr166 1.11 // OPENJDK @java.io.Serial
230 dl 1.1 private static final long serialVersionUID = 5293554502939613543L;
231     }
232    
233 jsr166 1.8 static final class LongCumulateTask extends CountedCompleter<Void> {
234 dl 1.1 final long[] array;
235 jsr166 1.12 @SuppressWarnings("serial") // Not statically typed as Serializable
236 dl 1.1 final LongBinaryOperator function;
237     LongCumulateTask left, right;
238     long in, out;
239     final int lo, hi, origin, fence, threshold;
240    
241 jsr166 1.9 /** Root task constructor */
242     public LongCumulateTask(LongCumulateTask parent,
243     LongBinaryOperator function,
244     long[] array, int lo, int hi) {
245     super(parent);
246     this.function = function; this.array = array;
247     this.lo = this.origin = lo; this.hi = this.fence = hi;
248     int p;
249     this.threshold =
250     (p = (hi - lo) / (ForkJoinPool.getCommonPoolParallelism() << 3))
251     <= MIN_PARTITION ? MIN_PARTITION : p;
252     }
253    
254     /** Subtask constructor */
255 dl 1.1 LongCumulateTask(LongCumulateTask parent, LongBinaryOperator function,
256     long[] array, int origin, int fence, int threshold,
257     int lo, int hi) {
258     super(parent);
259     this.function = function; this.array = array;
260     this.origin = origin; this.fence = fence;
261     this.threshold = threshold;
262     this.lo = lo; this.hi = hi;
263     }
264    
265     public final void compute() {
266     final LongBinaryOperator fn;
267     final long[] a;
268     if ((fn = this.function) == null || (a = this.array) == null)
269     throw new NullPointerException(); // hoist checks
270     int th = threshold, org = origin, fnc = fence, l, h;
271     LongCumulateTask t = this;
272     outer: while ((l = t.lo) >= 0 && (h = t.hi) <= a.length) {
273     if (h - l > th) {
274     LongCumulateTask lt = t.left, rt = t.right, f;
275     if (lt == null) { // first pass
276     int mid = (l + h) >>> 1;
277     f = rt = t.right =
278     new LongCumulateTask(t, fn, a, org, fnc, th, mid, h);
279 jsr166 1.10 t = lt = t.left =
280 dl 1.1 new LongCumulateTask(t, fn, a, org, fnc, th, l, mid);
281     }
282     else { // possibly refork
283     long pin = t.in;
284     lt.in = pin;
285     f = t = null;
286     if (rt != null) {
287     long lout = lt.out;
288     rt.in = (l == org ? lout :
289     fn.applyAsLong(pin, lout));
290     for (int c;;) {
291     if (((c = rt.getPendingCount()) & CUMULATE) != 0)
292     break;
293     if (rt.compareAndSetPendingCount(c, c|CUMULATE)){
294     t = rt;
295     break;
296     }
297     }
298     }
299     for (int c;;) {
300     if (((c = lt.getPendingCount()) & CUMULATE) != 0)
301     break;
302     if (lt.compareAndSetPendingCount(c, c|CUMULATE)) {
303     if (t != null)
304     f = t;
305     t = lt;
306     break;
307     }
308     }
309     if (t == null)
310     break;
311     }
312     if (f != null)
313     f.fork();
314     }
315     else {
316     int state; // Transition to sum, cumulate, or both
317     for (int b;;) {
318     if (((b = t.getPendingCount()) & FINISHED) != 0)
319     break outer; // already done
320     state = ((b & CUMULATE) != 0 ? FINISHED :
321     (l > org) ? SUMMED : (SUMMED|FINISHED));
322     if (t.compareAndSetPendingCount(b, b|state))
323     break;
324     }
325    
326     long sum;
327     if (state != SUMMED) {
328     int first;
329     if (l == org) { // leftmost; no in
330     sum = a[org];
331     first = org + 1;
332     }
333     else {
334     sum = t.in;
335     first = l;
336     }
337     for (int i = first; i < h; ++i) // cumulate
338     a[i] = sum = fn.applyAsLong(sum, a[i]);
339     }
340     else if (h < fnc) { // skip rightmost
341     sum = a[l];
342     for (int i = l + 1; i < h; ++i) // sum only
343     sum = fn.applyAsLong(sum, a[i]);
344     }
345     else
346     sum = t.in;
347     t.out = sum;
348     for (LongCumulateTask par;;) { // propagate
349     if ((par = (LongCumulateTask)t.getCompleter()) == null) {
350     if ((state & FINISHED) != 0) // enable join
351     t.quietlyComplete();
352     break outer;
353     }
354     int b = par.getPendingCount();
355     if ((b & state & FINISHED) != 0)
356     t = par; // both done
357     else if ((b & state & SUMMED) != 0) { // both summed
358     int nextState; LongCumulateTask lt, rt;
359     if ((lt = par.left) != null &&
360     (rt = par.right) != null) {
361     long lout = lt.out;
362     par.out = (rt.hi == fnc ? lout :
363     fn.applyAsLong(lout, rt.out));
364     }
365     int refork = (((b & CUMULATE) == 0 &&
366     par.lo == org) ? CUMULATE : 0);
367     if ((nextState = b|state|refork) == b ||
368     par.compareAndSetPendingCount(b, nextState)) {
369     state = SUMMED; // drop finished
370     t = par;
371     if (refork != 0)
372     par.fork();
373     }
374     }
375     else if (par.compareAndSetPendingCount(b, b|state))
376     break outer; // sib not ready
377     }
378     }
379     }
380     }
381 jsr166 1.11 // OPENJDK @java.io.Serial
382 dl 1.1 private static final long serialVersionUID = -5074099945909284273L;
383     }
384    
385 jsr166 1.8 static final class DoubleCumulateTask extends CountedCompleter<Void> {
386 dl 1.1 final double[] array;
387 jsr166 1.12 @SuppressWarnings("serial") // Not statically typed as Serializable
388 dl 1.1 final DoubleBinaryOperator function;
389     DoubleCumulateTask left, right;
390     double in, out;
391     final int lo, hi, origin, fence, threshold;
392    
393 jsr166 1.9 /** Root task constructor */
394     public DoubleCumulateTask(DoubleCumulateTask parent,
395     DoubleBinaryOperator function,
396     double[] array, int lo, int hi) {
397     super(parent);
398     this.function = function; this.array = array;
399     this.lo = this.origin = lo; this.hi = this.fence = hi;
400     int p;
401     this.threshold =
402     (p = (hi - lo) / (ForkJoinPool.getCommonPoolParallelism() << 3))
403     <= MIN_PARTITION ? MIN_PARTITION : p;
404     }
405    
406     /** Subtask constructor */
407 dl 1.1 DoubleCumulateTask(DoubleCumulateTask parent, DoubleBinaryOperator function,
408 jsr166 1.5 double[] array, int origin, int fence, int threshold,
409     int lo, int hi) {
410 dl 1.1 super(parent);
411     this.function = function; this.array = array;
412     this.origin = origin; this.fence = fence;
413     this.threshold = threshold;
414     this.lo = lo; this.hi = hi;
415     }
416    
417     public final void compute() {
418     final DoubleBinaryOperator fn;
419     final double[] a;
420     if ((fn = this.function) == null || (a = this.array) == null)
421     throw new NullPointerException(); // hoist checks
422     int th = threshold, org = origin, fnc = fence, l, h;
423     DoubleCumulateTask t = this;
424     outer: while ((l = t.lo) >= 0 && (h = t.hi) <= a.length) {
425     if (h - l > th) {
426     DoubleCumulateTask lt = t.left, rt = t.right, f;
427     if (lt == null) { // first pass
428     int mid = (l + h) >>> 1;
429     f = rt = t.right =
430     new DoubleCumulateTask(t, fn, a, org, fnc, th, mid, h);
431 jsr166 1.10 t = lt = t.left =
432 dl 1.1 new DoubleCumulateTask(t, fn, a, org, fnc, th, l, mid);
433     }
434     else { // possibly refork
435     double pin = t.in;
436     lt.in = pin;
437     f = t = null;
438     if (rt != null) {
439     double lout = lt.out;
440     rt.in = (l == org ? lout :
441     fn.applyAsDouble(pin, lout));
442     for (int c;;) {
443     if (((c = rt.getPendingCount()) & CUMULATE) != 0)
444     break;
445     if (rt.compareAndSetPendingCount(c, c|CUMULATE)){
446     t = rt;
447     break;
448     }
449     }
450     }
451     for (int c;;) {
452     if (((c = lt.getPendingCount()) & CUMULATE) != 0)
453     break;
454     if (lt.compareAndSetPendingCount(c, c|CUMULATE)) {
455     if (t != null)
456     f = t;
457     t = lt;
458     break;
459     }
460     }
461     if (t == null)
462     break;
463     }
464     if (f != null)
465     f.fork();
466     }
467     else {
468     int state; // Transition to sum, cumulate, or both
469     for (int b;;) {
470     if (((b = t.getPendingCount()) & FINISHED) != 0)
471     break outer; // already done
472     state = ((b & CUMULATE) != 0 ? FINISHED :
473     (l > org) ? SUMMED : (SUMMED|FINISHED));
474     if (t.compareAndSetPendingCount(b, b|state))
475     break;
476     }
477    
478     double sum;
479     if (state != SUMMED) {
480     int first;
481     if (l == org) { // leftmost; no in
482     sum = a[org];
483     first = org + 1;
484     }
485     else {
486     sum = t.in;
487     first = l;
488     }
489     for (int i = first; i < h; ++i) // cumulate
490     a[i] = sum = fn.applyAsDouble(sum, a[i]);
491     }
492     else if (h < fnc) { // skip rightmost
493     sum = a[l];
494     for (int i = l + 1; i < h; ++i) // sum only
495     sum = fn.applyAsDouble(sum, a[i]);
496     }
497     else
498     sum = t.in;
499     t.out = sum;
500     for (DoubleCumulateTask par;;) { // propagate
501     if ((par = (DoubleCumulateTask)t.getCompleter()) == null) {
502     if ((state & FINISHED) != 0) // enable join
503     t.quietlyComplete();
504     break outer;
505     }
506     int b = par.getPendingCount();
507     if ((b & state & FINISHED) != 0)
508     t = par; // both done
509     else if ((b & state & SUMMED) != 0) { // both summed
510     int nextState; DoubleCumulateTask lt, rt;
511     if ((lt = par.left) != null &&
512     (rt = par.right) != null) {
513     double lout = lt.out;
514     par.out = (rt.hi == fnc ? lout :
515     fn.applyAsDouble(lout, rt.out));
516     }
517     int refork = (((b & CUMULATE) == 0 &&
518     par.lo == org) ? CUMULATE : 0);
519     if ((nextState = b|state|refork) == b ||
520     par.compareAndSetPendingCount(b, nextState)) {
521     state = SUMMED; // drop finished
522     t = par;
523     if (refork != 0)
524     par.fork();
525     }
526     }
527     else if (par.compareAndSetPendingCount(b, b|state))
528     break outer; // sib not ready
529     }
530     }
531     }
532     }
533 jsr166 1.11 // OPENJDK @java.io.Serial
534 dl 1.1 private static final long serialVersionUID = -586947823794232033L;
535     }
536    
537 jsr166 1.8 static final class IntCumulateTask extends CountedCompleter<Void> {
538 dl 1.1 final int[] array;
539 jsr166 1.12 @SuppressWarnings("serial") // Not statically typed as Serializable
540 dl 1.1 final IntBinaryOperator function;
541     IntCumulateTask left, right;
542     int in, out;
543     final int lo, hi, origin, fence, threshold;
544    
545 jsr166 1.9 /** Root task constructor */
546     public IntCumulateTask(IntCumulateTask parent,
547     IntBinaryOperator function,
548     int[] array, int lo, int hi) {
549     super(parent);
550     this.function = function; this.array = array;
551     this.lo = this.origin = lo; this.hi = this.fence = hi;
552     int p;
553     this.threshold =
554     (p = (hi - lo) / (ForkJoinPool.getCommonPoolParallelism() << 3))
555     <= MIN_PARTITION ? MIN_PARTITION : p;
556     }
557    
558     /** Subtask constructor */
559 dl 1.1 IntCumulateTask(IntCumulateTask parent, IntBinaryOperator function,
560 jsr166 1.5 int[] array, int origin, int fence, int threshold,
561     int lo, int hi) {
562 dl 1.1 super(parent);
563     this.function = function; this.array = array;
564     this.origin = origin; this.fence = fence;
565     this.threshold = threshold;
566     this.lo = lo; this.hi = hi;
567     }
568    
569     public final void compute() {
570     final IntBinaryOperator fn;
571     final int[] a;
572     if ((fn = this.function) == null || (a = this.array) == null)
573     throw new NullPointerException(); // hoist checks
574     int th = threshold, org = origin, fnc = fence, l, h;
575     IntCumulateTask t = this;
576     outer: while ((l = t.lo) >= 0 && (h = t.hi) <= a.length) {
577     if (h - l > th) {
578     IntCumulateTask lt = t.left, rt = t.right, f;
579     if (lt == null) { // first pass
580     int mid = (l + h) >>> 1;
581     f = rt = t.right =
582     new IntCumulateTask(t, fn, a, org, fnc, th, mid, h);
583 jsr166 1.10 t = lt = t.left =
584 dl 1.1 new IntCumulateTask(t, fn, a, org, fnc, th, l, mid);
585     }
586     else { // possibly refork
587     int pin = t.in;
588     lt.in = pin;
589     f = t = null;
590     if (rt != null) {
591     int lout = lt.out;
592     rt.in = (l == org ? lout :
593     fn.applyAsInt(pin, lout));
594     for (int c;;) {
595     if (((c = rt.getPendingCount()) & CUMULATE) != 0)
596     break;
597     if (rt.compareAndSetPendingCount(c, c|CUMULATE)){
598     t = rt;
599     break;
600     }
601     }
602     }
603     for (int c;;) {
604     if (((c = lt.getPendingCount()) & CUMULATE) != 0)
605     break;
606     if (lt.compareAndSetPendingCount(c, c|CUMULATE)) {
607     if (t != null)
608     f = t;
609     t = lt;
610     break;
611     }
612     }
613     if (t == null)
614     break;
615     }
616     if (f != null)
617     f.fork();
618     }
619     else {
620     int state; // Transition to sum, cumulate, or both
621     for (int b;;) {
622     if (((b = t.getPendingCount()) & FINISHED) != 0)
623     break outer; // already done
624     state = ((b & CUMULATE) != 0 ? FINISHED :
625     (l > org) ? SUMMED : (SUMMED|FINISHED));
626     if (t.compareAndSetPendingCount(b, b|state))
627     break;
628     }
629    
630     int sum;
631     if (state != SUMMED) {
632     int first;
633     if (l == org) { // leftmost; no in
634     sum = a[org];
635     first = org + 1;
636     }
637     else {
638     sum = t.in;
639     first = l;
640     }
641     for (int i = first; i < h; ++i) // cumulate
642     a[i] = sum = fn.applyAsInt(sum, a[i]);
643     }
644     else if (h < fnc) { // skip rightmost
645     sum = a[l];
646     for (int i = l + 1; i < h; ++i) // sum only
647     sum = fn.applyAsInt(sum, a[i]);
648     }
649     else
650     sum = t.in;
651     t.out = sum;
652     for (IntCumulateTask par;;) { // propagate
653     if ((par = (IntCumulateTask)t.getCompleter()) == null) {
654     if ((state & FINISHED) != 0) // enable join
655     t.quietlyComplete();
656     break outer;
657     }
658     int b = par.getPendingCount();
659     if ((b & state & FINISHED) != 0)
660     t = par; // both done
661     else if ((b & state & SUMMED) != 0) { // both summed
662     int nextState; IntCumulateTask lt, rt;
663     if ((lt = par.left) != null &&
664     (rt = par.right) != null) {
665     int lout = lt.out;
666     par.out = (rt.hi == fnc ? lout :
667     fn.applyAsInt(lout, rt.out));
668     }
669     int refork = (((b & CUMULATE) == 0 &&
670     par.lo == org) ? CUMULATE : 0);
671     if ((nextState = b|state|refork) == b ||
672     par.compareAndSetPendingCount(b, nextState)) {
673     state = SUMMED; // drop finished
674     t = par;
675     if (refork != 0)
676     par.fork();
677     }
678     }
679     else if (par.compareAndSetPendingCount(b, b|state))
680     break outer; // sib not ready
681     }
682     }
683     }
684     }
685 jsr166 1.11 // OPENJDK @java.io.Serial
686 dl 1.1 private static final long serialVersionUID = 3731755594596840961L;
687     }
688     }