13
13
14
14
package io .reactivex .internal .operators .flowable ;
15
15
16
- import io .reactivex .plugins .RxJavaPlugins ;
17
-
18
- import java .util .ArrayList ;
19
- import java .util .List ;
20
16
import java .util .concurrent .Callable ;
21
17
import java .util .concurrent .atomic .*;
22
18
25
21
import io .reactivex .disposables .Disposable ;
26
22
import io .reactivex .exceptions .*;
27
23
import io .reactivex .functions .Function ;
24
+ import io .reactivex .internal .functions .ObjectHelper ;
28
25
import io .reactivex .internal .fuseable .*;
29
26
import io .reactivex .internal .queue .*;
30
27
import io .reactivex .internal .subscriptions .SubscriptionHelper ;
31
- import io .reactivex .internal .util .BackpressureHelper ;
28
+ import io .reactivex .internal .util .*;
29
+ import io .reactivex .plugins .RxJavaPlugins ;
32
30
33
31
public final class FlowableFlatMap <T , U > extends AbstractFlowableWithUpstream <T , U > {
34
32
final Function <? super T , ? extends Publisher <? extends U >> mapper ;
@@ -64,13 +62,11 @@ static final class MergeSubscriber<T, U> extends AtomicInteger implements Subscr
64
62
final int maxConcurrency ;
65
63
final int bufferSize ;
66
64
67
- volatile SimpleQueue <U > queue ;
65
+ volatile SimplePlainQueue <U > queue ;
68
66
69
67
volatile boolean done ;
70
68
71
- final AtomicReference <SimpleQueue <Throwable >> errors = new AtomicReference <SimpleQueue <Throwable >>();
72
-
73
- static final SimpleQueue <Throwable > ERRORS_CLOSED = new RejectingQueue <Throwable >();
69
+ final AtomicThrowable errs = new AtomicThrowable ();
74
70
75
71
volatile boolean cancelled ;
76
72
@@ -126,7 +122,7 @@ public void onNext(T t) {
126
122
}
127
123
Publisher <? extends U > p ;
128
124
try {
129
- p = mapper .apply (t );
125
+ p = ObjectHelper . requireNonNull ( mapper .apply (t ), "The mapper returned a null Publisher" );
130
126
} catch (Throwable e ) {
131
127
Exceptions .throwIfFatal (e );
132
128
s .cancel ();
@@ -140,7 +136,7 @@ public void onNext(T t) {
140
136
u = ((Callable <U >)p ).call ();
141
137
} catch (Throwable ex ) {
142
138
Exceptions .throwIfFatal (ex );
143
- getErrorQueue (). offer (ex );
139
+ errs . addThrowable (ex );
144
140
drain ();
145
141
return ;
146
142
}
@@ -210,7 +206,7 @@ void removeInner(InnerSubscriber<T, U> inner) {
210
206
}
211
207
212
208
SimpleQueue <U > getMainQueue () {
213
- SimpleQueue <U > q = queue ;
209
+ SimplePlainQueue <U > q = queue ;
214
210
if (q == null ) {
215
211
if (maxConcurrency == Integer .MAX_VALUE ) {
216
212
q = new SpscLinkedArrayQueue <U >(bufferSize );
@@ -316,9 +312,12 @@ public void onError(Throwable t) {
316
312
RxJavaPlugins .onError (t );
317
313
return ;
318
314
}
319
- getErrorQueue ().offer (t );
320
- done = true ;
321
- drain ();
315
+ if (errs .addThrowable (t )) {
316
+ done = true ;
317
+ drain ();
318
+ } else {
319
+ RxJavaPlugins .onError (t );
320
+ }
322
321
}
323
322
324
323
@ Override
@@ -343,9 +342,13 @@ public void request(long n) {
343
342
public void cancel () {
344
343
if (!cancelled ) {
345
344
cancelled = true ;
345
+ s .cancel ();
346
+ disposeAll ();
346
347
if (getAndIncrement () == 0 ) {
347
- s .cancel ();
348
- disposeAll ();
348
+ SimpleQueue <U > q = queue ;
349
+ if (q != null ) {
350
+ q .clear ();
351
+ }
349
352
}
350
353
}
351
354
}
@@ -363,7 +366,7 @@ void drainLoop() {
363
366
if (checkTerminate ()) {
364
367
return ;
365
368
}
366
- SimpleQueue <U > svq = queue ;
369
+ SimplePlainQueue <U > svq = queue ;
367
370
368
371
long r = requested .get ();
369
372
boolean unbounded = r == Long .MAX_VALUE ;
@@ -375,12 +378,8 @@ void drainLoop() {
375
378
long scalarEmission = 0 ;
376
379
U o = null ;
377
380
while (r != 0L ) {
378
- try {
379
- o = svq .poll ();
380
- } catch (Throwable ex ) {
381
- Exceptions .throwIfFatal (ex );
382
- getErrorQueue ().offer (ex );
383
- }
381
+ o = svq .poll ();
382
+
384
383
if (checkTerminate ()) {
385
384
return ;
386
385
}
@@ -413,11 +412,11 @@ void drainLoop() {
413
412
int n = inner .length ;
414
413
415
414
if (d && (svq == null || svq .isEmpty ()) && n == 0 ) {
416
- SimpleQueue < Throwable > e = errors . get ();
417
- if (e == null || e . isEmpty () ) {
415
+ Throwable ex = errs . terminate ();
416
+ if (ex == null ) {
418
417
child .onComplete ();
419
418
} else {
420
- reportError ( e );
419
+ child . onError ( ex );
421
420
}
422
421
return ;
423
422
}
@@ -447,6 +446,7 @@ void drainLoop() {
447
446
}
448
447
449
448
int j = index ;
449
+ sourceLoop :
450
450
for (int i = 0 ; i < n ; i ++) {
451
451
if (checkTerminate ()) {
452
452
return ;
@@ -456,33 +456,40 @@ void drainLoop() {
456
456
457
457
U o = null ;
458
458
for (;;) {
459
+ if (checkTerminate ()) {
460
+ return ;
461
+ }
462
+ SimpleQueue <U > q = is .queue ;
463
+ if (q == null ) {
464
+ break ;
465
+ }
459
466
long produced = 0 ;
460
467
while (r != 0L ) {
461
- if (checkTerminate ()) {
462
- return ;
463
- }
464
- SimpleQueue <U > q = is .queue ;
465
- if (q == null ) {
466
- break ;
467
- }
468
468
469
469
try {
470
470
o = q .poll ();
471
471
} catch (Throwable ex ) {
472
472
Exceptions .throwIfFatal (ex );
473
-
474
- s .cancel ();
475
- disposeAll ();
476
-
477
- child .onError (ex );
478
- return ;
473
+ is .dispose ();
474
+ errs .addThrowable (ex );
475
+ if (checkTerminate ()) {
476
+ return ;
477
+ }
478
+ removeInner (is );
479
+ innerCompleted = true ;
480
+ i ++;
481
+ continue sourceLoop ;
479
482
}
480
483
if (o == null ) {
481
484
break ;
482
485
}
483
486
484
487
child .onNext (o );
485
488
489
+ if (checkTerminate ()) {
490
+ return ;
491
+ }
492
+
486
493
r --;
487
494
produced ++;
488
495
}
@@ -536,86 +543,31 @@ void drainLoop() {
536
543
537
544
boolean checkTerminate () {
538
545
if (cancelled ) {
539
- s .cancel ();
540
- disposeAll ();
546
+ SimpleQueue <U > q = queue ;
547
+ if (q != null ) {
548
+ q .clear ();
549
+ }
541
550
return true ;
542
551
}
543
- SimpleQueue <Throwable > e = errors .get ();
544
- if (!delayErrors && (e != null && !e .isEmpty ())) {
545
- try {
546
- reportError (e );
547
- } finally {
548
- disposeAll ();
549
- }
552
+ if (!delayErrors && errs .get () != null ) {
553
+ actual .onError (errs .terminate ());
550
554
return true ;
551
555
}
552
556
return false ;
553
557
}
554
558
555
- void reportError (SimpleQueue <Throwable > q ) {
556
- List <Throwable > composite = null ;
557
- Throwable ex = null ;
558
-
559
- for (;;) {
560
- Throwable t ;
561
- try {
562
- t = q .poll ();
563
- } catch (Throwable exc ) {
564
- Exceptions .throwIfFatal (exc );
565
- if (ex == null ) {
566
- ex = exc ;
567
- } else {
568
- if (composite == null ) {
569
- composite = new ArrayList <Throwable >();
570
- composite .add (ex );
571
- }
572
- composite .add (exc );
573
- }
574
- break ;
575
- }
576
-
577
- if (t == null ) {
578
- break ;
579
- }
580
- if (ex == null ) {
581
- ex = t ;
582
- } else {
583
- if (composite == null ) {
584
- composite = new ArrayList <Throwable >();
585
- composite .add (ex );
586
- }
587
- composite .add (t );
588
- }
589
- }
590
- if (composite != null ) {
591
- actual .onError (new CompositeException (composite ));
592
- } else {
593
- actual .onError (ex );
594
- }
595
- }
596
-
597
559
void disposeAll () {
598
560
InnerSubscriber <?, ?>[] a = subscribers .get ();
599
561
if (a != CANCELLED ) {
600
562
a = subscribers .getAndSet (CANCELLED );
601
563
if (a != CANCELLED ) {
602
- errors .getAndSet (ERRORS_CLOSED );
603
564
for (InnerSubscriber <?, ?> inner : a ) {
604
565
inner .dispose ();
605
566
}
606
- }
607
- }
608
- }
609
-
610
- SimpleQueue <Throwable > getErrorQueue () {
611
- for (;;) {
612
- SimpleQueue <Throwable > q = errors .get ();
613
- if (q != null ) {
614
- return q ;
615
- }
616
- q = new MpscLinkedQueue <Throwable >();
617
- if (errors .compareAndSet (null , q )) {
618
- return q ;
567
+ Throwable ex = errs .terminate ();
568
+ if (ex != null && ex != ExceptionHelper .TERMINATED ) {
569
+ RxJavaPlugins .onError (ex );
570
+ }
619
571
}
620
572
}
621
573
}
@@ -676,9 +628,12 @@ public void onNext(U t) {
676
628
}
677
629
@ Override
678
630
public void onError (Throwable t ) {
679
- parent .getErrorQueue ().offer (t );
680
- done = true ;
681
- parent .drain ();
631
+ if (parent .errs .addThrowable (t )) {
632
+ done = true ;
633
+ parent .drain ();
634
+ } else {
635
+ RxJavaPlugins .onError (t );
636
+ }
682
637
}
683
638
@ Override
684
639
public void onComplete () {
@@ -708,31 +663,4 @@ public boolean isDisposed() {
708
663
return get () == SubscriptionHelper .CANCELLED ;
709
664
}
710
665
}
711
-
712
- static final class RejectingQueue <T > implements SimpleQueue <T > {
713
- @ Override
714
- public boolean offer (T e ) {
715
- return false ;
716
- }
717
-
718
- @ Override
719
- public boolean offer (T v1 , T v2 ) {
720
- return false ;
721
- }
722
-
723
- @ Override
724
- public T poll () {
725
- return null ;
726
- }
727
-
728
- @ Override
729
- public void clear () {
730
-
731
- }
732
-
733
- @ Override
734
- public boolean isEmpty () {
735
- return true ;
736
- }
737
- }
738
666
}
0 commit comments