31
31
public final class CompositeSubscription implements Subscription {
32
32
33
33
private Set <Subscription > subscriptions ;
34
- private boolean unsubscribed = false ;
34
+ private volatile boolean unsubscribed ;
35
35
36
36
public CompositeSubscription () {
37
37
}
@@ -41,7 +41,7 @@ public CompositeSubscription(final Subscription... subscriptions) {
41
41
}
42
42
43
43
@ Override
44
- public synchronized boolean isUnsubscribed () {
44
+ public boolean isUnsubscribed () {
45
45
return unsubscribed ;
46
46
}
47
47
@@ -58,21 +58,19 @@ public void add(final Subscription s) {
58
58
if (s .isUnsubscribed ()) {
59
59
return ;
60
60
}
61
- Subscription unsubscribe = null ;
62
- synchronized (this ) {
63
- if (unsubscribed ) {
64
- unsubscribe = s ;
65
- } else {
66
- if (subscriptions == null ) {
67
- subscriptions = new HashSet <Subscription >(4 );
61
+ if (!unsubscribed ) {
62
+ synchronized (this ) {
63
+ if (!unsubscribed ) {
64
+ if (subscriptions == null ) {
65
+ subscriptions = new HashSet <Subscription >(4 );
66
+ }
67
+ subscriptions .add (s );
68
+ return ;
68
69
}
69
- subscriptions .add (s );
70
70
}
71
71
}
72
- if (unsubscribe != null ) {
73
- // call after leaving the synchronized block so we're not holding a lock while executing this
74
- unsubscribe .unsubscribe ();
75
- }
72
+ // call after leaving the synchronized block so we're not holding a lock while executing this
73
+ s .unsubscribe ();
76
74
}
77
75
78
76
/**
@@ -83,16 +81,18 @@ public void add(final Subscription s) {
83
81
* the {@link Subscription} to remove
84
82
*/
85
83
public void remove (final Subscription s ) {
86
- boolean unsubscribe = false ;
87
- synchronized (this ) {
88
- if (unsubscribed || subscriptions == null ) {
89
- return ;
84
+ if (!unsubscribed ) {
85
+ boolean unsubscribe = false ;
86
+ synchronized (this ) {
87
+ if (unsubscribed || subscriptions == null ) {
88
+ return ;
89
+ }
90
+ unsubscribe = subscriptions .remove (s );
91
+ }
92
+ if (unsubscribe ) {
93
+ // if we removed successfully we then need to call unsubscribe on it (outside of the lock)
94
+ s .unsubscribe ();
90
95
}
91
- unsubscribe = subscriptions .remove (s );
92
- }
93
- if (unsubscribe ) {
94
- // if we removed successfully we then need to call unsubscribe on it (outside of the lock)
95
- s .unsubscribe ();
96
96
}
97
97
}
98
98
@@ -102,28 +102,35 @@ public void remove(final Subscription s) {
102
102
* an unoperative state.
103
103
*/
104
104
public void clear () {
105
- Collection <Subscription > unsubscribe = null ;
106
- synchronized (this ) {
107
- if (unsubscribed || subscriptions == null ) {
108
- return ;
109
- } else {
110
- unsubscribe = subscriptions ;
111
- subscriptions = null ;
105
+ if (!unsubscribed ) {
106
+ Collection <Subscription > unsubscribe = null ;
107
+ synchronized (this ) {
108
+ if (unsubscribed || subscriptions == null ) {
109
+ return ;
110
+ } else {
111
+ unsubscribe = subscriptions ;
112
+ subscriptions = null ;
113
+ }
112
114
}
115
+ unsubscribeFromAll (unsubscribe );
113
116
}
114
- unsubscribeFromAll (unsubscribe );
115
117
}
116
118
117
119
@ Override
118
120
public void unsubscribe () {
119
- synchronized (this ) {
120
- if (unsubscribed ) {
121
- return ;
121
+ if (!unsubscribed ) {
122
+ Collection <Subscription > unsubscribe = null ;
123
+ synchronized (this ) {
124
+ if (unsubscribed ) {
125
+ return ;
126
+ }
127
+ unsubscribed = true ;
128
+ unsubscribe = subscriptions ;
129
+ subscriptions = null ;
122
130
}
123
- unsubscribed = true ;
131
+ // we will only get here once
132
+ unsubscribeFromAll (unsubscribe );
124
133
}
125
- // we will only get here once
126
- unsubscribeFromAll (subscriptions );
127
134
}
128
135
129
136
private static void unsubscribeFromAll (Collection <Subscription > subscriptions ) {
@@ -143,4 +150,16 @@ private static void unsubscribeFromAll(Collection<Subscription> subscriptions) {
143
150
}
144
151
Exceptions .throwIfAny (es );
145
152
}
153
+ /**
154
+ * Returns true if this composite is not unsubscribed and contains subscriptions.
155
+ * @return {@code true} if this composite is not unsubscribed and contains subscriptions.
156
+ */
157
+ public boolean hasSubscriptions () {
158
+ if (!unsubscribed ) {
159
+ synchronized (this ) {
160
+ return !unsubscribed && subscriptions != null && !subscriptions .isEmpty ();
161
+ }
162
+ }
163
+ return false ;
164
+ }
146
165
}
0 commit comments