16
16
package rx .internal .operators ;
17
17
18
18
import java .util .concurrent .ConcurrentLinkedQueue ;
19
- import java .util .concurrent .atomic .AtomicInteger ;
20
- import java .util .concurrent .atomic .AtomicLong ;
19
+ import java .util .concurrent .atomic .*;
21
20
22
- import rx .Observable ;
21
+ import rx .* ;
23
22
import rx .Observable .Operator ;
24
- import rx .Producer ;
25
- import rx .Subscriber ;
26
23
import rx .functions .Action0 ;
27
24
import rx .internal .producers .ProducerArbiter ;
28
25
import rx .observers .SerializedSubscriber ;
29
- import rx .subscriptions .SerialSubscription ;
30
- import rx .subscriptions .Subscriptions ;
26
+ import rx .subscriptions .*;
31
27
32
28
/**
33
29
* Returns an Observable that emits the items emitted by two or more Observables, one after the other.
@@ -112,9 +108,19 @@ public void onStart() {
112
108
}
113
109
114
110
private void requestFromChild (long n ) {
115
- if (n <=0 ) return ;
111
+ if (n <= 0 ) return ;
116
112
// we track 'requested' so we know whether we should subscribe the next or not
117
- long previous = BackpressureUtils .getAndAddRequest (requested , n );
113
+
114
+ final AtomicLong requestedField = requested ;
115
+
116
+ long previous ;
117
+
118
+ if (requestedField .get () != Long .MAX_VALUE ) {
119
+ previous = BackpressureUtils .getAndAddRequest (requestedField , n );
120
+ } else {
121
+ previous = Long .MAX_VALUE ;
122
+ }
123
+
118
124
arbiter .request (n );
119
125
if (previous == 0 ) {
120
126
if (currentSubscriber == null && wip .get () > 0 ) {
@@ -125,10 +131,6 @@ private void requestFromChild(long n) {
125
131
}
126
132
}
127
133
128
- private void decrementRequested () {
129
- requested .decrementAndGet ();
130
- }
131
-
132
134
@ Override
133
135
public void onNext (Observable <? extends T > t ) {
134
136
queue .add (nl .next (t ));
@@ -167,8 +169,10 @@ void subscribeNext() {
167
169
child .onCompleted ();
168
170
} else if (o != null ) {
169
171
Observable <? extends T > obs = nl .getValue (o );
172
+
170
173
currentSubscriber = new ConcatInnerSubscriber <T >(this , child , arbiter );
171
174
current .set (currentSubscriber );
175
+
172
176
obs .unsafeSubscribe (currentSubscriber );
173
177
}
174
178
} else {
@@ -179,14 +183,23 @@ void subscribeNext() {
179
183
}
180
184
}
181
185
}
186
+
187
+ void produced (long c ) {
188
+ if (c != 0L ) {
189
+ arbiter .produced (c );
190
+ BackpressureUtils .produced (requested , c );
191
+ }
192
+ }
182
193
}
183
194
184
195
static class ConcatInnerSubscriber <T > extends Subscriber <T > {
185
196
186
197
private final Subscriber <T > child ;
187
198
private final ConcatSubscriber <T > parent ;
188
- private final AtomicInteger once = new AtomicInteger ();
199
+ private final AtomicBoolean once = new AtomicBoolean ();
189
200
private final ProducerArbiter arbiter ;
201
+
202
+ long produced ;
190
203
191
204
public ConcatInnerSubscriber (ConcatSubscriber <T > parent , Subscriber <T > child , ProducerArbiter arbiter ) {
192
205
this .parent = parent ;
@@ -196,31 +209,33 @@ public ConcatInnerSubscriber(ConcatSubscriber<T> parent, Subscriber<T> child, Pr
196
209
197
210
@ Override
198
211
public void onNext (T t ) {
212
+ produced ++;
213
+
199
214
child .onNext (t );
200
- parent .decrementRequested ();
201
- arbiter .produced (1 );
202
215
}
203
216
204
217
@ Override
205
218
public void onError (Throwable e ) {
206
- if (once .compareAndSet (0 , 1 )) {
219
+ if (once .compareAndSet (false , true )) {
207
220
// terminal error through parent so everything gets cleaned up, including this inner
208
221
parent .onError (e );
209
222
}
210
223
}
211
224
212
225
@ Override
213
226
public void onCompleted () {
214
- if (once .compareAndSet (0 , 1 )) {
227
+ if (once .compareAndSet (false , true )) {
228
+ ConcatSubscriber <T > p = parent ;
229
+ // signal the production count at once instead of one by one
230
+ p .produced (produced );
215
231
// terminal completion to parent so it continues to the next
216
- parent .completeInner ();
232
+ p .completeInner ();
217
233
}
218
234
}
219
235
220
236
@ Override
221
237
public void setProducer (Producer producer ) {
222
238
arbiter .setProducer (producer );
223
239
}
224
-
225
240
}
226
241
}
0 commit comments