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

co.easimart.vertx.stream.ControllableReadStream Maven / Gradle / Ivy

package co.easimart.vertx.stream;

import java.util.LinkedList;
import java.util.concurrent.atomic.AtomicBoolean;

import io.vertx.core.Context;
import io.vertx.core.Handler;
import io.vertx.core.streams.ReadStream;

public class ControllableReadStream implements ReadStream {

    private final Context context;
    private Handler exceptionHandler;
    private Handler dataHandler;
    private final LinkedList objectQueue;
    private final AtomicBoolean paused;
    private final AtomicBoolean resuming;
    private boolean waitingForEnding;
    private boolean ended;
    private Handler endHandler;

    public ControllableReadStream(Context context) {
        this.context = context;
        this.objectQueue = new LinkedList<>();
        this.paused = new AtomicBoolean(false);
        this.resuming = new AtomicBoolean(false);
        this.waitingForEnding = false;
        this.ended = false;
    }

    @Override
    public ReadStream exceptionHandler(Handler handler) {
        context.runOnContext(ignored -> this.exceptionHandler = handler);
        return this;
    }

    @Override
    public ReadStream handler(Handler handler) {
        context.runOnContext(ignored -> this.dataHandler = handler);
        return this;
    }

    @Override
    public ReadStream endHandler(Handler endHandler) {
        context.runOnContext(ignored -> this.endHandler = endHandler);
        return this;
    }

    @Override
    public ReadStream pause() {
        synchronized (this.paused) {
            this.resuming.set(false); // cancel resuming
            this.paused.set(true); // set to paused now
        }
        return this;
    }

    @Override
    public ReadStream resume() {
        synchronized (this.paused) {
            if (!this.paused.get()) return this; // if not paused, do nothing
            this.resuming.set(true); // resuming in-progress. still paused until the context kicks
        }
        context.runOnContext(ignored -> {
            synchronized (this.paused) {
                if (this.resuming.get()) { // still want to resuming
                    this.paused.set(false); // resumed
                }
                this.resuming.set(false); // finished resuming
            }
            flushNextInContext();
        });
        return this;
    }

    public ControllableReadStream error(Throwable throwable) {
        context.runOnContext(ignored -> {
            if (this.waitingForEnding || this.ended) return;
            if (this.exceptionHandler != null) {
                this.exceptionHandler.handle(throwable);
            }
        });

        return this;
    }

    protected void flushNextInContext() {
        synchronized (this.paused) {
            if (this.paused.get()) return;
            if (this.objectQueue.peekFirst() != null) {
                T obj = this.objectQueue.removeFirst();
                if (this.dataHandler != null) {
                    this.dataHandler.handle(obj);
                }

                context.runOnContext(ignored -> this.flushNextInContext());
            } else if (this.waitingForEnding) {
                this.waitingForEnding = false;
                this.doEndInContext();
            }
        }
    }

    public ControllableReadStream feed(T obj) {
        context.runOnContext(ignored -> {
            if (this.waitingForEnding || this.ended) {
                return;
            }
            this.objectQueue.add(obj);
            flushNextInContext();
        });
        return this;
    }

    public ControllableReadStream end() {
        context.runOnContext(ignored -> {
            if (this.waitingForEnding || this.ended) return;
            this.waitingForEnding = true;
            flushNextInContext();
        });
        return this;
    }

    protected void doEndInContext() {
        if (this.ended) return; //ended already
        this.ended = true;
        if (this.endHandler != null) {
            this.endHandler.handle(null);
        }
    }


}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy