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

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

Go to download

Easy Redis Java client and Real-Time Data Platform. Valkey compatible. Sync/Async/RxJava3/Reactive API. Client side caching. Over 50 Redis based Java objects and services: JCache API, Apache Tomcat, Hibernate, Spring, Set, Multimap, SortedSet, Map, List, Queue, Deque, Semaphore, Lock, AtomicLong, Map Reduce, Bloom filter, Scheduler, RPC

There is a newer version: 3.40.2
Show newest version
package reactor.core.publisher;

import java.time.Duration;
import java.util.Queue;
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;

import reactor.core.Disposable;
import reactor.core.publisher.Sinks.Empty;
import reactor.core.publisher.Sinks.Many;
import reactor.core.publisher.Sinks.One;
import reactor.core.scheduler.Scheduler;

final class SinksSpecs {

	static final Sinks.RootSpec UNSAFE_ROOT_SPEC  = new RootSpecImpl(false);
	static final Sinks.RootSpec DEFAULT_ROOT_SPEC = new RootSpecImpl(true);

	abstract static class AbstractSerializedSink {

		volatile int                                                   wip;
		static final AtomicIntegerFieldUpdater WIP =
				AtomicIntegerFieldUpdater.newUpdater(AbstractSerializedSink.class, "wip");

		volatile Thread                                                          lockedAt;
		static final AtomicReferenceFieldUpdater LOCKED_AT =
				AtomicReferenceFieldUpdater.newUpdater(AbstractSerializedSink.class, Thread.class, "lockedAt");

		boolean tryAcquire(Thread currentThread) {
			if (WIP.get(this) == 0 && WIP.compareAndSet(this, 0, 1)) {
				// lazySet in thread A here is ok because:
				// 1. initial state is `null`
				// 2. `LOCKED_AT.get(this) != currentThread` from a different thread B could see outdated null or an outdated old thread
				// 3. but that old thread cannot be B: since we're in thread B, it must have executed the compareAndSet which would have loaded the update from A
				// 4. Seeing `null` or `C` is equivalent from seeing `A` from the perspective of the condition (`!= currentThread` is still true in all three cases)
				LOCKED_AT.lazySet(this, currentThread);
			}
			else {
				if (LOCKED_AT.get(this) != currentThread) {
					return false;
				}
				WIP.incrementAndGet(this);
			}
			return true;
		}
	}

	static final class RootSpecImpl implements Sinks.RootSpec,
	                                     Sinks.ManySpec,
	                                     Sinks.MulticastSpec,
	                                     Sinks.MulticastReplaySpec {

		final boolean serialized;
		final Sinks.UnicastSpec unicastSpec; //needed because UnicastSpec method names overlap with MulticastSpec

		RootSpecImpl(boolean serialized) {
			this.serialized = serialized;
			//there will only be as many instances of UnicastSpecImpl as there are RootSpecImpl instances (2)
			this.unicastSpec = new UnicastSpecImpl(serialized);
		}

		 & ContextHolder> Empty wrapEmpty(EMPTY original) {
			if (serialized) {
				return new SinkEmptySerialized<>(original, original);
			}
			return original;
		}

		 & ContextHolder> One wrapOne(ONE original) {
			if (serialized) {
				return new SinkOneSerialized<>(original, original);
			}
			return original;
		}

		 & ContextHolder> Many wrapMany(MANY original) {
			if (serialized) {
				return new SinkManySerialized<>(original, original);
			}
			return original;
		}

		@Override
		public Sinks.ManySpec many() {
			return this;
		}

		@Override
		public  Empty empty() {
			return wrapEmpty(new SinkEmptyMulticast<>());
		}

		@Override
		public  One one() {
			final NextProcessor original = new NextProcessor<>(null);
			return wrapOne(original);
		}

		@Override
		public Sinks.UnicastSpec unicast() {
			return this.unicastSpec;
		}

		@Override
		public Sinks.MulticastSpec multicast() {
			return this;
		}

		@Override
		public Sinks.MulticastReplaySpec replay() {
			return this;
		}

		@Override
		public  Many onBackpressureBuffer() {
			@SuppressWarnings("deprecation") // EmitterProcessor will be removed in 3.5.
			final EmitterProcessor original = EmitterProcessor.create();
			return wrapMany(original);
		}

		@Override
		public  Many onBackpressureBuffer(int bufferSize) {
			@SuppressWarnings("deprecation") // EmitterProcessor will be removed in 3.5.
			final EmitterProcessor original = EmitterProcessor.create(bufferSize);
			return wrapMany(original);
		}

		@Override
		public  Many onBackpressureBuffer(int bufferSize, boolean autoCancel) {
			@SuppressWarnings("deprecation") // EmitterProcessor will be removed in 3.5.
			final EmitterProcessor original = EmitterProcessor.create(bufferSize, autoCancel);
			return wrapMany(original);
		}

		@Override
		public  Many directAllOrNothing() {
			final SinkManyBestEffort original = SinkManyBestEffort.createAllOrNothing();
			return wrapMany(original);
		}

		@Override
		public  Many directBestEffort() {
			final SinkManyBestEffort original = SinkManyBestEffort.createBestEffort();
			return wrapMany(original);
		}


		@Override
		public  Many all() {
			@SuppressWarnings("deprecation") // ReplayProcessor will be removed in 3.5.
			final ReplayProcessor original = ReplayProcessor.create();
			return wrapMany(original);
		}

		@Override
		public  Many all(int batchSize) {
			@SuppressWarnings("deprecation") // ReplayProcessor will be removed in 3.5
			final ReplayProcessor original = ReplayProcessor.create(batchSize, true);
			return wrapMany(original);
		}

		@Override
		public  Many latest() {
			@SuppressWarnings("deprecation") // ReplayProcessor will be removed in 3.5.
			final ReplayProcessor original = ReplayProcessor.cacheLast();
			return wrapMany(original);
		}

		@Override
		public  Many latestOrDefault(T value) {
			@SuppressWarnings("deprecation") // ReplayProcessor will be removed in 3.5.
			final ReplayProcessor original = ReplayProcessor.cacheLastOrDefault(value);
			return wrapMany(original);
		}

		@Override
		public  Many limit(int historySize) {
			@SuppressWarnings("deprecation") // ReplayProcessor will be removed in 3.5.
			final ReplayProcessor original = ReplayProcessor.create(historySize);
			return wrapMany(original);
		}

		@Override
		public  Many limit(Duration maxAge) {
			@SuppressWarnings("deprecation") // ReplayProcessor will be removed in 3.5.
			final ReplayProcessor original = ReplayProcessor.createTimeout(maxAge);
			return wrapMany(original);
		}

		@Override
		public  Many limit(Duration maxAge, Scheduler scheduler) {
			@SuppressWarnings("deprecation") // ReplayProcessor will be removed in 3.5.
			final ReplayProcessor original = ReplayProcessor.createTimeout(maxAge, scheduler);
			return wrapMany(original);
		}

		@Override
		public  Many limit(int historySize, Duration maxAge) {
			@SuppressWarnings("deprecation") // ReplayProcessor will be removed in 3.5.
			final ReplayProcessor original = ReplayProcessor.createSizeAndTimeout(historySize, maxAge);
			return wrapMany(original);
		}

		@Override
		public  Many limit(int historySize, Duration maxAge, Scheduler scheduler) {
			@SuppressWarnings("deprecation") // ReplayProcessor will be removed in 3.5.
			final ReplayProcessor original = ReplayProcessor.createSizeAndTimeout(historySize, maxAge, scheduler);
			return wrapMany(original);
		}
	}

	static final class UnicastSpecImpl implements Sinks.UnicastSpec {

		final boolean serialized;

		UnicastSpecImpl(boolean serialized) {
			this.serialized = serialized;
		}

		 & ContextHolder> Many wrapMany(MANY original) {
			if (serialized) {
				return new SinkManySerialized<>(original, original);
			}
			return original;
		}

		@Override
		public  Many onBackpressureBuffer() {
			@SuppressWarnings("deprecation") // UnicastProcessor will be removed in 3.5.
			final UnicastProcessor original = UnicastProcessor.create();
			return wrapMany(original);
		}

		@Override
		public  Many onBackpressureBuffer(Queue queue) {
			@SuppressWarnings("deprecation") // UnicastProcessor will be removed in 3.5.
			final UnicastProcessor original = UnicastProcessor.create(queue);
			return wrapMany(original);
		}

		@Override
		public  Many onBackpressureBuffer(Queue queue, Disposable endCallback) {
			@SuppressWarnings("deprecation") // UnicastProcessor will be removed in 3.5.
			final UnicastProcessor original = UnicastProcessor.create(queue, endCallback);
			return wrapMany(original);
		}

		@Override
		public  Many onBackpressureError() {
			final UnicastManySinkNoBackpressure original = UnicastManySinkNoBackpressure.create();
			return wrapMany(original);
		}
	}
}





© 2015 - 2025 Weber Informatics LLC | Privacy Policy