17
17
18
18
import java .util .concurrent .atomic .AtomicBoolean ;
19
19
import java .util .concurrent .atomic .AtomicInteger ;
20
- import java .util .concurrent .locks .ReadWriteLock ;
21
- import java .util .concurrent .locks .ReentrantReadWriteLock ;
20
+ import java .util .concurrent .locks .ReentrantLock ;
22
21
23
22
import rx .Observable .OnSubscribe ;
24
23
import rx .Subscriber ;
@@ -43,10 +42,9 @@ public final class OnSubscribeRefCount<T> implements OnSubscribe<T> {
43
42
private final AtomicInteger subscriptionCount = new AtomicInteger (0 );
44
43
45
44
/**
46
- * Ensures that subscribers wait for the first subscription to be assigned
47
- * to baseSubcription before being subscribed themselves.
45
+ * Use this lock for every subscription and disconnect action.
48
46
*/
49
- private final ReadWriteLock lock = new ReentrantReadWriteLock ();
47
+ private final ReentrantLock lock = new ReentrantLock ();
50
48
51
49
/**
52
50
* Constructor.
@@ -61,48 +59,26 @@ public OnSubscribeRefCount(ConnectableObservable<? extends T> source) {
61
59
@ Override
62
60
public void call (final Subscriber <? super T > subscriber ) {
63
61
62
+ lock .lock ();
64
63
if (subscriptionCount .incrementAndGet () == 1 ) {
65
64
66
- // ensure secondary subscriptions wait for baseSubscription to be
67
- // set by first subscription
68
- lock .writeLock ().lock ();
69
-
70
65
final AtomicBoolean writeLocked = new AtomicBoolean (true );
71
-
66
+
72
67
try {
73
68
// need to use this overload of connect to ensure that
74
- // baseSubscription is set in the case that source is a synchronous
75
- // Observable
76
- source .connect (new Action1 <Subscription >() {
77
- @ Override
78
- public void call (Subscription subscription ) {
79
-
80
- try {
81
- baseSubscription .add (subscription );
82
-
83
- // handle unsubscribing from the base subscription
84
- subscriber .add (disconnect ());
85
-
86
- // ready to subscribe to source so do it
87
- source .unsafeSubscribe (subscriber );
88
- } finally {
89
- // release the write lock
90
- lock .writeLock ().unlock ();
91
- writeLocked .set (false );
92
- }
93
- }
94
- });
69
+ // baseSubscription is set in the case that source is a
70
+ // synchronous Observable
71
+ source .connect (onSubscribe (subscriber , writeLocked ));
95
72
} finally {
96
73
// need to cover the case where the source is subscribed to
97
- // outside of this class thus preventing the above Action1
74
+ // outside of this class thus preventing the above Action1
98
75
// being called
99
76
if (writeLocked .get ()) {
100
77
// Action1 was not called
101
- lock .writeLock (). unlock ();
78
+ lock .unlock ();
102
79
}
103
80
}
104
81
} else {
105
- lock .readLock ().lock ();
106
82
try {
107
83
// handle unsubscribing from the base subscription
108
84
subscriber .add (disconnect ());
@@ -111,22 +87,49 @@ public void call(Subscription subscription) {
111
87
source .unsafeSubscribe (subscriber );
112
88
} finally {
113
89
// release the read lock
114
- lock .readLock (). unlock ();
90
+ lock .unlock ();
115
91
}
116
92
}
117
93
118
94
}
119
95
96
+ private Action1 <Subscription > onSubscribe (final Subscriber <? super T > subscriber ,
97
+ final AtomicBoolean writeLocked ) {
98
+ return new Action1 <Subscription >() {
99
+ @ Override
100
+ public void call (Subscription subscription ) {
101
+
102
+ try {
103
+ baseSubscription .add (subscription );
104
+
105
+ // handle unsubscribing from the base subscription
106
+ subscriber .add (disconnect ());
107
+
108
+ // ready to subscribe to source so do it
109
+ source .unsafeSubscribe (subscriber );
110
+ } finally {
111
+ // release the write lock
112
+ lock .unlock ();
113
+ writeLocked .set (false );
114
+ }
115
+ }
116
+ };
117
+ }
118
+
120
119
private Subscription disconnect () {
121
120
return Subscriptions .create (new Action0 () {
122
121
@ Override
123
122
public void call () {
124
- if (subscriptionCount .decrementAndGet () == 0 ) {
125
- baseSubscription .unsubscribe ();
126
-
127
- // need a new baseSubscription because once unsubscribed
128
- // stays that way
129
- baseSubscription = new CompositeSubscription ();
123
+ lock .lock ();
124
+ try {
125
+ if (subscriptionCount .decrementAndGet () == 0 ) {
126
+ baseSubscription .unsubscribe ();
127
+ // need a new baseSubscription because once
128
+ // unsubscribed stays that way
129
+ baseSubscription = new CompositeSubscription ();
130
+ }
131
+ } finally {
132
+ lock .unlock ();
130
133
}
131
134
}
132
135
});
0 commit comments