All Downloads are FREE. Search and download functionalities are using the official Maven repository.

rx.internal.operators.OnSubscribeAmb Maven / Gradle / Ivy

/**
 * Copyright 2014 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.internal.operators;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

import rx.Observable;
import rx.Observable.OnSubscribe;
import rx.Subscriber;

/**
 * Given multiple {@link Observable}s, propagates the one that first emits an item.
 */
public final class OnSubscribeAmb implements OnSubscribe{

    /**
     * Given two {@link Observable}s, propagates the one that first emits an item.
     *
     * @param o1
     *          the first {@code Observable}
     * @param o2
     *          the second {@code Observable}
     * @return an {@code Observable} that mirrors the one of the source {@code Observable}s that was first to
     *         emit an item
     */
    public static  OnSubscribe amb(Observable o1, Observable o2) {
        List> sources = new ArrayList>();
        sources.add(o1);
        sources.add(o2);
        return amb(sources);
    }

    /**
     * Given three {@link Observable}s, propagates the one that first emits an item.
     *
     * @param o1
     *          the first {@code Observable}
     * @param o2
     *          the second {@code Observable}
     * @param o3
     *          the third {@code Observable}
     * @return an {@code Observable} that mirrors the one of the source {@code Observable}s that was first to
     *         emit an item
     */
    public static  OnSubscribe amb(Observable o1, Observable o2, Observable o3) {
        List> sources = new ArrayList>();
        sources.add(o1);
        sources.add(o2);
        sources.add(o3);
        return amb(sources);
    }

    /**
     * Given four {@link Observable}s, propagates the one that first emits an item.
     *
     * @param o1
     *          the first {@code Observable}
     * @param o2
     *          the second {@code Observable}
     * @param o3
     *          the third {@code Observable}
     * @param o4
     *          the fourth {@code Observable}
     * @return an {@code Observable} that mirrors the one of the source {@code Observable}s that was first to
     *         emit an item
     */
    public static  OnSubscribe amb(Observable o1, Observable o2, Observable o3, Observable o4) {
        List> sources = new ArrayList>();
        sources.add(o1);
        sources.add(o2);
        sources.add(o3);
        sources.add(o4);
        return amb(sources);
    }

    /**
     * Given five {@link Observable}s, propagates the one that first emits an item.
     *
     * @param o1
     *          the first {@code Observable}
     * @param o2
     *          the second {@code Observable}
     * @param o3
     *          the third {@code Observable}
     * @param o4
     *          the fourth {@code Observable}
     * @param o5
     *          the fifth {@code Observable}
     * @return an {@code Observable} that mirrors the one of the source {@code Observable}s that was first to
     *         emit an item
     */
    public static  OnSubscribe amb(Observable o1, Observable o2, Observable o3, Observable o4, Observable o5) {
        List> sources = new ArrayList>();
        sources.add(o1);
        sources.add(o2);
        sources.add(o3);
        sources.add(o4);
        sources.add(o5);
        return amb(sources);
    }

    /**
     * Given six {@link Observable}s, propagates the one that first emits an item.
     *
     * @param o1
     *          the first {@code Observable}
     * @param o2
     *          the second {@code Observable}
     * @param o3
     *          the third {@code Observable}
     * @param o4
     *          the fourth {@code Observable}
     * @param o5
     *          the fifth {@code Observable}
     * @param o6
     *          the sixth {@code Observable}
     * @return an {@code Observable} that mirrors the one of the source {@code Observable}s that was first to
     *         emit an item
     */
    public static  OnSubscribe amb(Observable o1, Observable o2, Observable o3, Observable o4, Observable o5, Observable o6) {
        List> sources = new ArrayList>();
        sources.add(o1);
        sources.add(o2);
        sources.add(o3);
        sources.add(o4);
        sources.add(o5);
        sources.add(o6);
        return amb(sources);
    }

    /**
     * Given seven {@link Observable}s, propagates the one that first emits an item.
     *
     * @param o1
     *          the first {@code Observable}
     * @param o2
     *          the second {@code Observable}
     * @param o3
     *          the third {@code Observable}
     * @param o4
     *          the fourth {@code Observable}
     * @param o5
     *          the fifth {@code Observable}
     * @param o6
     *          the sixth {@code Observable}
     * @param o7
     *          the seventh {@code Observable}
     * @return an {@code Observable} that mirrors the one of the source {@code Observable}s that was first to
     *         emit an item
     */
    public static  OnSubscribe amb(Observable o1, Observable o2, Observable o3, Observable o4, Observable o5, Observable o6, Observable o7) {
        List> sources = new ArrayList>();
        sources.add(o1);
        sources.add(o2);
        sources.add(o3);
        sources.add(o4);
        sources.add(o5);
        sources.add(o6);
        sources.add(o7);
        return amb(sources);
    }

    /**
     * Given eight {@link Observable}s, propagates the one that first emits an item.
     *
     * @param o1
     *          the first {@code Observable}
     * @param o2
     *          the second {@code Observable}
     * @param o3
     *          the third {@code Observable}
     * @param o4
     *          the fourth {@code Observable}
     * @param o5
     *          the fifth {@code Observable}
     * @param o6
     *          the sixth {@code Observable}
     * @param o7
     *          the seventh {@code Observable}
     * @param o8
     *          the eighth {@code Observable}
     * @return an {@code Observable} that mirrors the one of the source {@code Observable}s that was first to
     *         emit an item
     */
    public static  OnSubscribe amb(Observable o1, Observable o2, Observable o3, Observable o4, Observable o5, Observable o6, Observable o7, Observable o8) {
        List> sources = new ArrayList>();
        sources.add(o1);
        sources.add(o2);
        sources.add(o3);
        sources.add(o4);
        sources.add(o5);
        sources.add(o6);
        sources.add(o7);
        sources.add(o8);
        return amb(sources);
    }

    /**
     * Given nine {@link Observable}s, propagates the one that first emits an item.
     *
     * @param o1
     *          the first {@code Observable}
     * @param o2
     *          the second {@code Observable}
     * @param o3
     *          the third {@code Observable}
     * @param o4
     *          the fourth {@code Observable}
     * @param o5
     *          the fifth {@code Observable}
     * @param o6
     *          the sixth {@code Observable}
     * @param o7
     *          the seventh {@code Observable}
     * @param o8
     *          the eighth {@code Observable}
     * @param o9
     *          the ninth {@code Observable}
     * @return an {@code Observable} that mirrors the one of the source {@code Observable}s that was first to
     *         emit an item
     */
    public static  OnSubscribe amb(Observable o1, Observable o2, Observable o3, Observable o4, Observable o5, Observable o6, Observable o7, Observable o8, Observable o9) {
        List> sources = new ArrayList>();
        sources.add(o1);
        sources.add(o2);
        sources.add(o3);
        sources.add(o4);
        sources.add(o5);
        sources.add(o6);
        sources.add(o7);
        sources.add(o8);
        sources.add(o9);
        return amb(sources);
    }

    /**
     * Given a set of {@link Observable}s, propagates the one that first emits an item.
     *
     * @param sources
     *          an {@code Iterable} of {@code Observable}s
     * @return an {@code Observable} that mirrors the one of the {@code Observable}s in {@code sources} that was
     *         the first to emit an item
     */
    public static  OnSubscribe amb(final Iterable> sources) {
        return new OnSubscribeAmb(sources);
    }

    private static final class AmbSubscriber extends Subscriber {

        private static final int NONE = -1;

        private final Subscriber subscriber;
        private final int index;
        private final AtomicInteger choice;

        private AmbSubscriber(Subscriber subscriber, int index, AtomicInteger choice) {
            this.subscriber = subscriber;
            this.choice = choice;
            this.index = index;
        }

        @Override
        public void onNext(T args) {
            if (!isSelected()) {
                unsubscribe();
                return;
            }
            subscriber.onNext(args);
        }

        @Override
        public void onCompleted() {
            if (!isSelected()) {
                unsubscribe();
                return;
            }
            subscriber.onCompleted();
        }

        @Override
        public void onError(Throwable e) {
            if (!isSelected()) {
                unsubscribe();
                return;
            }
            subscriber.onError(e);
        }

        private boolean isSelected() {
            int ch = choice.get();
            if (ch == NONE) {
                return choice.compareAndSet(NONE, index);
            }
            return ch == index;
        }
    }

    private final Iterable> sources;

    private OnSubscribeAmb(Iterable> sources) {
        this.sources = sources;
    }

    @Override
    public void call(Subscriber subscriber) {
        AtomicInteger choice = new AtomicInteger(AmbSubscriber.NONE);
        int index = 0;
        for (Observable source : sources) {
            if (subscriber.isUnsubscribed()) {
                break;
            }
            if (choice.get() != AmbSubscriber.NONE) {
                // Already choose someone, the rest Observables can be skipped.
                break;
            }
            AmbSubscriber ambSubscriber = new AmbSubscriber(subscriber, index, choice);
            subscriber.add(ambSubscriber);
            source.unsafeSubscribe(ambSubscriber);
            index++;
        }
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy