35
35
36
36
import java .util .concurrent .atomic .AtomicBoolean ;
37
37
import java .util .concurrent .atomic .AtomicLong ;
38
- import java .util .concurrent .atomic .AtomicLongFieldUpdater ;
39
38
import java .util .concurrent .atomic .AtomicReference ;
40
39
41
40
import rx .Notification ;
50
49
import rx .functions .Func2 ;
51
50
import rx .schedulers .Schedulers ;
52
51
import rx .subjects .PublishSubject ;
53
- import rx .subscriptions .CompositeSubscription ;
52
+ import rx .subscriptions .SerialSubscription ;
54
53
55
54
public final class OnSubscribeRedo <T > implements OnSubscribe <T > {
56
55
@@ -82,8 +81,10 @@ public Observable<?> call(Observable<? extends Notification<?>> ts) {
82
81
@ Override
83
82
public Notification <Long > call (Notification <Long > n , Notification <?> term ) {
84
83
final long value = n .getValue ();
85
- if (value < count ) return Notification .createOnNext (value + 1 );
86
- else return (Notification <Long >) term ;
84
+ if (value < count )
85
+ return Notification .createOnNext (value + 1 );
86
+ else
87
+ return (Notification <Long >) term ;
87
88
}
88
89
}).dematerialize ();
89
90
}
@@ -103,8 +104,10 @@ public Observable<? extends Notification<?>> call(Observable<? extends Notificat
103
104
@ Override
104
105
public Notification <Integer > call (Notification <Integer > n , Notification <?> term ) {
105
106
final int value = n .getValue ();
106
- if (predicate .call (value , term .getThrowable ()).booleanValue ()) return Notification .createOnNext (value + 1 );
107
- else return (Notification <Integer >) term ;
107
+ if (predicate .call (value , term .getThrowable ()).booleanValue ())
108
+ return Notification .createOnNext (value + 1 );
109
+ else
110
+ return (Notification <Integer >) term ;
108
111
}
109
112
});
110
113
}
@@ -115,8 +118,10 @@ public static <T> Observable<T> retry(Observable<T> source) {
115
118
}
116
119
117
120
public static <T > Observable <T > retry (Observable <T > source , final long count ) {
118
- if (count < 0 ) throw new IllegalArgumentException ("count >= 0 expected" );
119
- if (count == 0 ) return source ;
121
+ if (count < 0 )
122
+ throw new IllegalArgumentException ("count >= 0 expected" );
123
+ if (count == 0 )
124
+ return source ;
120
125
return retry (source , new RedoFinite (count ));
121
126
}
122
127
@@ -141,7 +146,8 @@ public static <T> Observable<T> repeat(Observable<T> source, final long count) {
141
146
}
142
147
143
148
public static <T > Observable <T > repeat (Observable <T > source , final long count , Scheduler scheduler ) {
144
- if (count < 0 ) throw new IllegalArgumentException ("count >= 0 expected" );
149
+ if (count < 0 )
150
+ throw new IllegalArgumentException ("count >= 0 expected" );
145
151
return repeat (source , new RedoFinite (count - 1 ), scheduler );
146
152
}
147
153
@@ -162,11 +168,6 @@ public static <T> Observable<T> redo(Observable<T> source, Func1<? super Observa
162
168
private boolean stopOnComplete ;
163
169
private boolean stopOnError ;
164
170
private final Scheduler scheduler ;
165
- private final AtomicBoolean isLocked = new AtomicBoolean (true );
166
- private final AtomicBoolean isStarted = new AtomicBoolean (false );
167
- // incremented when requests are made, decremented when requests are fulfilled
168
- private final AtomicLong consumerCapacity = new AtomicLong (0l );
169
- private final AtomicReference <Producer > currentProducer = new AtomicReference <Producer >();
170
171
171
172
private OnSubscribeRedo (Observable <T > source , Func1 <? super Observable <? extends Notification <?>>, ? extends Observable <?>> f , boolean stopOnComplete , boolean stopOnError ,
172
173
Scheduler scheduler ) {
@@ -179,17 +180,18 @@ private OnSubscribeRedo(Observable<T> source, Func1<? super Observable<? extends
179
180
180
181
@ Override
181
182
public void call (final Subscriber <? super T > child ) {
182
- isStarted .set (false );
183
- isLocked .set (true );
184
- consumerCapacity .set (0l );
185
- currentProducer .set (null );
183
+ final AtomicBoolean isLocked = new AtomicBoolean (true );
184
+ final AtomicBoolean isStarted = new AtomicBoolean (false );
185
+ // incremented when requests are made, decremented when requests are fulfilled
186
+ final AtomicLong consumerCapacity = new AtomicLong (0l );
187
+ final AtomicReference <Producer > currentProducer = new AtomicReference <Producer >();
186
188
187
- final Scheduler .Worker inner = scheduler .createWorker ();
188
- child .add (inner );
189
+ final Scheduler .Worker worker = scheduler .createWorker ();
190
+ child .add (worker );
189
191
190
- final CompositeSubscription sourceSubscriptions = new CompositeSubscription ();
192
+ final SerialSubscription sourceSubscriptions = new SerialSubscription ();
191
193
child .add (sourceSubscriptions );
192
-
194
+
193
195
final PublishSubject <Notification <?>> terminals = PublishSubject .create ();
194
196
195
197
final Action0 subscribeToSource = new Action0 () {
@@ -222,7 +224,7 @@ public void setProducer(Producer producer) {
222
224
};
223
225
// new subscription each time so if it unsubscribes itself it does not prevent retries
224
226
// by unsubscribing the child subscription
225
- sourceSubscriptions .add (terminalDelegatingSubscriber );
227
+ sourceSubscriptions .set (terminalDelegatingSubscriber );
226
228
source .unsafeSubscribe (terminalDelegatingSubscriber );
227
229
}
228
230
};
@@ -247,8 +249,10 @@ public void onError(Throwable e) {
247
249
248
250
@ Override
249
251
public void onNext (Notification <?> t ) {
250
- if (t .isOnCompleted () && stopOnComplete ) child .onCompleted ();
251
- else if (t .isOnError () && stopOnError ) child .onError (t .getThrowable ());
252
+ if (t .isOnCompleted () && stopOnComplete )
253
+ child .onCompleted ();
254
+ else if (t .isOnError () && stopOnError )
255
+ child .onError (t .getThrowable ());
252
256
else {
253
257
isLocked .set (false );
254
258
filteredTerminals .onNext (t );
@@ -264,7 +268,7 @@ public void setProducer(Producer producer) {
264
268
}));
265
269
266
270
// subscribe to the restarts observable to know when to schedule the next redo.
267
- child . add ( inner .schedule (new Action0 () {
271
+ worker .schedule (new Action0 () {
268
272
@ Override
269
273
public void call () {
270
274
restarts .unsafeSubscribe (new Subscriber <Object >(child ) {
@@ -281,7 +285,9 @@ public void onError(Throwable e) {
281
285
@ Override
282
286
public void onNext (Object t ) {
283
287
if (!isLocked .get () && !child .isUnsubscribed ()) {
284
- child .add (inner .schedule (subscribeToSource ));
288
+ if (consumerCapacity .get () > 0 ) {
289
+ worker .schedule (subscribeToSource );
290
+ }
285
291
}
286
292
}
287
293
@@ -291,18 +297,24 @@ public void setProducer(Producer producer) {
291
297
}
292
298
});
293
299
}
294
- })) ;
300
+ });
295
301
296
302
child .setProducer (new Producer () {
297
303
298
304
@ Override
299
305
public void request (long n ) {
300
306
if (isStarted .compareAndSet (false , true )) {
301
307
consumerCapacity .set (n );
302
- if (!child .isUnsubscribed ()) child .add (inner .schedule (subscribeToSource ));
303
- } else if (currentProducer .get () != null ) {
304
- consumerCapacity .getAndAdd (n );
305
- currentProducer .get ().request (n );
308
+ worker .schedule (subscribeToSource );
309
+ } else {
310
+ if (consumerCapacity .getAndAdd (n ) == 0 ) {
311
+ // restart
312
+ worker .schedule (subscribeToSource );
313
+ } else {
314
+ if (currentProducer .get () != null ) {
315
+ currentProducer .get ().request (n );
316
+ }
317
+ }
306
318
}
307
319
}
308
320
});
0 commit comments