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

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