@@ -99,7 +99,7 @@ public void call() {
99
99
public void connect (Action1 <? super Subscription > connection ) {
100
100
// each time we connect we create a new Subscription
101
101
boolean shouldSubscribe = false ;
102
-
102
+
103
103
// subscription is the state of whether we are connected or not
104
104
OriginSubscriber <T > origin = requestHandler .state .getOrigin ();
105
105
if (origin == null ) {
@@ -113,7 +113,7 @@ public void connect(Action1<? super Subscription> connection) {
113
113
connection .call (Subscriptions .create (new Action0 () {
114
114
@ Override
115
115
public void call () {
116
- Subscription s = requestHandler .state .getOrigin ();
116
+ OriginSubscriber < T > s = requestHandler .state .getOrigin ();
117
117
requestHandler .state .setOrigin (null );
118
118
if (s != null ) {
119
119
s .unsubscribe ();
@@ -135,9 +135,11 @@ private static class OriginSubscriber<T> extends Subscriber<T> {
135
135
private final RequestHandler <T > requestHandler ;
136
136
private final AtomicLong originOutstanding = new AtomicLong ();
137
137
private final long THRESHOLD = RxRingBuffer .SIZE / 4 ;
138
+ private final RxRingBuffer buffer = RxRingBuffer .getSpmcInstance ();
138
139
139
140
OriginSubscriber (RequestHandler <T > requestHandler ) {
140
141
this .requestHandler = requestHandler ;
142
+ add (buffer );
141
143
}
142
144
143
145
@ Override
@@ -199,6 +201,8 @@ public void onNext(T t) {
199
201
* with a complicated state machine so I'm sticking with mutex locks and just trying to make sure the work done while holding the
200
202
* lock is small (such as never emitting data).
201
203
*
204
+ * This does however mean we can't rely on a reference to State being consistent. For example, it can end up with a null OriginSubscriber.
205
+ *
202
206
* @param <T>
203
207
*/
204
208
private static class State <T > {
@@ -288,7 +292,7 @@ private long resetAfterSubscriberUpdate() {
288
292
289
293
private static class RequestHandler <T > {
290
294
private final NotificationLite <T > notifier = NotificationLite .instance ();
291
- private final RxRingBuffer buffer = RxRingBuffer . getSpmcInstance ();
295
+
292
296
private final State <T > state = new State <T >();
293
297
@ SuppressWarnings ("unused" )
294
298
volatile long wip ;
@@ -297,16 +301,24 @@ private static class RequestHandler<T> {
297
301
298
302
public void requestFromChildSubscriber (Subscriber <? super T > subscriber , Long request ) {
299
303
state .requestFromSubscriber (subscriber , request );
300
- drainQueue ();
304
+ OriginSubscriber <T > originSubscriber = state .getOrigin ();
305
+ if (originSubscriber != null ) {
306
+ drainQueue (originSubscriber );
307
+ }
301
308
}
302
309
303
310
public void emit (Object t ) throws MissingBackpressureException {
311
+ OriginSubscriber <T > originSubscriber = state .getOrigin ();
312
+ if (originSubscriber == null ) {
313
+ // unsubscribed so break ... we are done
314
+ return ;
315
+ }
304
316
if (notifier .isCompleted (t )) {
305
- buffer .onCompleted ();
317
+ originSubscriber . buffer .onCompleted ();
306
318
} else {
307
- buffer .onNext (notifier .getValue (t ));
319
+ originSubscriber . buffer .onNext (notifier .getValue (t ));
308
320
}
309
- drainQueue ();
321
+ drainQueue (originSubscriber );
310
322
}
311
323
312
324
private void requestMoreAfterEmission (int emitted ) {
@@ -319,7 +331,7 @@ private void requestMoreAfterEmission(int emitted) {
319
331
}
320
332
}
321
333
322
- public void drainQueue () {
334
+ public void drainQueue (OriginSubscriber < T > originSubscriber ) {
323
335
if (WIP .getAndIncrement (this ) == 0 ) {
324
336
int emitted = 0 ;
325
337
do {
@@ -338,7 +350,7 @@ public void drainQueue() {
338
350
if (!shouldEmit ) {
339
351
break ;
340
352
}
341
- Object o = buffer .poll ();
353
+ Object o = originSubscriber . buffer .poll ();
342
354
if (o == null ) {
343
355
// nothing in buffer so increment outstanding back again
344
356
state .incrementOutstandingAfterFailedEmit ();
0 commit comments