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

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

There is a newer version: 0.20.7
Show newest version
 /**
  * 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.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
import rx.Observable;
import rx.Observable.Operator;
import rx.Subscriber;
import rx.functions.Action0;
import rx.observers.SerializedSubscriber;
import rx.subscriptions.SerialSubscription;
import rx.subscriptions.Subscriptions;

/**
 * Returns an Observable that emits the items emitted by two or more Observables, one after the
 * other.
 * 

* * @param the source and result value type */ public final class OperatorConcat implements Operator> { @Override public Subscriber> call(final Subscriber child) { final SerializedSubscriber s = new SerializedSubscriber(child); final SerialSubscription current = new SerialSubscription(); child.add(current); return new ConcatSubscriber(s, current); } static final class ConcatSubscriber extends Subscriber> { final NotificationLite> nl = NotificationLite.instance(); private final Subscriber s; private final SerialSubscription current; final ConcurrentLinkedQueue queue; volatile int wip; @SuppressWarnings("rawtypes") static final AtomicIntegerFieldUpdater WIP_UPDATER = AtomicIntegerFieldUpdater.newUpdater(ConcatSubscriber.class, "wip"); public ConcatSubscriber(Subscriber s, SerialSubscription current) { super(s); this.s = s; this.current = current; this.queue = new ConcurrentLinkedQueue(); add(Subscriptions.create(new Action0() { @Override public void call() { queue.clear(); } })); } @Override public void onNext(Observable t) { queue.add(nl.next(t)); if (WIP_UPDATER.getAndIncrement(this) == 0) { subscribeNext(); } } @Override public void onError(Throwable e) { s.onError(e); unsubscribe(); } @Override public void onCompleted() { queue.add(nl.completed()); if (WIP_UPDATER.getAndIncrement(this) == 0) { subscribeNext(); } } void completeInner() { if (WIP_UPDATER.decrementAndGet(this) > 0) { subscribeNext(); } } void subscribeNext() { Object o = queue.poll(); if (nl.isCompleted(o)) { s.onCompleted(); } else if (o != null) { Observable obs = nl.getValue(o); Subscriber sourceSub = new Subscriber() { @Override public void onNext(T t) { s.onNext(t); } @Override public void onError(Throwable e) { ConcatSubscriber.this.onError(e); } @Override public void onCompleted() { completeInner(); } }; current.set(sourceSub); obs.unsafeSubscribe(sourceSub); } } } }