package com.github.davidmoten.rx.subjects;
import java.util.concurrent.atomic.AtomicReference;
import rx.Subscriber;
import rx.subjects.Subject;
/**
* A {@link Subject} that supports a maximum of one {@link Subscriber}. When
* there is no subscriber any notifications (<code>onNext</code>,
* <code>onError</code>, <code>onCompleted</code>) are ignored.
*
* @param <T>
* type of items being emitted/observed by this subject
*/
public final class PublishSubjectSingleSubscriber<T> extends Subject<T, T> {
// Visible for testing
static final String ONLY_ONE_SUBSCRIPTION_IS_ALLOWED = "only one subscription is allowed";
private final SingleSubscribeOnSubscribe<T> onSubscribe;
private PublishSubjectSingleSubscriber(SingleSubscribeOnSubscribe<T> onSubscribe) {
super(onSubscribe);
this.onSubscribe = onSubscribe;
}
private PublishSubjectSingleSubscriber() {
this(new SingleSubscribeOnSubscribe<T>());
}
/**
* Returns a new instance of a {@link PublishSubjectSingleSubscriber}.
*
* @return the new instance
* @param <T>
* type of items being emitted/observed by this subject
*/
public static <T> PublishSubjectSingleSubscriber<T> create() {
return new PublishSubjectSingleSubscriber<T>();
}
@Override
public void onCompleted() {
Subscriber<? super T> sub = onSubscribe.subscriber.get();
if (sub != null) {
sub.onCompleted();
}
}
@Override
public void onError(Throwable e) {
Subscriber<? super T> sub = onSubscribe.subscriber.get();
if (sub != null) {
sub.onError(e);
}
}
@Override
public void onNext(T t) {
Subscriber<? super T> sub = onSubscribe.subscriber.get();
if (sub != null) {
sub.onNext(t);
}
}
private static class SingleSubscribeOnSubscribe<T> implements OnSubscribe<T> {
final AtomicReference<Subscriber<? super T>> subscriber = new AtomicReference<Subscriber<? super T>>();
@Override
public void call(Subscriber<? super T> sub) {
if (!subscriber.compareAndSet(null, sub))
throw new RuntimeException(ONLY_ONE_SUBSCRIPTION_IS_ALLOWED);
}
}
@Override
public boolean hasObservers() {
return onSubscribe.subscriber.get() != null;
}
}