38
38
* the result value type
39
39
*/
40
40
public final class OperatorMulticast <T , R > extends ConnectableObservable <R > {
41
- final Observable <? extends T > source ;
42
- final Object guard ;
43
- final Func0 <? extends Subject <? super T , ? extends R >> subjectFactory ;
41
+ private final Observable <? extends T > source ;
42
+ private final Object guard ;
43
+ private final Func0 <? extends Subject <? super T , ? extends R >> subjectFactory ;
44
44
private final AtomicReference <Subject <? super T , ? extends R >> connectedSubject ;
45
45
private final List <Subscriber <? super R >> waitingForConnect ;
46
46
47
47
/** Guarded by guard. */
48
- Subscriber <T > subscription ;
48
+ private Subscriber <T > subscription ;
49
+ // wraps subscription above with for unsubscription using guard
50
+ private Subscription guardedSubscription ;
49
51
50
52
public OperatorMulticast (Observable <? extends T > source , final Func0 <? extends Subject <? super T , ? extends R >> subjectFactory ) {
51
53
this (new Object (), new AtomicReference <Subject <? super T , ? extends R >>(), new ArrayList <Subscriber <? super R >>(), source , subjectFactory );
@@ -82,7 +84,8 @@ public void connect(Action1<? super Subscription> connection) {
82
84
// subscription is the state of whether we are connected or not
83
85
synchronized (guard ) {
84
86
if (subscription != null ) {
85
- // already connected, return as there is nothing to do
87
+ // already connected
88
+ connection .call (guardedSubscription );
86
89
return ;
87
90
} else {
88
91
shouldSubscribe = true ;
@@ -106,6 +109,21 @@ public void onNext(T args) {
106
109
subject .onNext (args );
107
110
}
108
111
};
112
+ guardedSubscription = Subscriptions .create (new Action0 () {
113
+ @ Override
114
+ public void call () {
115
+ Subscription s ;
116
+ synchronized (guard ) {
117
+ s = subscription ;
118
+ subscription = null ;
119
+ guardedSubscription = null ;
120
+ connectedSubject .set (null );
121
+ }
122
+ if (s != null ) {
123
+ s .unsubscribe ();
124
+ }
125
+ }
126
+ });
109
127
110
128
// register any subscribers that are waiting with this new subject
111
129
for (Subscriber <? super R > s : waitingForConnect ) {
@@ -116,34 +134,22 @@ public void onNext(T args) {
116
134
// record the Subject so OnSubscribe can see it
117
135
connectedSubject .set (subject );
118
136
}
137
+
119
138
}
120
139
121
140
// in the lock above we determined we should subscribe, do it now outside the lock
122
141
if (shouldSubscribe ) {
123
142
// register a subscription that will shut this down
124
- connection .call (Subscriptions .create (new Action0 () {
125
- @ Override
126
- public void call () {
127
- Subscription s ;
128
- synchronized (guard ) {
129
- s = subscription ;
130
- subscription = null ;
131
- connectedSubject .set (null );
132
- }
133
- if (s != null ) {
134
- s .unsubscribe ();
135
- }
136
- }
137
- }));
143
+ connection .call (guardedSubscription );
138
144
139
145
// now that everything is hooked up let's subscribe
140
146
// as long as the subscription is not null (which can happen if already unsubscribed)
141
- boolean subscriptionIsNull ;
142
- synchronized (guard ) {
143
- subscriptionIsNull = subscription == null ;
147
+ Subscriber < T > sub ;
148
+ synchronized (guard ) {
149
+ sub = subscription ;
144
150
}
145
- if (! subscriptionIsNull )
146
- source .subscribe (subscription );
151
+ if (sub != null )
152
+ source .subscribe (sub );
147
153
}
148
154
}
149
155
}
0 commit comments