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

io.datakernel.datastream.processor.StreamBuffer Maven / Gradle / Ivy

package io.datakernel.datastream.processor;

import io.datakernel.datastream.*;
import io.datakernel.promise.Promise;

import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Set;

import static io.datakernel.datastream.StreamCapability.IMMEDIATE_SUSPEND;

public class StreamBuffer implements StreamTransformer {

	private final Input input;
	private final Output output;

	private final Deque buffer = new ArrayDeque<>();
	private final int minBuffered;
	private final int maxBuffered;

	private boolean suspended = false; // TODO

	// region creators
	private StreamBuffer(int minBuffered, int maxBuffered) {
		this.minBuffered = minBuffered;
		this.maxBuffered = maxBuffered;
		this.input = new Input();
		this.output = new Output();
	}

	public static  StreamBuffer create() {
		return new StreamBuffer<>(0, 0);
	}

	public static  StreamBuffer create(int minBuffered, int maxBuffered) {
		return new StreamBuffer<>(minBuffered, maxBuffered);
	}
	// endregion

	protected final class Input extends AbstractStreamConsumer {
		@Override
		public Set getCapabilities() {
			return addCapabilities(output.getConsumer(), IMMEDIATE_SUSPEND);
		}

		@Override
		protected Promise onEndOfStream() {
			output.tryProduce();
			assert output.getConsumer() != null;
			return output.getConsumer().getAcknowledgement();
		}

		@Override
		protected void onError(Throwable e) {
			output.close(e);
		}
	}

	protected final class Output extends AbstractStreamSupplier implements StreamDataAcceptor {
		@Override
		public void accept(T item) {
			if (suspended) {
				buffer.offer(item);
				if (buffer.size() >= maxBuffered) {
					input.getSupplier().suspend();
				}
				return;
			}
			output.getLastDataAcceptor().accept(item);
		}

		@Override
		protected void produce(AsyncProduceController async) {
			while (!buffer.isEmpty()) {
				if (!output.isReceiverReady()) {
					return;
				}
				send(buffer.pop());
				if (buffer.size() < minBuffered) {
					input.getSupplier().resume(this);
				}
			}
			if (output.isReceiverReady()) {
				suspended = false;
				input.getSupplier().resume(this);
			}
			if (input.getEndOfStream().isResult()) {
				sendEndOfStream();
			}
		}

		@Override
		protected void onSuspended() {
			suspended = true;
			if (maxBuffered == 0) {
				input.getSupplier().suspend();
			}
		}

		@Override
		public Set getCapabilities() {
			return addCapabilities(input.getSupplier(), IMMEDIATE_SUSPEND);
		}

		@Override
		protected void onError(Throwable e) {
			input.close(e);
		}
	}

	@Override
	public StreamConsumer getInput() {
		return input;
	}

	@Override
	public StreamSupplier getOutput() {
		return output;
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy