2020import java .util .Collection ;
2121import java .util .LinkedList ;
2222import java .util .List ;
23+ import java .util .concurrent .locks .ReentrantLock ;
2324
2425import rx .Subscription ;
25- import rx .exceptions .* ;
26+ import rx .exceptions .Exceptions ;
2627
2728/**
2829 * Subscription that represents a group of Subscriptions that are unsubscribed together.
@@ -33,6 +34,7 @@ public final class SubscriptionList implements Subscription {
3334
3435 private LinkedList <Subscription > subscriptions ;
3536 private volatile boolean unsubscribed ;
37+ private final ReentrantLock lock = new ReentrantLock ();
3638
3739 public SubscriptionList () {
3840 }
@@ -64,14 +66,19 @@ public void add(final Subscription s) {
6466 return ;
6567 }
6668 if (!unsubscribed ) {
67- synchronized (this ) {
69+ lock .lock ();
70+ try {
6871 if (!unsubscribed ) {
69- if (subscriptions == null ) {
70- subscriptions = new LinkedList <Subscription >();
72+ LinkedList <Subscription > subs = subscriptions ;
73+ if (subs == null ) {
74+ subs = new LinkedList <Subscription >();
75+ subscriptions = subs ;
7176 }
72- subscriptions .add (s );
77+ subs .add (s );
7378 return ;
7479 }
80+ } finally {
81+ lock .unlock ();
7582 }
7683 }
7784 // call after leaving the synchronized block so we're not holding a lock while executing this
@@ -81,11 +88,15 @@ public void add(final Subscription s) {
8188 public void remove (final Subscription s ) {
8289 if (!unsubscribed ) {
8390 boolean unsubscribe = false ;
84- synchronized (this ) {
85- if (unsubscribed || subscriptions == null ) {
91+ lock .lock ();
92+ try {
93+ LinkedList <Subscription > subs = subscriptions ;
94+ if (unsubscribed || subs == null ) {
8695 return ;
8796 }
88- unsubscribe = subscriptions .remove (s );
97+ unsubscribe = subs .remove (s );
98+ } finally {
99+ lock .unlock ();
89100 }
90101 if (unsubscribe ) {
91102 // if we removed successfully we then need to call unsubscribe on it (outside of the lock)
@@ -102,13 +113,16 @@ public void remove(final Subscription s) {
102113 public void unsubscribe () {
103114 if (!unsubscribed ) {
104115 List <Subscription > list ;
105- synchronized (this ) {
116+ lock .lock ();
117+ try {
106118 if (unsubscribed ) {
107119 return ;
108120 }
109121 unsubscribed = true ;
110122 list = subscriptions ;
111123 subscriptions = null ;
124+ } finally {
125+ lock .unlock ();
112126 }
113127 // we will only get here once
114128 unsubscribeFromAll (list );
@@ -136,9 +150,12 @@ private static void unsubscribeFromAll(Collection<Subscription> subscriptions) {
136150 public void clear () {
137151 if (!unsubscribed ) {
138152 List <Subscription > list ;
139- synchronized (this ) {
153+ lock .lock ();
154+ try {
140155 list = subscriptions ;
141156 subscriptions = null ;
157+ } finally {
158+ lock .unlock ();
142159 }
143160 unsubscribeFromAll (list );
144161 }
@@ -149,8 +166,11 @@ public void clear() {
149166 */
150167 public boolean hasSubscriptions () {
151168 if (!unsubscribed ) {
152- synchronized (this ) {
169+ lock .lock ();
170+ try {
153171 return !unsubscribed && subscriptions != null && !subscriptions .isEmpty ();
172+ } finally {
173+ lock .unlock ();
154174 }
155175 }
156176 return false ;
0 commit comments