Skip to content

Commit 5918265

Browse files
Refactor MultipleAssignment
- simplified state machine
1 parent c3ee348 commit 5918265

File tree

1 file changed

+54
-20
lines changed

1 file changed

+54
-20
lines changed

rxjava-core/src/main/java/rx/subscriptions/MultipleAssignmentSubscription.java

Lines changed: 54 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -25,43 +25,77 @@
2525
*
2626
* @see <a href="http://msdn.microsoft.com/en-us/library/system.reactive.disposables.multipleassignmentdisposable">Rx.Net equivalent MultipleAssignmentDisposable</a>
2727
*/
28-
public class MultipleAssignmentSubscription implements Subscription {
29-
private AtomicReference<Subscription> reference = new AtomicReference<Subscription>();
30-
/** Sentinel for the unsubscribed state. */
31-
private static final Subscription UNSUBSCRIBED_SENTINEL = new Subscription() {
32-
@Override
33-
public void unsubscribe() {
28+
public final class MultipleAssignmentSubscription implements Subscription {
29+
30+
private final AtomicReference<State> state = new AtomicReference<State>(new State(false, Subscriptions.empty()));
31+
32+
private static final class State {
33+
final boolean isUnsubscribed;
34+
final Subscription subscription;
35+
36+
State(boolean u, Subscription s) {
37+
this.isUnsubscribed = u;
38+
this.subscription = s;
39+
}
40+
41+
State unsubscribe() {
42+
return new State(true, subscription);
3443
}
35-
};
44+
45+
State set(Subscription s) {
46+
return new State(isUnsubscribed, s);
47+
}
48+
49+
}
3650

3751
public boolean isUnsubscribed() {
38-
return reference.get() == UNSUBSCRIBED_SENTINEL;
52+
return state.get().isUnsubscribed;
3953
}
4054

4155
@Override
4256
public void unsubscribe() {
43-
Subscription s = reference.getAndSet(UNSUBSCRIBED_SENTINEL);
44-
if (s != null) {
45-
s.unsubscribe();
46-
}
57+
State oldState;
58+
State newState;
59+
do {
60+
oldState = state.get();
61+
if (oldState.isUnsubscribed) {
62+
return;
63+
} else {
64+
newState = oldState.unsubscribe();
65+
}
66+
} while (!state.compareAndSet(oldState, newState));
67+
oldState.subscription.unsubscribe();
4768
}
4869

70+
@Deprecated
4971
public void setSubscription(Subscription s) {
72+
set(s);
73+
}
74+
75+
public void set(Subscription s) {
76+
if (s == null) {
77+
throw new IllegalArgumentException("Subscription can not be null");
78+
}
79+
State oldState;
80+
State newState;
5081
do {
51-
Subscription r = reference.get();
52-
if (r == UNSUBSCRIBED_SENTINEL) {
82+
oldState = state.get();
83+
if (oldState.isUnsubscribed) {
5384
s.unsubscribe();
5485
return;
86+
} else {
87+
newState = oldState.set(s);
5588
}
56-
if (reference.compareAndSet(r, s)) {
57-
break;
58-
}
59-
} while (true);
89+
} while (!state.compareAndSet(oldState, newState));
6090
}
6191

92+
@Deprecated
6293
public Subscription getSubscription() {
63-
Subscription s = reference.get();
64-
return s != UNSUBSCRIBED_SENTINEL ? s : Subscriptions.empty();
94+
return get();
95+
}
96+
97+
public Subscription get() {
98+
return state.get().subscription;
6599
}
66100

67101
}

0 commit comments

Comments
 (0)