rx.subjects.UnicastSubject 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.subjects;
import java.util.Queue;
import java.util.concurrent.atomic.*;
import rx.*;
import rx.annotations.Experimental;
import rx.exceptions.*;
import rx.functions.Action0;
import rx.internal.operators.*;
import rx.internal.util.atomic.*;
import rx.internal.util.unsafe.*;
/**
* A Subject variant which buffers events until a single Subscriber arrives and replays them to it
* and potentially switches to direct delivery once the Subscriber caught up and requested an unlimited
* amount. In this case, the buffered values are no longer retained. If the Subscriber
* requests a limited amount, queueing is involved and only those values are retained which
* weren't requested by the Subscriber at that time.
*
* @param the input and output value type
*/
@Experimental
public final class UnicastSubject extends Subject {
final State state;
/**
* Constructs an empty UnicastSubject instance with the default capacity hint of 16 elements.
*
* @param the input and output value type
* @return the created UnicastSubject instance
*/
public static UnicastSubject create() {
return create(16);
}
/**
* Constructs an empty UnicastSubject instance with a capacity hint.
* The capacity hint determines the internal queue's island size: the larger
* it is the less frequent allocation will happen if there is no subscriber
* or the subscriber hasn't caught up.
* @param the input and output value type
* @param capacityHint the capacity hint for the internal queue
* @return the created BufferUntilSubscriber instance
*/
public static UnicastSubject create(int capacityHint) {
State state = new State(capacityHint, null);
return new UnicastSubject(state);
}
/**
* Constructs an empty UnicastSubject instance with a capacity hint and
* an Action0 instance to call if the subject reaches its terminal state
* or the single Subscriber unsubscribes mid-sequence.
* The capacity hint determines the internal queue's island size: the larger
* it is the less frequent allocation will happen if there is no subscriber
* or the subscriber hasn't caught up.
* @param the input and output value type
* @param capacityHint the capacity hint for the internal queue
* @param onTerminated the optional callback to call when subject reaches its terminal state
* or the single Subscriber unsubscribes mid-sequence. It will be called
* at most once.
* @return the created BufferUntilSubscriber instance
*/
public static UnicastSubject create(int capacityHint, Action0 onTerminated) {
State state = new State(capacityHint, onTerminated);
return new UnicastSubject(state);
}
private UnicastSubject(State state) {
super(state);
this.state = state;
}
@Override
public void onNext(T t) {
state.onNext(t);
}
@Override
public void onError(Throwable e) {
state.onError(e);
}
@Override
public void onCompleted() {
state.onCompleted();
}
@Override
public boolean hasObservers() {
return state.subscriber.get() != null;
}
/**
* The single-consumption replaying state.
*
* @param the value type
*/
static final class State extends AtomicLong implements Producer, Observer, OnSubscribe, Subscription {
/** */
private static final long serialVersionUID = -9044104859202255786L;
/** The single subscriber. */
final AtomicReference> subscriber;
/** The queue holding values until the subscriber arrives and catches up. */
final Queue