rx.internal.operators.OnSubscribeFromEmitter Maven / Gradle / Ivy
/**
* Copyright 2016 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.Queue;
import java.util.concurrent.atomic.*;
import rx.*;
import rx.Observable.OnSubscribe;
import rx.exceptions.*;
import rx.functions.Action1;
import rx.internal.util.RxRingBuffer;
import rx.internal.util.atomic.SpscUnboundedAtomicArrayQueue;
import rx.internal.util.unsafe.*;
import rx.plugins.RxJavaHooks;
import rx.subscriptions.SerialSubscription;
public final class OnSubscribeFromEmitter implements OnSubscribe {
final Action1> asyncEmitter;
final AsyncEmitter.BackpressureMode backpressure;
public OnSubscribeFromEmitter(Action1> asyncEmitter, AsyncEmitter.BackpressureMode backpressure) {
this.asyncEmitter = asyncEmitter;
this.backpressure = backpressure;
}
@Override
public void call(Subscriber super T> t) {
BaseAsyncEmitter emitter;
switch (backpressure) {
case NONE: {
emitter = new NoneAsyncEmitter(t);
break;
}
case ERROR: {
emitter = new ErrorAsyncEmitter(t);
break;
}
case DROP: {
emitter = new DropAsyncEmitter(t);
break;
}
case LATEST: {
emitter = new LatestAsyncEmitter(t);
break;
}
default: {
emitter = new BufferAsyncEmitter(t, RxRingBuffer.SIZE);
break;
}
}
t.add(emitter);
t.setProducer(emitter);
asyncEmitter.call(emitter);
}
/**
* A Subscription that wraps an AsyncEmitter.Cancellable instance.
*/
static final class CancellableSubscription
extends AtomicReference
implements Subscription {
/** */
private static final long serialVersionUID = 5718521705281392066L;
public CancellableSubscription(AsyncEmitter.Cancellable cancellable) {
super(cancellable);
}
@Override
public boolean isUnsubscribed() {
return get() == null;
}
@Override
public void unsubscribe() {
if (get() != null) {
AsyncEmitter.Cancellable c = getAndSet(null);
if (c != null) {
try {
c.cancel();
} catch (Exception ex) {
Exceptions.throwIfFatal(ex);
RxJavaHooks.onError(ex);
}
}
}
}
}
static abstract class BaseAsyncEmitter
extends AtomicLong
implements AsyncEmitter, Producer, Subscription {
/** */
private static final long serialVersionUID = 7326289992464377023L;
final Subscriber super T> actual;
final SerialSubscription serial;
public BaseAsyncEmitter(Subscriber super T> actual) {
this.actual = actual;
this.serial = new SerialSubscription();
}
@Override
public void onCompleted() {
if (actual.isUnsubscribed()) {
return;
}
try {
actual.onCompleted();
} finally {
serial.unsubscribe();
}
}
@Override
public void onError(Throwable e) {
if (actual.isUnsubscribed()) {
return;
}
try {
actual.onError(e);
} finally {
serial.unsubscribe();
}
}
@Override
public final void unsubscribe() {
serial.unsubscribe();
onUnsubscribed();
}
void onUnsubscribed() {
// default is no-op
}
@Override
public final boolean isUnsubscribed() {
return serial.isUnsubscribed();
}
@Override
public final void request(long n) {
if (BackpressureUtils.validate(n)) {
BackpressureUtils.getAndAddRequest(this, n);
onRequested();
}
}
void onRequested() {
// default is no-op
}
@Override
public final void setSubscription(Subscription s) {
serial.set(s);
}
@Override
public final void setCancellation(AsyncEmitter.Cancellable c) {
setSubscription(new CancellableSubscription(c));
}
@Override
public final long requested() {
return get();
}
}
static final class NoneAsyncEmitter extends BaseAsyncEmitter {
/** */
private static final long serialVersionUID = 3776720187248809713L;
public NoneAsyncEmitter(Subscriber super T> actual) {
super(actual);
}
@Override
public void onNext(T t) {
if (actual.isUnsubscribed()) {
return;
}
actual.onNext(t);
for (;;) {
long r = get();
if (r == 0L || compareAndSet(r, r - 1)) {
return;
}
}
}
}
static abstract class NoOverflowBaseAsyncEmitter extends BaseAsyncEmitter {
/** */
private static final long serialVersionUID = 4127754106204442833L;
public NoOverflowBaseAsyncEmitter(Subscriber super T> actual) {
super(actual);
}
@Override
public void onNext(T t) {
if (actual.isUnsubscribed()) {
return;
}
if (get() != 0) {
actual.onNext(t);
BackpressureUtils.produced(this, 1);
} else {
onOverflow();
}
}
abstract void onOverflow();
}
static final class DropAsyncEmitter extends NoOverflowBaseAsyncEmitter {
/** */
private static final long serialVersionUID = 8360058422307496563L;
public DropAsyncEmitter(Subscriber super T> actual) {
super(actual);
}
@Override
void onOverflow() {
// nothing to do
}
}
static final class ErrorAsyncEmitter extends NoOverflowBaseAsyncEmitter {
/** */
private static final long serialVersionUID = 338953216916120960L;
private boolean done;
public ErrorAsyncEmitter(Subscriber super T> actual) {
super(actual);
}
@Override
public void onNext(T t) {
if (done) {
return;
}
super.onNext(t);
}
@Override
public void onCompleted() {
if (done) {
return;
}
done = true;
super.onCompleted();
}
@Override
public void onError(Throwable e) {
if (done) {
RxJavaHooks.onError(e);
return;
}
done = true;
super.onError(e);
}
@Override
void onOverflow() {
onError(new MissingBackpressureException("fromEmitter: could not emit value due to lack of requests"));
}
}
static final class BufferAsyncEmitter extends BaseAsyncEmitter {
/** */
private static final long serialVersionUID = 2427151001689639875L;
final Queue
© 2015 - 2024 Weber Informatics LLC | Privacy Policy