/**
 * Copyright 2013 Netflix, Inc.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package rx.subscriptions;

import java.util.concurrent.atomic.AtomicReference;

import rx.Observable;
import rx.Subscription;

/**
 * Subscription that can be checked for status such as in a loop inside an {@link Observable} to exit the loop if unsubscribed.
 * 
 * @see <a href="http://msdn.microsoft.com/en-us/library/system.reactive.disposables.multipleassignmentdisposable">Rx.Net equivalent MultipleAssignmentDisposable</a>
 */
public class MultipleAssignmentSubscription implements Subscription {
    private AtomicReference<Subscription> reference = new AtomicReference<Subscription>();
    /** Sentinel for the unsubscribed state. */
    private static final Subscription UNSUBSCRIBED_SENTINEL = new Subscription() {
        @Override
        public void unsubscribe() {
        }
    };

    public boolean isUnsubscribed() {
        return reference.get() == UNSUBSCRIBED_SENTINEL;
    }

    @Override
    public void unsubscribe() {
        Subscription s = reference.getAndSet(UNSUBSCRIBED_SENTINEL);
        if (s != null) {
            s.unsubscribe();
        }
    }

    public void setSubscription(Subscription s) {
        do {
            Subscription r = reference.get();
            if (r == UNSUBSCRIBED_SENTINEL) {
                s.unsubscribe();
                return;
            }
            if (reference.compareAndSet(r, s)) {
                break;
            }
        } while (true);
    }

    public Subscription getSubscription() {
        Subscription s = reference.get();
        return s != UNSUBSCRIBED_SENTINEL ? s : Subscriptions.empty();
    }

}

@@ -1030,16 +1030,22 @@
 %0Apublic 
+final 
 class Mu
@@ -1099,16 +1099,17 @@
 ption %7B%0A
+%0A
     priv
@@ -1112,16 +1112,22 @@
 private 
+final 
 AtomicRe
@@ -1139,29 +1139,18 @@
 ce%3CS
-ubscription%3E referenc
+tate%3E stat
 e = 
@@ -1174,194 +1174,461 @@
 ce%3CS
-ubscription%3E();%0A    /** Sentinel for the unsubscribed state. */%0A    private static final Subscription UNSUBSCRIBED_SENTINEL = new Subscription() %7B%0A        @Override%0A        public void u
+tate%3E(new State(false, Subscriptions.empty()));%0A%0A    private static final class State %7B%0A        final boolean isUnsubscribed;%0A        final Subscription subscription;%0A%0A        State(boolean u, Subscription s) %7B%0A            this.isUnsubscribed = u;%0A            this.subscription = s;%0A        %7D%0A%0A        State unsubscribe() %7B%0A            return new State(true, subscription);%0A        %7D%0A%0A        State set(Subscription s) %7B%0A            return new State(isU
 nsub
@@ -1625,36 +1625,38 @@
 te(isUnsubscribe
-() %7B
+d, s);
 %0A        %7D%0A    %7D
@@ -1654,14 +1654,14 @@
   %7D%0A
+%0A
     %7D
-;
 %0A%0A  
@@ -1715,48 +1715,34 @@
 urn 
-reference.get() == UNSUBSCRIBED_SENTINEL
+state.get().isUnsubscribed
 ;%0A  
@@ -1805,65 +1805,93 @@
    S
-ubscription s = reference.getAndSet(UNSUBSCRIBED_SENTINEL
+tate oldState;%0A        State newState;%0A        do %7B%0A            oldState = state.get(
 );%0A 
@@ -1901,38 +1901,123 @@
     
+    
 if (
-s != null) %7B%0A            s
+oldState.isUnsubscribed) %7B%0A                return;%0A            %7D else %7B%0A                newState = oldState
 .uns
@@ -2040,168 +2040,504 @@
     
-%7D%0A    %7D%0A%0A    public void setSubscription(Subscription s) %7B%0A        do %7B%0A            Subscription r = reference.get();%0A            if (r == UNSUBSCRIBED_SENTINEL
+    %7D%0A        %7D while (!state.compareAndSet(oldState, newState));%0A        oldState.subscription.unsubscribe();%0A    %7D%0A%0A    @Deprecated%0A    public void setSubscription(Subscription s) %7B%0A        set(s);%0A    %7D%0A%0A    public void set(Subscription s) %7B%0A        if (s == null) %7B%0A            throw new IllegalArgumentException(%22Subscription can not be null%22);%0A        %7D%0A        State oldState;%0A        State newState;%0A        do %7B%0A            oldState = state.get();%0A            if (oldState.isUnsubscribed
 ) %7B%0A
@@ -2598,32 +2598,39 @@
 n;%0A            %7D
+ else %7B
 %0A            if 
@@ -2630,112 +2630,136 @@
     
-if (reference.compareAndSet(r, s)) %7B%0A                break;%0A            %7D%0A        %7D while (true);%0A    %7D%0A
+    newState = oldState.set(s);%0A            %7D%0A        %7D while (!state.compareAndSet(oldState, newState));%0A    %7D%0A%0A    @Deprecated
 %0A   
@@ -2811,41 +2811,60 @@
     
-Subscription s = reference.
+return get();%0A    %7D%0A%0A    public Subscription 
 get()
-;
+ %7B
 %0A   
@@ -2880,41 +2880,20 @@
 rn s
- != UNSUBSCRIBED_SENTINEL ? s : S
+tate.get().s
 ubsc
@@ -2899,25 +2899,16 @@
 cription
-s.empty()
 ;%0A    %7D%0A

Refactor MultipleAssignment