ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/ArrayPrefixHelpers.java
Revision: 1.13
Committed: Thu Oct 10 16:58:35 2019 UTC (4 years, 6 months ago) by jsr166
Branch: MAIN
CVS Tags: HEAD
Changes since 1.12: +1 -0 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 jsr166 1.13 @SuppressWarnings("serial") // Not statically typed as Serializable
80 dl 1.1 final BinaryOperator<T> function;
81     CumulateTask<T> left, right;
82 jsr166 1.12 @SuppressWarnings("serial") // Not statically typed as Serializable
83     T in;
84     @SuppressWarnings("serial") // Not statically typed as Serializable
85     T out;
86 dl 1.1 final int lo, hi, origin, fence, threshold;
87    
88 jsr166 1.9 /** Root task constructor */
89     public CumulateTask(CumulateTask<T> parent,
90     BinaryOperator<T> function,
91     T[] array, int lo, int hi) {
92     super(parent);
93     this.function = function; this.array = array;
94     this.lo = this.origin = lo; this.hi = this.fence = hi;
95     int p;
96     this.threshold =
97     (p = (hi - lo) / (ForkJoinPool.getCommonPoolParallelism() << 3))
98     <= MIN_PARTITION ? MIN_PARTITION : p;
99     }
100    
101     /** Subtask constructor */
102 dl 1.1 CumulateTask(CumulateTask<T> parent, BinaryOperator<T> function,
103     T[] array, int origin, int fence, int threshold,
104     int lo, int hi) {
105     super(parent);
106     this.function = function; this.array = array;
107     this.origin = origin; this.fence = fence;
108     this.threshold = threshold;
109     this.lo = lo; this.hi = hi;
110     }
111    
112     public final void compute() {
113     final BinaryOperator<T> fn;
114     final T[] a;
115     if ((fn = this.function) == null || (a = this.array) == null)
116     throw new NullPointerException(); // hoist checks
117     int th = threshold, org = origin, fnc = fence, l, h;
118     CumulateTask<T> t = this;
119     outer: while ((l = t.lo) >= 0 && (h = t.hi) <= a.length) {
120     if (h - l > th) {
121     CumulateTask<T> lt = t.left, rt = t.right, f;
122     if (lt == null) { // first pass
123     int mid = (l + h) >>> 1;
124     f = rt = t.right =
125     new CumulateTask<T>(t, fn, a, org, fnc, th, mid, h);
126 jsr166 1.10 t = lt = t.left =
127 dl 1.1 new CumulateTask<T>(t, fn, a, org, fnc, th, l, mid);
128     }
129     else { // possibly refork
130     T pin = t.in;
131     lt.in = pin;
132     f = t = null;
133     if (rt != null) {
134     T lout = lt.out;
135     rt.in = (l == org ? lout :
136     fn.apply(pin, lout));
137     for (int c;;) {
138     if (((c = rt.getPendingCount()) & CUMULATE) != 0)
139     break;
140     if (rt.compareAndSetPendingCount(c, c|CUMULATE)){
141     t = rt;
142     break;
143     }
144     }
145     }
146     for (int c;;) {
147     if (((c = lt.getPendingCount()) & CUMULATE) != 0)
148     break;
149     if (lt.compareAndSetPendingCount(c, c|CUMULATE)) {
150     if (t != null)
151     f = t;
152     t = lt;
153     break;
154     }
155     }
156     if (t == null)
157     break;
158     }
159     if (f != null)
160     f.fork();
161     }
162     else {
163     int state; // Transition to sum, cumulate, or both
164     for (int b;;) {
165     if (((b = t.getPendingCount()) & FINISHED) != 0)
166     break outer; // already done
167     state = ((b & CUMULATE) != 0 ? FINISHED :
168     (l > org) ? SUMMED : (SUMMED|FINISHED));
169     if (t.compareAndSetPendingCount(b, b|state))
170     break;
171     }
172    
173     T sum;
174     if (state != SUMMED) {
175     int first;
176     if (l == org) { // leftmost; no in
177     sum = a[org];
178     first = org + 1;
179     }
180     else {
181     sum = t.in;
182     first = l;
183     }
184     for (int i = first; i < h; ++i) // cumulate
185     a[i] = sum = fn.apply(sum, a[i]);
186     }
187     else if (h < fnc) { // skip rightmost
188     sum = a[l];
189     for (int i = l + 1; i < h; ++i) // sum only
190     sum = fn.apply(sum, a[i]);
191     }
192     else
193     sum = t.in;
194     t.out = sum;
195     for (CumulateTask<T> par;;) { // propagate
196 jsr166 1.2 @SuppressWarnings("unchecked") CumulateTask<T> partmp
197     = (CumulateTask<T>)t.getCompleter();
198     if ((par = partmp) == null) {
199 dl 1.1 if ((state & FINISHED) != 0) // enable join
200     t.quietlyComplete();
201     break outer;
202     }
203     int b = par.getPendingCount();
204     if ((b & state & FINISHED) != 0)
205     t = par; // both done
206     else if ((b & state & SUMMED) != 0) { // both summed
207     int nextState; CumulateTask<T> lt, rt;
208     if ((lt = par.left) != null &&
209     (rt = par.right) != null) {
210     T lout = lt.out;
211     par.out = (rt.hi == fnc ? lout :
212     fn.apply(lout, rt.out));
213     }
214     int refork = (((b & CUMULATE) == 0 &&
215     par.lo == org) ? CUMULATE : 0);
216     if ((nextState = b|state|refork) == b ||
217     par.compareAndSetPendingCount(b, nextState)) {
218     state = SUMMED; // drop finished
219     t = par;
220     if (refork != 0)
221     par.fork();
222     }
223     }
224     else if (par.compareAndSetPendingCount(b, b|state))
225     break outer; // sib not ready
226     }
227     }
228     }
229     }
230 jsr166 1.11 // OPENJDK @java.io.Serial
231 dl 1.1 private static final long serialVersionUID = 5293554502939613543L;
232     }
233    
234 jsr166 1.8 static final class LongCumulateTask extends CountedCompleter<Void> {
235 dl 1.1 final long[] array;
236 jsr166 1.12 @SuppressWarnings("serial") // Not statically typed as Serializable
237 dl 1.1 final LongBinaryOperator function;
238     LongCumulateTask left, right;
239     long in, out;
240     final int lo, hi, origin, fence, threshold;
241    
242 jsr166 1.9 /** Root task constructor */
243     public LongCumulateTask(LongCumulateTask parent,
244     LongBinaryOperator function,
245     long[] array, int lo, int hi) {
246     super(parent);
247     this.function = function; this.array = array;
248     this.lo = this.origin = lo; this.hi = this.fence = hi;
249     int p;
250     this.threshold =
251     (p = (hi - lo) / (ForkJoinPool.getCommonPoolParallelism() << 3))
252     <= MIN_PARTITION ? MIN_PARTITION : p;
253     }
254    
255     /** Subtask constructor */
256 dl 1.1 LongCumulateTask(LongCumulateTask parent, LongBinaryOperator function,
257     long[] array, int origin, int fence, int threshold,
258     int lo, int hi) {
259     super(parent);
260     this.function = function; this.array = array;
261     this.origin = origin; this.fence = fence;
262     this.threshold = threshold;
263     this.lo = lo; this.hi = hi;
264     }
265    
266     public final void compute() {
267     final LongBinaryOperator fn;
268     final long[] a;
269     if ((fn = this.function) == null || (a = this.array) == null)
270     throw new NullPointerException(); // hoist checks
271     int th = threshold, org = origin, fnc = fence, l, h;
272     LongCumulateTask t = this;
273     outer: while ((l = t.lo) >= 0 && (h = t.hi) <= a.length) {
274     if (h - l > th) {
275     LongCumulateTask lt = t.left, rt = t.right, f;
276     if (lt == null) { // first pass
277     int mid = (l + h) >>> 1;
278     f = rt = t.right =
279     new LongCumulateTask(t, fn, a, org, fnc, th, mid, h);
280 jsr166 1.10 t = lt = t.left =
281 dl 1.1 new LongCumulateTask(t, fn, a, org, fnc, th, l, mid);
282     }
283     else { // possibly refork
284     long pin = t.in;
285     lt.in = pin;
286     f = t = null;
287     if (rt != null) {
288     long lout = lt.out;
289     rt.in = (l == org ? lout :
290     fn.applyAsLong(pin, lout));
291     for (int c;;) {
292     if (((c = rt.getPendingCount()) & CUMULATE) != 0)
293     break;
294     if (rt.compareAndSetPendingCount(c, c|CUMULATE)){
295     t = rt;
296     break;
297     }
298     }
299     }
300     for (int c;;) {
301     if (((c = lt.getPendingCount()) & CUMULATE) != 0)
302     break;
303     if (lt.compareAndSetPendingCount(c, c|CUMULATE)) {
304     if (t != null)
305     f = t;
306     t = lt;
307     break;
308     }
309     }
310     if (t == null)
311     break;
312     }
313     if (f != null)
314     f.fork();
315     }
316     else {
317     int state; // Transition to sum, cumulate, or both
318     for (int b;;) {
319     if (((b = t.getPendingCount()) & FINISHED) != 0)
320     break outer; // already done
321     state = ((b & CUMULATE) != 0 ? FINISHED :
322     (l > org) ? SUMMED : (SUMMED|FINISHED));
323     if (t.compareAndSetPendingCount(b, b|state))
324     break;
325     }
326    
327     long sum;
328     if (state != SUMMED) {
329     int first;
330     if (l == org) { // leftmost; no in
331     sum = a[org];
332     first = org + 1;
333     }
334     else {
335     sum = t.in;
336     first = l;
337     }
338     for (int i = first; i < h; ++i) // cumulate
339     a[i] = sum = fn.applyAsLong(sum, a[i]);
340     }
341     else if (h < fnc) { // skip rightmost
342     sum = a[l];
343     for (int i = l + 1; i < h; ++i) // sum only
344     sum = fn.applyAsLong(sum, a[i]);
345     }
346     else
347     sum = t.in;
348     t.out = sum;
349     for (LongCumulateTask par;;) { // propagate
350     if ((par = (LongCumulateTask)t.getCompleter()) == null) {
351     if ((state & FINISHED) != 0) // enable join
352     t.quietlyComplete();
353     break outer;
354     }
355     int b = par.getPendingCount();
356     if ((b & state & FINISHED) != 0)
357     t = par; // both done
358     else if ((b & state & SUMMED) != 0) { // both summed
359     int nextState; LongCumulateTask lt, rt;
360     if ((lt = par.left) != null &&
361     (rt = par.right) != null) {
362     long lout = lt.out;
363     par.out = (rt.hi == fnc ? lout :
364     fn.applyAsLong(lout, rt.out));
365     }
366     int refork = (((b & CUMULATE) == 0 &&
367     par.lo == org) ? CUMULATE : 0);
368     if ((nextState = b|state|refork) == b ||
369     par.compareAndSetPendingCount(b, nextState)) {
370     state = SUMMED; // drop finished
371     t = par;
372     if (refork != 0)
373     par.fork();
374     }
375     }
376     else if (par.compareAndSetPendingCount(b, b|state))
377     break outer; // sib not ready
378     }
379     }
380     }
381     }
382 jsr166 1.11 // OPENJDK @java.io.Serial
383 dl 1.1 private static final long serialVersionUID = -5074099945909284273L;
384     }
385    
386 jsr166 1.8 static final class DoubleCumulateTask extends CountedCompleter<Void> {
387 dl 1.1 final double[] array;
388 jsr166 1.12 @SuppressWarnings("serial") // Not statically typed as Serializable
389 dl 1.1 final DoubleBinaryOperator function;
390     DoubleCumulateTask left, right;
391     double in, out;
392     final int lo, hi, origin, fence, threshold;
393    
394 jsr166 1.9 /** Root task constructor */
395     public DoubleCumulateTask(DoubleCumulateTask parent,
396     DoubleBinaryOperator function,
397     double[] array, int lo, int hi) {
398     super(parent);
399     this.function = function; this.array = array;
400     this.lo = this.origin = lo; this.hi = this.fence = hi;
401     int p;
402     this.threshold =
403     (p = (hi - lo) / (ForkJoinPool.getCommonPoolParallelism() << 3))
404     <= MIN_PARTITION ? MIN_PARTITION : p;
405     }
406    
407     /** Subtask constructor */
408 dl 1.1 DoubleCumulateTask(DoubleCumulateTask parent, DoubleBinaryOperator function,
409 jsr166 1.5 double[] array, int origin, int fence, int threshold,
410     int lo, int hi) {
411 dl 1.1 super(parent);
412     this.function = function; this.array = array;
413     this.origin = origin; this.fence = fence;
414     this.threshold = threshold;
415     this.lo = lo; this.hi = hi;
416     }
417    
418     public final void compute() {
419     final DoubleBinaryOperator fn;
420     final double[] a;
421     if ((fn = this.function) == null || (a = this.array) == null)
422     throw new NullPointerException(); // hoist checks
423     int th = threshold, org = origin, fnc = fence, l, h;
424     DoubleCumulateTask t = this;
425     outer: while ((l = t.lo) >= 0 && (h = t.hi) <= a.length) {
426     if (h - l > th) {
427     DoubleCumulateTask lt = t.left, rt = t.right, f;
428     if (lt == null) { // first pass
429     int mid = (l + h) >>> 1;
430     f = rt = t.right =
431     new DoubleCumulateTask(t, fn, a, org, fnc, th, mid, h);
432 jsr166 1.10 t = lt = t.left =
433 dl 1.1 new DoubleCumulateTask(t, fn, a, org, fnc, th, l, mid);
434     }
435     else { // possibly refork
436     double pin = t.in;
437     lt.in = pin;
438     f = t = null;
439     if (rt != null) {
440     double lout = lt.out;
441     rt.in = (l == org ? lout :
442     fn.applyAsDouble(pin, lout));
443     for (int c;;) {
444     if (((c = rt.getPendingCount()) & CUMULATE) != 0)
445     break;
446     if (rt.compareAndSetPendingCount(c, c|CUMULATE)){
447     t = rt;
448     break;
449     }
450     }
451     }
452     for (int c;;) {
453     if (((c = lt.getPendingCount()) & CUMULATE) != 0)
454     break;
455     if (lt.compareAndSetPendingCount(c, c|CUMULATE)) {
456     if (t != null)
457     f = t;
458     t = lt;
459     break;
460     }
461     }
462     if (t == null)
463     break;
464     }
465     if (f != null)
466     f.fork();
467     }
468     else {
469     int state; // Transition to sum, cumulate, or both
470     for (int b;;) {
471     if (((b = t.getPendingCount()) & FINISHED) != 0)
472     break outer; // already done
473     state = ((b & CUMULATE) != 0 ? FINISHED :
474     (l > org) ? SUMMED : (SUMMED|FINISHED));
475     if (t.compareAndSetPendingCount(b, b|state))
476     break;
477     }
478    
479     double sum;
480     if (state != SUMMED) {
481     int first;
482     if (l == org) { // leftmost; no in
483     sum = a[org];
484     first = org + 1;
485     }
486     else {
487     sum = t.in;
488     first = l;
489     }
490     for (int i = first; i < h; ++i) // cumulate
491     a[i] = sum = fn.applyAsDouble(sum, a[i]);
492     }
493     else if (h < fnc) { // skip rightmost
494     sum = a[l];
495     for (int i = l + 1; i < h; ++i) // sum only
496     sum = fn.applyAsDouble(sum, a[i]);
497     }
498     else
499     sum = t.in;
500     t.out = sum;
501     for (DoubleCumulateTask par;;) { // propagate
502     if ((par = (DoubleCumulateTask)t.getCompleter()) == null) {
503     if ((state & FINISHED) != 0) // enable join
504     t.quietlyComplete();
505     break outer;
506     }
507     int b = par.getPendingCount();
508     if ((b & state & FINISHED) != 0)
509     t = par; // both done
510     else if ((b & state & SUMMED) != 0) { // both summed
511     int nextState; DoubleCumulateTask lt, rt;
512     if ((lt = par.left) != null &&
513     (rt = par.right) != null) {
514     double lout = lt.out;
515     par.out = (rt.hi == fnc ? lout :
516     fn.applyAsDouble(lout, rt.out));
517     }
518     int refork = (((b & CUMULATE) == 0 &&
519     par.lo == org) ? CUMULATE : 0);
520     if ((nextState = b|state|refork) == b ||
521     par.compareAndSetPendingCount(b, nextState)) {
522     state = SUMMED; // drop finished
523     t = par;
524     if (refork != 0)
525     par.fork();
526     }
527     }
528     else if (par.compareAndSetPendingCount(b, b|state))
529     break outer; // sib not ready
530     }
531     }
532     }
533     }
534 jsr166 1.11 // OPENJDK @java.io.Serial
535 dl 1.1 private static final long serialVersionUID = -586947823794232033L;
536     }
537    
538 jsr166 1.8 static final class IntCumulateTask extends CountedCompleter<Void> {
539 dl 1.1 final int[] array;
540 jsr166 1.12 @SuppressWarnings("serial") // Not statically typed as Serializable
541 dl 1.1 final IntBinaryOperator function;
542     IntCumulateTask left, right;
543     int in, out;
544     final int lo, hi, origin, fence, threshold;
545    
546 jsr166 1.9 /** Root task constructor */
547     public IntCumulateTask(IntCumulateTask parent,
548     IntBinaryOperator function,
549     int[] array, int lo, int hi) {
550     super(parent);
551     this.function = function; this.array = array;
552     this.lo = this.origin = lo; this.hi = this.fence = hi;
553     int p;
554     this.threshold =
555     (p = (hi - lo) / (ForkJoinPool.getCommonPoolParallelism() << 3))
556     <= MIN_PARTITION ? MIN_PARTITION : p;
557     }
558    
559     /** Subtask constructor */
560 dl 1.1 IntCumulateTask(IntCumulateTask parent, IntBinaryOperator function,
561 jsr166 1.5 int[] array, int origin, int fence, int threshold,
562     int lo, int hi) {
563 dl 1.1 super(parent);
564     this.function = function; this.array = array;
565     this.origin = origin; this.fence = fence;
566     this.threshold = threshold;
567     this.lo = lo; this.hi = hi;
568     }
569    
570     public final void compute() {
571     final IntBinaryOperator fn;
572     final int[] a;
573     if ((fn = this.function) == null || (a = this.array) == null)
574     throw new NullPointerException(); // hoist checks
575     int th = threshold, org = origin, fnc = fence, l, h;
576     IntCumulateTask t = this;
577     outer: while ((l = t.lo) >= 0 && (h = t.hi) <= a.length) {
578     if (h - l > th) {
579     IntCumulateTask lt = t.left, rt = t.right, f;
580     if (lt == null) { // first pass
581     int mid = (l + h) >>> 1;
582     f = rt = t.right =
583     new IntCumulateTask(t, fn, a, org, fnc, th, mid, h);
584 jsr166 1.10 t = lt = t.left =
585 dl 1.1 new IntCumulateTask(t, fn, a, org, fnc, th, l, mid);
586     }
587     else { // possibly refork
588     int pin = t.in;
589     lt.in = pin;
590     f = t = null;
591     if (rt != null) {
592     int lout = lt.out;
593     rt.in = (l == org ? lout :
594     fn.applyAsInt(pin, lout));
595     for (int c;;) {
596     if (((c = rt.getPendingCount()) & CUMULATE) != 0)
597     break;
598     if (rt.compareAndSetPendingCount(c, c|CUMULATE)){
599     t = rt;
600     break;
601     }
602     }
603     }
604     for (int c;;) {
605     if (((c = lt.getPendingCount()) & CUMULATE) != 0)
606     break;
607     if (lt.compareAndSetPendingCount(c, c|CUMULATE)) {
608     if (t != null)
609     f = t;
610     t = lt;
611     break;
612     }
613     }
614     if (t == null)
615     break;
616     }
617     if (f != null)
618     f.fork();
619     }
620     else {
621     int state; // Transition to sum, cumulate, or both
622     for (int b;;) {
623     if (((b = t.getPendingCount()) & FINISHED) != 0)
624     break outer; // already done
625     state = ((b & CUMULATE) != 0 ? FINISHED :
626     (l > org) ? SUMMED : (SUMMED|FINISHED));
627     if (t.compareAndSetPendingCount(b, b|state))
628     break;
629     }
630    
631     int sum;
632     if (state != SUMMED) {
633     int first;
634     if (l == org) { // leftmost; no in
635     sum = a[org];
636     first = org + 1;
637     }
638     else {
639     sum = t.in;
640     first = l;
641     }
642     for (int i = first; i < h; ++i) // cumulate
643     a[i] = sum = fn.applyAsInt(sum, a[i]);
644     }
645     else if (h < fnc) { // skip rightmost
646     sum = a[l];
647     for (int i = l + 1; i < h; ++i) // sum only
648     sum = fn.applyAsInt(sum, a[i]);
649     }
650     else
651     sum = t.in;
652     t.out = sum;
653     for (IntCumulateTask par;;) { // propagate
654     if ((par = (IntCumulateTask)t.getCompleter()) == null) {
655     if ((state & FINISHED) != 0) // enable join
656     t.quietlyComplete();
657     break outer;
658     }
659     int b = par.getPendingCount();
660     if ((b & state & FINISHED) != 0)
661     t = par; // both done
662     else if ((b & state & SUMMED) != 0) { // both summed
663     int nextState; IntCumulateTask lt, rt;
664     if ((lt = par.left) != null &&
665     (rt = par.right) != null) {
666     int lout = lt.out;
667     par.out = (rt.hi == fnc ? lout :
668     fn.applyAsInt(lout, rt.out));
669     }
670     int refork = (((b & CUMULATE) == 0 &&
671     par.lo == org) ? CUMULATE : 0);
672     if ((nextState = b|state|refork) == b ||
673     par.compareAndSetPendingCount(b, nextState)) {
674     state = SUMMED; // drop finished
675     t = par;
676     if (refork != 0)
677     par.fork();
678     }
679     }
680     else if (par.compareAndSetPendingCount(b, b|state))
681     break outer; // sib not ready
682     }
683     }
684     }
685     }
686 jsr166 1.11 // OPENJDK @java.io.Serial
687 dl 1.1 private static final long serialVersionUID = 3731755594596840961L;
688     }
689     }