18
18
import java .util .ArrayList ;
19
19
import java .util .List ;
20
20
import java .util .concurrent .atomic .AtomicReference ;
21
+ import java .util .concurrent .atomic .AtomicReferenceFieldUpdater ;
21
22
22
23
import rx .Subscription ;
23
24
import rx .exceptions .CompositeException ;
29
30
* @see <a href="http://msdn.microsoft.com/en-us/library/system.reactive.disposables.compositedisposable(v=vs.103).aspx">Rx.Net equivalent CompositeDisposable</a>
30
31
*/
31
32
public final class CompositeSubscription implements Subscription {
32
-
33
- private final AtomicReference <State > state = new AtomicReference <State >();
33
+ /** The atomic state updater. */
34
+ static final AtomicReferenceFieldUpdater <CompositeSubscription , State > STATE_UPDATER
35
+ = AtomicReferenceFieldUpdater .newUpdater (CompositeSubscription .class , State .class , "state" );
36
+ /** The subscription state. */
37
+ volatile State state ;
34
38
35
39
/** Empty initial state. */
36
40
private static final State CLEAR_STATE ;
@@ -97,43 +101,45 @@ State clear() {
97
101
}
98
102
99
103
public CompositeSubscription () {
100
- state .set (CLEAR_STATE );
104
+ // this creates only a store-store barrier which is generally faster when
105
+ // CompositeSubscriptions are created in a tight loop.
106
+ STATE_UPDATER .lazySet (this , CLEAR_STATE );
101
107
}
102
108
103
109
public CompositeSubscription (final Subscription ... subscriptions ) {
104
- state . set ( new State (false , subscriptions ));
110
+ STATE_UPDATER . lazySet ( this , new State (false , subscriptions ));
105
111
}
106
112
107
113
@ Override
108
114
public boolean isUnsubscribed () {
109
- return state .get (). isUnsubscribed ;
115
+ return state .isUnsubscribed ;
110
116
}
111
117
112
118
public void add (final Subscription s ) {
113
119
State oldState ;
114
120
State newState ;
115
121
do {
116
- oldState = state . get () ;
122
+ oldState = state ;
117
123
if (oldState .isUnsubscribed ) {
118
124
s .unsubscribe ();
119
125
return ;
120
126
} else {
121
127
newState = oldState .add (s );
122
128
}
123
- } while (!state .compareAndSet (oldState , newState ));
129
+ } while (!STATE_UPDATER .compareAndSet (this , oldState , newState ));
124
130
}
125
131
126
132
public void remove (final Subscription s ) {
127
133
State oldState ;
128
134
State newState ;
129
135
do {
130
- oldState = state . get () ;
136
+ oldState = state ;
131
137
if (oldState .isUnsubscribed ) {
132
138
return ;
133
139
} else {
134
140
newState = oldState .remove (s );
135
141
}
136
- } while (!state .compareAndSet (oldState , newState ));
142
+ } while (!STATE_UPDATER .compareAndSet (this , oldState , newState ));
137
143
// if we removed successfully we then need to call unsubscribe on it
138
144
s .unsubscribe ();
139
145
}
@@ -142,29 +148,25 @@ public void clear() {
142
148
State oldState ;
143
149
State newState ;
144
150
do {
145
- oldState = state . get () ;
151
+ oldState = state ;
146
152
if (oldState .isUnsubscribed ) {
147
153
return ;
148
154
} else {
149
155
newState = oldState .clear ();
150
156
}
151
- } while (!state .compareAndSet (oldState , newState ));
157
+ } while (!STATE_UPDATER .compareAndSet (this , oldState , newState ));
152
158
// if we cleared successfully we then need to call unsubscribe on all previous
153
159
unsubscribeFromAll (oldState .subscriptions );
154
160
}
155
161
156
162
@ Override
157
163
public void unsubscribe () {
158
- State oldState ;
159
- State newState ;
160
- do {
161
- oldState = state .get ();
162
- if (oldState .isUnsubscribed ) {
163
- return ;
164
- } else {
165
- newState = oldState .unsubscribe ();
166
- }
167
- } while (!state .compareAndSet (oldState , newState ));
164
+ State oldState = state ;
165
+ if (oldState .isUnsubscribed ) {
166
+ return ;
167
+ }
168
+ // intrinsics may make this a single instruction and may prevent concurrent add/remove faster
169
+ oldState = STATE_UPDATER .getAndSet (this , oldState .unsubscribe ());
168
170
unsubscribeFromAll (oldState .subscriptions );
169
171
}
170
172
0 commit comments