@@ -45,31 +45,34 @@ final class FlowableExpand<T> extends Flowable<T> implements FlowableTransformer
45
45
46
46
final int capacityHint ;
47
47
48
+ final boolean delayErrors ;
49
+
48
50
FlowableExpand (Flowable <T > source , Function <? super T , ? extends Publisher <? extends T >> expander ,
49
- ExpandStrategy strategy , int capacityHint ) {
51
+ ExpandStrategy strategy , int capacityHint , boolean delayErrors ) {
50
52
this .source = source ;
51
53
this .expander = expander ;
52
54
this .strategy = strategy ;
53
55
this .capacityHint = capacityHint ;
56
+ this .delayErrors = delayErrors ;
54
57
}
55
58
56
59
@ Override
57
60
protected void subscribeActual (Subscriber <? super T > s ) {
58
61
if (strategy != ExpandStrategy .DEPTH_FIRST ) {
59
- ExpandBreadthSubscriber <T > parent = new ExpandBreadthSubscriber <T >(s , expander , capacityHint );
62
+ ExpandBreadthSubscriber <T > parent = new ExpandBreadthSubscriber <T >(s , expander , capacityHint , delayErrors );
60
63
parent .queue .offer (source );
61
64
s .onSubscribe (parent );
62
65
parent .drainQueue ();
63
66
} else {
64
- ExpandDepthSubscription <T > parent = new ExpandDepthSubscription <T >(s , expander , capacityHint );
67
+ ExpandDepthSubscription <T > parent = new ExpandDepthSubscription <T >(s , expander , capacityHint , delayErrors );
65
68
parent .source = source ;
66
69
s .onSubscribe (parent );
67
70
}
68
71
}
69
72
70
73
@ Override
71
74
public Publisher <T > apply (Flowable <T > upstream ) {
72
- return new FlowableExpand <T >(upstream , expander , strategy , capacityHint );
75
+ return new FlowableExpand <T >(upstream , expander , strategy , capacityHint , delayErrors );
73
76
}
74
77
75
78
static final class ExpandBreadthSubscriber <T > extends SubscriptionArbiter implements FlowableSubscriber <T > {
@@ -84,16 +87,22 @@ static final class ExpandBreadthSubscriber<T> extends SubscriptionArbiter implem
84
87
85
88
final AtomicInteger wip ;
86
89
90
+ final boolean delayErrors ;
91
+
92
+ final AtomicThrowable errors ;
93
+
87
94
volatile boolean active ;
88
95
89
96
long produced ;
90
97
91
98
ExpandBreadthSubscriber (Subscriber <? super T > actual ,
92
- Function <? super T , ? extends Publisher <? extends T >> expander , int capacityHint ) {
99
+ Function <? super T , ? extends Publisher <? extends T >> expander , int capacityHint , boolean delayErrors ) {
93
100
this .actual = actual ;
94
101
this .expander = expander ;
95
102
this .wip = new AtomicInteger ();
96
103
this .queue = new SpscLinkedArrayQueue <Publisher <? extends T >>(capacityHint );
104
+ this .errors = new AtomicThrowable ();
105
+ this .delayErrors = delayErrors ;
97
106
}
98
107
99
108
@ Override
@@ -123,8 +132,13 @@ public void onNext(T t) {
123
132
@ Override
124
133
public void onError (Throwable t ) {
125
134
setSubscription (SubscriptionHelper .CANCELLED );
126
- super .cancel ();
127
- actual .onError (t );
135
+ if (delayErrors ) {
136
+ errors .addThrowable (t );
137
+ active = false ;
138
+ } else {
139
+ super .cancel ();
140
+ actual .onError (t );
141
+ }
128
142
drainQueue ();
129
143
}
130
144
@@ -151,7 +165,12 @@ void drainQueue() {
151
165
if (q .isEmpty ()) {
152
166
setSubscription (SubscriptionHelper .CANCELLED );
153
167
super .cancel ();
154
- actual .onComplete ();
168
+ Throwable ex = errors .terminate ();
169
+ if (ex == null ) {
170
+ actual .onComplete ();
171
+ } else {
172
+ actual .onError (ex );
173
+ }
155
174
} else {
156
175
Publisher <? extends T > p = q .poll ();
157
176
long c = produced ;
@@ -187,6 +206,8 @@ static final class ExpandDepthSubscription<T>
187
206
188
207
final AtomicReference <Object > current ;
189
208
209
+ final boolean delayErrors ;
210
+
190
211
ArrayDeque <ExpandDepthSubscriber > subscriptionStack ;
191
212
192
213
volatile boolean cancelled ;
@@ -197,14 +218,15 @@ static final class ExpandDepthSubscription<T>
197
218
198
219
ExpandDepthSubscription (Subscriber <? super T > actual ,
199
220
Function <? super T , ? extends Publisher <? extends T >> expander ,
200
- int capacityHint ) {
221
+ int capacityHint , boolean delayErrors ) {
201
222
this .actual = actual ;
202
223
this .expander = expander ;
203
224
this .subscriptionStack = new ArrayDeque <ExpandDepthSubscriber >();
204
225
this .error = new AtomicThrowable ();
205
226
this .active = new AtomicInteger ();
206
227
this .requested = new AtomicLong ();
207
228
this .current = new AtomicReference <Object >();
229
+ this .delayErrors = delayErrors ;
208
230
}
209
231
210
232
@ Override
@@ -307,6 +329,13 @@ void drainQueue() {
307
329
} else {
308
330
309
331
boolean currentDone = curr .done ;
332
+
333
+ if (!delayErrors && error .get () != null ) {
334
+ cancel ();
335
+ a .onError (error .terminate ());
336
+ return ;
337
+ }
338
+
310
339
T v = curr .value ;
311
340
312
341
boolean newSource = false ;
0 commit comments