64 lines
1.8 KiB
Java
64 lines
1.8 KiB
Java
package io.gitlab.jfronny.commons.concurrent;
|
|
|
|
import io.gitlab.jfronny.commons.SamWithReceiver;
|
|
import io.gitlab.jfronny.commons.ref.R;
|
|
|
|
import java.util.Objects;
|
|
import java.util.concurrent.ForkJoinPool;
|
|
import java.util.concurrent.Future;
|
|
import java.util.function.Consumer;
|
|
|
|
public class AsyncRequest {
|
|
private final Action action;
|
|
private final Runnable finalize;
|
|
private final AsyncRequestState state = new AsyncRequestState();
|
|
private Future<Void> future = null;
|
|
|
|
public AsyncRequest(Action action, Runnable finalize) {
|
|
this.action = Objects.requireNonNull(action);
|
|
this.finalize = Objects.requireNonNull(finalize);
|
|
}
|
|
|
|
public AsyncRequest(Consumer<Context> runnable) {
|
|
this.action = (context, callback) -> new VoidFuture(ForkJoinPool.commonPool().submit(() -> {
|
|
runnable.accept(context);
|
|
callback.run();
|
|
}));
|
|
this.finalize = R::nop;
|
|
}
|
|
|
|
public void request() {
|
|
if (state.request().shouldStart()) start();
|
|
}
|
|
|
|
private void start() {
|
|
Future<Void>[] tasks = new Future[0];
|
|
future = tasks[0] = action.schedule(new Context() {
|
|
@Override
|
|
public boolean isCancelled() {
|
|
return tasks[0].isCancelled();
|
|
}
|
|
}, () -> {
|
|
if (!tasks[0].isCancelled()) {
|
|
finalize.run();
|
|
future = null;
|
|
}
|
|
if (state.emitFinished().shouldContinue()) start();
|
|
});
|
|
}
|
|
|
|
public void cancel() {
|
|
if (future != null) future.cancel(false);
|
|
state.cancel();
|
|
}
|
|
|
|
@SamWithReceiver
|
|
interface Action {
|
|
Future<Void> schedule(Context context, Runnable callback);
|
|
}
|
|
|
|
interface Context {
|
|
boolean isCancelled();
|
|
}
|
|
}
|