23
23
import rx .Observable .OnSubscribe ;
24
24
import rx .Observer ;
25
25
import rx .Subscriber ;
26
- import rx .Subscription ;
27
26
import rx .functions .Action0 ;
28
27
import rx .functions .Action1 ;
29
- import rx .operators .SafeObservableSubscription ;
30
28
import rx .subscriptions .Subscriptions ;
31
29
32
30
/* package */ class SubjectSubscriptionManager <T > {
39
37
* Always runs at the beginning of 'subscribe' regardless of terminal state.
40
38
* @param onTerminated
41
39
* Only runs if Subject is in terminal state and the Observer ends up not being registered.
42
- * @param onUnsubscribe called after the child subscription is removed from the state
40
+ * @param onUnsubscribe
41
+ * called after the child subscription is removed from the state
43
42
* @return
44
43
*/
45
- public OnSubscribe <T > getOnSubscribeFunc (final Action1 <SubjectObserver <? super T >> onSubscribe ,
44
+ public OnSubscribe <T > getOnSubscribeFunc (final Action1 <SubjectObserver <? super T >> onSubscribe ,
46
45
final Action1 <SubjectObserver <? super T >> onTerminated ,
47
46
final Action1 <SubjectObserver <? super T >> onUnsubscribe ) {
48
47
return new OnSubscribe <T >() {
@@ -73,10 +72,9 @@ public void call(Subscriber<? super T> actualOperator) {
73
72
}
74
73
break ;
75
74
} else {
76
- final SafeObservableSubscription subscription = new SafeObservableSubscription ();
77
- actualOperator .add (subscription ); // add to parent if the Subject itself is unsubscribed
78
75
addedObserver = true ;
79
- subscription .wrap (Subscriptions .create (new Action0 () {
76
+ // add to parent if the Subject itself is unsubscribed
77
+ actualOperator .add (Subscriptions .create (new Action0 () {
80
78
81
79
@ Override
82
80
public void call () {
@@ -85,19 +83,19 @@ public void call() {
85
83
do {
86
84
current = state .get ();
87
85
// on unsubscribe remove it from the map of outbound observers to notify
88
- newState = current .removeObserver (subscription );
86
+ newState = current .removeObserver (observer );
89
87
} while (!state .compareAndSet (current , newState ));
90
88
if (onUnsubscribe != null ) {
91
89
onUnsubscribe .call (observer );
92
90
}
93
91
}
94
92
}));
95
- if (subscription .isUnsubscribed ()) {
96
- addedObserver = false ;
93
+ if (actualOperator .isUnsubscribed ()) {
94
+ // we've been unsubscribed while working so return and do nothing
97
95
return ;
98
96
}
99
97
// on subscribe add it to the map of outbound observers to notify
100
- newState = current .addObserver (subscription , observer );
98
+ newState = current .addObserver (observer );
101
99
}
102
100
} while (!state .compareAndSet (current , newState ));
103
101
@@ -126,7 +124,7 @@ protected Collection<SubjectObserver<? super T>> terminate(Action1<Collection<Su
126
124
}
127
125
} while (!state .compareAndSet (current , newState ));
128
126
129
- Collection <SubjectObserver <? super T >> observerCollection = (Collection )Arrays .asList (newState .observers );
127
+ Collection <SubjectObserver <? super T >> observerCollection = (Collection ) Arrays .asList (newState .observers );
130
128
/*
131
129
* if we get here then we won setting the state to terminated
132
130
* and have a deterministic set of Observers to emit to (concurrent subscribes
@@ -158,97 +156,79 @@ public SubjectObserver<Object>[] rawSnapshot() {
158
156
protected static class State <T > {
159
157
final boolean terminated ;
160
158
final CountDownLatch terminationLatch ;
161
- final Subscription [] subscriptions ;
162
159
final SubjectObserver [] observers ;
163
160
// to avoid lots of empty arrays
164
- final Subscription [] EMPTY_S = new Subscription [0 ];
165
- // to avoid lots of empty arrays
166
161
final SubjectObserver [] EMPTY_O = new SubjectObserver [0 ];
167
162
168
- private State (boolean isTerminated , CountDownLatch terminationLatch ,
169
- Subscription [] subscriptions , SubjectObserver [] observers ) {
163
+ private State (boolean isTerminated , CountDownLatch terminationLatch , SubjectObserver [] observers ) {
170
164
this .terminationLatch = terminationLatch ;
171
165
this .terminated = isTerminated ;
172
- this .subscriptions = subscriptions ;
173
166
this .observers = observers ;
174
167
}
175
168
176
169
State () {
177
170
this .terminated = false ;
178
171
this .terminationLatch = null ;
179
- this .subscriptions = EMPTY_S ;
180
172
this .observers = EMPTY_O ;
181
173
}
182
174
183
175
public State <T > terminate () {
184
176
if (terminated ) {
185
177
throw new IllegalStateException ("Already terminated." );
186
178
}
187
- return new State <T >(true , new CountDownLatch (1 ), subscriptions , observers );
179
+ return new State <T >(true , new CountDownLatch (1 ), observers );
188
180
}
189
181
190
- public State <T > addObserver (Subscription s , SubjectObserver <? super T > observer ) {
182
+ public State <T > addObserver (SubjectObserver <? super T > observer ) {
191
183
int n = this .observers .length ;
192
184
193
- Subscription [] newsubscriptions = Arrays .copyOf (this .subscriptions , n + 1 );
194
185
SubjectObserver [] newobservers = Arrays .copyOf (this .observers , n + 1 );
195
186
196
- newsubscriptions [n ] = s ;
197
187
newobservers [n ] = observer ;
198
188
199
- return createNewWith (newsubscriptions , newobservers );
189
+ return createNewWith (newobservers );
200
190
}
201
191
202
- private State <T > createNewWith (Subscription [] newsubscriptions , SubjectObserver [] newobservers ) {
203
- return new State <T >(terminated , terminationLatch , newsubscriptions , newobservers );
192
+ private State <T > createNewWith (SubjectObserver [] newobservers ) {
193
+ return new State <T >(terminated , terminationLatch , newobservers );
204
194
}
205
195
206
- public State <T > removeObserver (Subscription s ) {
196
+ public State <T > removeObserver (SubjectObserver <? super T > o ) {
207
197
// we are empty, nothing to remove
208
198
if (this .observers .length == 0 ) {
209
199
return this ;
210
- } else
211
- if (this .observers .length == 1 ) {
212
- if (this .subscriptions [0 ].equals (s )) {
213
- return createNewWith (EMPTY_S , EMPTY_O );
214
- }
215
- return this ;
216
200
}
201
+
217
202
int n = this .observers .length - 1 ;
218
203
int copied = 0 ;
219
- Subscription [] newsubscriptions = new Subscription [n ];
220
204
SubjectObserver [] newobservers = new SubjectObserver [n ];
221
205
222
- for (int i = 0 ; i < this .subscriptions .length ; i ++) {
223
- Subscription s0 = this .subscriptions [i ];
224
- if (!s0 .equals (s )) {
206
+ for (int i = 0 ; i < this .observers .length ; i ++) {
207
+ SubjectObserver s0 = this .observers [i ];
208
+ if (!s0 .equals (o )) {
225
209
if (copied == n ) {
226
210
// if s was not found till the end of the iteration
227
211
// we return ourselves since no modification should
228
212
// have happened
229
213
return this ;
230
214
}
231
- newsubscriptions [copied ] = s0 ;
232
- newobservers [copied ] = this .observers [i ];
215
+ newobservers [copied ] = s0 ;
233
216
copied ++;
234
217
}
235
218
}
236
219
237
220
if (copied == 0 ) {
238
- return createNewWith (EMPTY_S , EMPTY_O );
221
+ return createNewWith (EMPTY_O );
239
222
}
240
223
// if somehow copied less than expected, truncate the arrays
241
224
// if s is unique, this should never happen
242
225
if (copied < n ) {
243
- Subscription [] newsubscriptions2 = new Subscription [copied ];
244
- System .arraycopy (newsubscriptions , 0 , newsubscriptions2 , 0 , copied );
245
-
246
226
SubjectObserver [] newobservers2 = new SubjectObserver [copied ];
247
227
System .arraycopy (newobservers , 0 , newobservers2 , 0 , copied );
248
228
249
- return createNewWith (newsubscriptions2 , newobservers2 );
229
+ return createNewWith (newobservers2 );
250
230
}
251
- return createNewWith (newsubscriptions , newobservers );
231
+ return createNewWith (newobservers );
252
232
}
253
233
}
254
234
0 commit comments