
io.github.vipcxj.jasync.ng.runtime.schedule.LazyTask Maven / Gradle / Ivy
package io.github.vipcxj.jasync.ng.runtime.schedule;
import io.github.vipcxj.jasync.ng.spec.JContext;
import io.github.vipcxj.jasync.ng.spec.JDisposable;
import io.github.vipcxj.jasync.ng.spec.JScheduler;
import io.github.vipcxj.jasync.ng.spec.JThunk;
import io.github.vipcxj.schedule.EventHandle;
import io.github.vipcxj.schedule.Schedule;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
import java.util.function.BiConsumer;
public class LazyTask implements Task {
private volatile boolean disposed;
private final long delay;
private final TimeUnit timeUnit;
private final BiConsumer, JContext> handler;
private volatile JDisposable disposable;
@SuppressWarnings("rawtypes")
private final static AtomicReferenceFieldUpdater DISPOSABLE = AtomicReferenceFieldUpdater.newUpdater(LazyTask.class, JDisposable.class, "disposable");
public LazyTask(BiConsumer, JContext> handler) {
this(handler, 0, TimeUnit.MILLISECONDS);
}
public LazyTask(BiConsumer, JContext> handler, long delay, TimeUnit timeUnit) {
this.handler = handler;
this.delay = delay;
this.timeUnit = timeUnit;
this.disposed = false;
}
private void doSchedule(JThunk thunk, JContext context) {
try {
handler.accept(thunk, context);
} catch (Throwable t) {
thunk.reject(t, context);
}
}
private void dispose() {
JDisposable disposable = this.disposable;
if (disposable != null && DISPOSABLE.compareAndSet(this, disposable, null)) {
disposable.dispose();
}
}
@Override
public void schedule(JThunk thunk, JContext context) {
if (!disposed) {
JScheduler scheduler = context.getScheduler();
if (delay > 0) {
if (scheduler.supportDelay()) {
disposable = scheduler.schedule(() -> doSchedule(thunk, context), delay, timeUnit);
} else {
DisposableHandler disposableHandler = new DisposableHandler();
final EventHandlerDisposable disposable = new EventHandlerDisposable(disposableHandler);
EventHandle handle = Schedule.instance().addEvent(delay, timeUnit, () -> {
disposableHandler.updateDisposable(scheduler.schedule(() -> doSchedule(thunk, context)));
});
disposable.updateHandle(handle);
this.disposable = disposable;
}
} else {
disposable = scheduler.schedule(() -> doSchedule(thunk, context));
}
if (disposed) {
dispose();
}
}
}
@Override
public void cancel() {
if (!disposed) {
disposed = true;
dispose();
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy