ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/ArrayPrefixHelpers.java
Revision: 1.11
Committed: Fri Aug 30 18:05:39 2019 UTC (4 years, 8 months ago) by jsr166
Branch: MAIN
Changes since 1.10: +4 -0 lines
Log Message:
accommodate 8229997: Apply java.io.Serial annotations in java.base

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