org.reactfx.Await Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of reactfx Show documentation
Show all versions of reactfx Show documentation
Reactive event streams for JavaFX
package org.reactfx;
import static javafx.concurrent.WorkerStateEvent.*;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.Executor;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import javafx.beans.binding.BooleanBinding;
import javafx.beans.value.ObservableBooleanValue;
import javafx.concurrent.Task;
abstract class AwaitBase extends LazilyBoundStream implements AwaitingEventStream {
private final EventStream source;
private final Indicator pending = new Indicator();
public AwaitBase(EventStream source) {
this.source = source;
}
@Override
public final ObservableBooleanValue pendingProperty() {
return pending;
}
@Override
public final boolean isPending() {
return pending.isOn();
}
@Override
protected final Subscription subscribeToInputs() {
return source.subscribe(future -> {
Guard g = pending.on();
addCompletionHandler(future, (result, success) -> {
if(success) {
emit(result);
}
g.close();
});
});
}
protected abstract void addCompletionHandler(F future, BiConsumer action);
}
class AwaitCompletionStage extends AwaitBase> {
private final Executor clientThreadExecutor;
public AwaitCompletionStage(
EventStream> source,
Executor clientThreadExecutor) {
super(source);
this.clientThreadExecutor = clientThreadExecutor;
}
@Override
protected void addCompletionHandler(CompletionStage future, BiConsumer f) {
future.whenCompleteAsync((result, error) -> {
f.accept(result, error == null);
}, clientThreadExecutor);
}
}
class AwaitTask extends AwaitBase> {
public AwaitTask(EventStream> source) {
super(source);
}
@Override
protected void addCompletionHandler(Task t, BiConsumer f) {
t.addEventHandler(WORKER_STATE_SUCCEEDED, e -> f.accept(t.getValue(), true));
t.addEventHandler(WORKER_STATE_FAILED, e -> f.accept(null, false));
t.addEventHandler(WORKER_STATE_CANCELLED, e -> f.accept(null, false));
}
}
abstract class AwaitLatestBase extends LazilyBoundStream implements AwaitingEventStream {
private final EventStream source;
private long revision = 0;
private F expectedFuture = null;
private BooleanBinding pending = null;
public AwaitLatestBase(EventStream source) {
this.source = source;
}
@Override
public ObservableBooleanValue pendingProperty() {
if(pending == null) {
pending = new BooleanBinding() {
@Override
protected boolean computeValue() {
return expectedFuture != null;
}
};
}
return pending;
}
@Override
public boolean isPending() {
return pending != null ? pending.get() : expectedFuture != null;
}
@Override
protected Subscription subscribeToInputs() {
return source.subscribe(future -> {
long rev = replaceExpected(future);
addResultHandler(future, t -> {
if(rev == revision) {
emit(t);
setExpected(null);
}
});
addErrorHandler(future, () -> {
if(rev == revision) {
setExpected(null);
}
});
});
}
private final long replaceExpected(F newExpected) {
if(expectedFuture != null) {
cancel(expectedFuture);
}
++revision;
setExpected(newExpected);
return revision;
}
private void setExpected(F newExpected) {
expectedFuture = newExpected;
if(pending != null) {
pending.invalidate();
}
}
protected final void cancelExpected() {
replaceExpected(null);
}
protected abstract void addResultHandler(F future, Consumer action);
protected abstract void addErrorHandler(F future, Runnable action);
protected abstract void cancel(F future);
}
class AwaitLatestCompletionStage extends AwaitLatestBase> {
private final Executor clientThreadExecutor;
public AwaitLatestCompletionStage(
EventStream> source,
Executor clientThreadExecutor) {
super(source);
this.clientThreadExecutor = clientThreadExecutor;
}
@Override
protected void addResultHandler(CompletionStage future, Consumer f) {
future.thenAcceptAsync(f, clientThreadExecutor);
}
@Override
protected void addErrorHandler(CompletionStage future, Runnable action) {
future.whenCompleteAsync((u, error) -> {
if(error != null) {
action.run();
}
}, clientThreadExecutor);
}
@Override
protected void cancel(CompletionStage future) {
// do nothing (cannot cancel a CompletionStage)
}
}
class CancellableAwaitLatestCompletionStage extends AwaitLatestCompletionStage {
private final EventStream> canceller;
public CancellableAwaitLatestCompletionStage(
EventStream> source,
EventStream> canceller,
Executor clientThreadExecutor) {
super(source, clientThreadExecutor);
this.canceller = canceller;
}
@Override
protected Subscription subscribeToInputs() {
Subscription s1 = super.subscribeToInputs();
Subscription s2 = canceller.subscribe(x -> cancelExpected());
return s1.and(s2);
}
}
class AwaitLatestTask extends AwaitLatestBase> {
public AwaitLatestTask(EventStream> source) {
super(source);
}
@Override
protected void addResultHandler(Task t, Consumer f) {
t.addEventHandler(WORKER_STATE_SUCCEEDED, e -> f.accept(t.getValue()));
}
@Override
protected void addErrorHandler(Task t, Runnable f) {
t.addEventHandler(WORKER_STATE_FAILED, e -> f.run());
}
@Override
protected void cancel(Task task) {
task.cancel();
}
}
class CancellableAwaitLatestTask extends AwaitLatestTask {
private final EventStream> canceller;
public CancellableAwaitLatestTask(
EventStream> source,
EventStream> canceller) {
super(source);
this.canceller = canceller;
}
@Override
protected Subscription subscribeToInputs() {
Subscription s1 = super.subscribeToInputs();
Subscription s2 = canceller.subscribe(x -> cancelExpected());
return s1.and(s2);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy