
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