27
27
import rx .concurrency .CurrentThreadScheduler ;
28
28
import rx .concurrency .ImmediateScheduler ;
29
29
import rx .subscriptions .CompositeSubscription ;
30
+ import rx .subscriptions .SerialSubscription ;
30
31
import rx .subscriptions .Subscriptions ;
31
32
import rx .util .functions .Action0 ;
32
33
import rx .util .functions .Action1 ;
@@ -46,10 +47,6 @@ public static <T> OnSubscribeFunc<T> observeOn(Observable<? extends T> source, S
46
47
private static class ObserveOn <T > implements OnSubscribeFunc <T > {
47
48
private final Observable <? extends T > source ;
48
49
private final Scheduler scheduler ;
49
- private volatile Scheduler recursiveScheduler ;
50
-
51
- final ConcurrentLinkedQueue <Notification <? extends T >> queue = new ConcurrentLinkedQueue <Notification <? extends T >>();
52
- final AtomicInteger counter = new AtomicInteger (0 );
53
50
54
51
public ObserveOn (Observable <? extends T > source , Scheduler scheduler ) {
55
52
this .source = source ;
@@ -65,71 +62,67 @@ public Subscription onSubscribe(final Observer<? super T> observer) {
65
62
// do nothing if we request CurrentThreadScheduler so we don't invoke overhead
66
63
return source .subscribe (observer );
67
64
} else {
68
- return observeOn (observer , scheduler );
65
+ return new Observation (observer ). init ( );
69
66
}
70
67
}
68
+ /** Observe through individual queue per observer. */
69
+ private class Observation implements Action1 <Notification <? extends T >> {
70
+ final Observer <? super T > observer ;
71
+ final CompositeSubscription s ;
72
+ final ConcurrentLinkedQueue <Notification <? extends T >> queue ;
73
+ final AtomicInteger counter ;
74
+ private volatile Scheduler recursiveScheduler ;
75
+ public Observation (Observer <? super T > observer ) {
76
+ this .observer = observer ;
77
+ this .queue = new ConcurrentLinkedQueue <Notification <? extends T >>();
78
+ this .counter = new AtomicInteger (0 );
79
+ this .s = new CompositeSubscription ();
80
+ }
81
+ public Subscription init () {
82
+ s .add (source .materialize ().subscribe (this ));
83
+ return s ;
84
+ }
71
85
72
- public Subscription observeOn (final Observer <? super T > observer , final Scheduler scheduler ) {
73
- final CompositeSubscription s = new CompositeSubscription ();
74
-
75
- s .add (source .materialize ().subscribe (new Action1 <Notification <? extends T >>() {
76
-
77
- @ Override
78
- public void call (Notification <? extends T > e ) {
79
- // this must happen before 'counter' is used to provide synchronization between threads
80
- queue .offer (e );
81
-
82
- // we now use counter to atomically determine if we need to start processing or not
83
- // it will be 0 if it's the first notification or the scheduler has finished processing work
84
- // and we need to start doing it again
85
- if (counter .getAndIncrement () == 0 ) {
86
- if (recursiveScheduler == null ) {
87
- s .add (scheduler .schedule (null , new Func2 <Scheduler , T , Subscription >() {
88
-
86
+ @ Override
87
+ public void call (Notification <? extends T > e ) {
88
+ queue .offer (e );
89
+ if (counter .getAndIncrement () == 0 ) {
90
+ if (recursiveScheduler == null ) {
91
+ s .add (scheduler .schedule (null , new Func2 <Scheduler , T , Subscription >() {
89
92
@ Override
90
93
public Subscription call (Scheduler innerScheduler , T state ) {
91
94
// record innerScheduler so 'processQueue' can use it for all subsequent executions
92
95
recursiveScheduler = innerScheduler ;
93
96
94
- processQueue (s , observer );
97
+ processQueue ();
95
98
96
99
return Subscriptions .empty ();
97
100
}
98
101
}));
99
- } else {
100
- processQueue (s , observer );
101
- }
102
+ } else {
103
+ processQueue ();
102
104
}
103
-
104
105
}
105
- }));
106
-
107
- return s ;
108
- }
109
-
110
- /**
111
- * This uses 'recursiveScheduler' NOT 'scheduler' as it should reuse the same scheduler each time it processes.
112
- * This means it must first get the recursiveScheduler when it first executes.
113
- */
114
- private void processQueue (final CompositeSubscription s , final Observer <? super T > observer ) {
106
+ }
107
+ void processQueue () {
108
+ s .add (recursiveScheduler .schedule (new Action1 <Action0 >() {
109
+ @ Override
110
+ public void call (Action0 self ) {
111
+ Notification <? extends T > not = queue .poll ();
112
+ if (not != null ) {
113
+ not .accept (observer );
114
+ }
115
115
116
- s .add (recursiveScheduler .schedule (new Action1 <Action0 >() {
117
- @ Override
118
- public void call (Action0 self ) {
119
- Notification <? extends T > not = queue .poll ();
120
- if (not != null ) {
121
- not .accept (observer );
122
- }
116
+ // decrement count and if we still have work to do
117
+ // recursively schedule ourselves to process again
118
+ if (counter .decrementAndGet () > 0 ) {
119
+ self .call ();
120
+ }
123
121
124
- // decrement count and if we still have work to do
125
- // recursively schedule ourselves to process again
126
- if (counter .decrementAndGet () > 0 ) {
127
- self .call ();
128
122
}
129
-
130
- }
131
- }));
123
+ }));
124
+ }
132
125
}
133
126
}
134
127
135
- }
128
+ }
0 commit comments