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

reactor.core.publisher.LambdaMonoSubscriber Maven / Gradle / Ivy

There is a newer version: 5.20.0
Show newest version
/*
 * Copyright (c) 2011-2017 Pivotal Software Inc, All Rights Reserved.
 *
 * 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 reactor.core.publisher;

import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
import java.util.function.Consumer;

import org.reactivestreams.Subscriber;
import org.reactivestreams.Subscription;
import reactor.core.Disposable;
import reactor.core.Exceptions;
import reactor.util.annotation.Nullable;
import reactor.util.context.Context;

/**
 * An unbounded Java Lambda adapter to {@link Subscriber}, targeted at {@link Mono}.
 *
 * @param  the value type
 */
final class LambdaMonoSubscriber implements InnerConsumer, Disposable {

	final Consumer            consumer;
	final Consumer    errorConsumer;
	final Runnable                       completeConsumer;
	final Consumer subscriptionConsumer;

	volatile Subscription subscription;
	static final AtomicReferenceFieldUpdater S =
			AtomicReferenceFieldUpdater.newUpdater(LambdaMonoSubscriber.class,
					Subscription.class,
					"subscription");

	/**
	 * Create a {@link Subscriber} reacting onNext, onError and onComplete. The subscriber
	 * will automatically request Long.MAX_VALUE onSubscribe.
	 * 

* The argument {@code subscriptionHandler} is executed once by new subscriber to * generate a context shared by every request calls. * * @param consumer A {@link Consumer} with argument onNext data * @param errorConsumer A {@link Consumer} called onError * @param completeConsumer A {@link Runnable} called onComplete with the actual * context if any * @param subscriptionConsumer A {@link Consumer} called with the {@link Subscription} * to perform initial request, or null to request max */ LambdaMonoSubscriber(@Nullable Consumer consumer, @Nullable Consumer errorConsumer, @Nullable Runnable completeConsumer, @Nullable Consumer subscriptionConsumer) { this.consumer = consumer; this.errorConsumer = errorConsumer; this.completeConsumer = completeConsumer; this.subscriptionConsumer = subscriptionConsumer; } @Override public final void onSubscribe(Subscription s) { if (Operators.validate(subscription, s)) { this.subscription = s; if (subscriptionConsumer != null) { try { subscriptionConsumer.accept(s); } catch (Throwable t) { Exceptions.throwIfFatal(t); s.cancel(); onError(t); } } else { s.request(Long.MAX_VALUE); } } } @Override public final void onComplete() { Subscription s = S.getAndSet(this, Operators.cancelledSubscription()); if (s == Operators.cancelledSubscription()) { return; } if (completeConsumer != null) { try { completeConsumer.run(); } catch (Throwable t) { Operators.onErrorDropped(t, Context.empty()); } } } @Override public final void onError(Throwable t) { Subscription s = S.getAndSet(this, Operators.cancelledSubscription()); if (s == Operators.cancelledSubscription()) { Operators.onErrorDropped(t, Context.empty()); return; } doError(t); } void doError(Throwable t) { if (errorConsumer != null) { errorConsumer.accept(t); } else { throw Exceptions.errorCallbackNotImplemented(t); } } @Override public final void onNext(T x) { Subscription s = S.getAndSet(this, Operators.cancelledSubscription()); if (s == Operators.cancelledSubscription()) { Operators.onNextDropped(x, Context.empty()); return; } if (consumer != null) { try { consumer.accept(x); } catch (Throwable t) { Operators.onErrorDropped(t, Context.empty()); return; } } if (completeConsumer != null) { try { completeConsumer.run(); } catch (Throwable t) { Operators.onErrorDropped(t, Context.empty()); } } } @Override @Nullable public Object scanUnsafe(Attr key) { if (key == Attr.PARENT) { return subscription; } if (key == Attr.PREFETCH) { return Integer.MAX_VALUE; } if (key == Attr.TERMINATED || key == Attr.CANCELLED) { return isDisposed(); } return null; } @Override public boolean isDisposed() { return subscription == Operators.cancelledSubscription(); } @Override public void dispose() { Subscription s = S.getAndSet(this, Operators.cancelledSubscription()); if (s != null && s != Operators.cancelledSubscription()) { s.cancel(); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy