// Path: core/src/main/java/com/github/phantomthief/util/ThrowableConsumer.java
// @FunctionalInterface
// public interface ThrowableConsumer<T, X extends Throwable> {
// 
//     void accept(T t) throws X;
// 
//     default ThrowableConsumer<T, X> andThen(ThrowableConsumer<? super T, X> after) {
//         requireNonNull(after);
//         return t -> {
//             accept(t);
//             after.accept(t);
//         };
//     }
// }
// 
// Path: core/src/main/java/com/github/phantomthief/util/ThrowableFunction.java
// @FunctionalInterface
// public interface ThrowableFunction<T, R, X extends Throwable> {
// 
//     static <T, X extends Throwable> ThrowableFunction<T, T, X> identity() {
//         return t -> t;
//     }
// 
//     R apply(T t) throws X;
// 
//     default <V> ThrowableFunction<V, R, X>
//             compose(ThrowableFunction<? super V, ? extends T, X> before) {
//         requireNonNull(before);
//         return (V v) -> apply(before.apply(v));
//     }
// 
//     default <V> ThrowableFunction<T, V, X>
//             andThen(ThrowableFunction<? super R, ? extends V, X> after) {
//         requireNonNull(after);
//         return (T t) -> after.apply(apply(t));
//     }
// }
// 
// Path: core/src/main/java/com/github/phantomthief/util/ThrowableRunnable.java
// @FunctionalInterface
// public interface ThrowableRunnable<X extends Throwable> {
// 
//     void run() throws X;
// }


import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.util.concurrent.Uninterruptibles.getUninterruptibly;
import static java.lang.System.nanoTime;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.NANOSECONDS;
import java.time.Duration;
import java.util.IdentityHashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Function;
import java.util.function.Supplier;
import javax.annotation.Nonnegative;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.github.phantomthief.util.ThrowableConsumer;
import com.github.phantomthief.util.ThrowableFunction;
import com.github.phantomthief.util.ThrowableRunnable;
import com.google.common.util.concurrent.AbstractFuture;
import com.google.common.util.concurrent.AsyncFunction;
import com.google.common.util.concurrent.ExecutionError;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.UncheckedExecutionException;
import com.google.common.util.concurrent.UncheckedTimeoutException;
     */
    public static Future<?> scheduleWithDynamicDelay(@Nonnull ScheduledExecutorService executor,
            @Nullable Duration initDelay, @Nonnull Scheduled task) {
        checkNotNull(executor);
        checkNotNull(task);
        AtomicBoolean canceled = new AtomicBoolean(false);
        AbstractFuture<?> future = new AbstractFuture<Object>() {

            @Override
            public boolean cancel(boolean mayInterruptIfRunning) {
                canceled.set(true);
                return super.cancel(mayInterruptIfRunning);
            }
        };
        executor.schedule(new ScheduledTaskImpl(executor, task, canceled),
                initDelay == null ? 0 : initDelay.toMillis(), MILLISECONDS);
        return future;
    }

    /**
     * 执行一个计划任务，按照上一次计划任务返回的等待时间，来运行下一次任务
     *
     * @param executor 任务执行器，当任务执行器停止时，所有任务将停止运行
     * @param initialDelay 首次执行的延迟时间
     * @param delay 任务延迟提供器，用来设置任务执行之后下一次的执行间隔时间
     * @param task 执行的任务，在任务中抛出的异常会终止任务的运行，需谨慎处理
     * @return 执行任务的Future，可以用来取消任务
     */
    public static Future<?> scheduleWithDynamicDelay(@Nonnull ScheduledExecutorService executor,
            @Nonnull Duration initialDelay, @Nonnull Supplier<Duration> delay,
// Path: core/src/main/java/com/github/phantomthief/util/ThrowableConsumer.java
// @FunctionalInterface
// public interface ThrowableConsumer<T, X extends Throwable> {
// 
//     void accept(T t) throws X;
// 
//     default ThrowableConsumer<T, X> andThen(ThrowableConsumer<? super T, X> after) {
//         requireNonNull(after);
//         return t -> {
//             accept(t);
//             after.accept(t);
//         };
//     }
// }
// 
// Path: core/src/main/java/com/github/phantomthief/util/ThrowableFunction.java
// @FunctionalInterface
// public interface ThrowableFunction<T, R, X extends Throwable> {
// 
//     static <T, X extends Throwable> ThrowableFunction<T, T, X> identity() {
//         return t -> t;
//     }
// 
//     R apply(T t) throws X;
// 
//     default <V> ThrowableFunction<V, R, X>
//             compose(ThrowableFunction<? super V, ? extends T, X> before) {
//         requireNonNull(before);
//         return (V v) -> apply(before.apply(v));
//     }
// 
//     default <V> ThrowableFunction<T, V, X>
//             andThen(ThrowableFunction<? super R, ? extends V, X> after) {
//         requireNonNull(after);
//         return (T t) -> after.apply(apply(t));
//     }
// }
// 
// Path: core/src/main/java/com/github/phantomthief/util/ThrowableRunnable.java
// @FunctionalInterface
// public interface ThrowableRunnable<X extends Throwable> {
// 
//     void run() throws X;
// }


// Path: core/src/main/java/com/github/phantomthief/concurrent/MoreFutures.java
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.util.concurrent.Uninterruptibles.getUninterruptibly;
import static java.lang.System.nanoTime;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.NANOSECONDS;
import java.time.Duration;
import java.util.IdentityHashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Function;
import java.util.function.Supplier;
import javax.annotation.Nonnegative;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.github.phantomthief.util.ThrowableConsumer;
import com.github.phantomthief.util.ThrowableFunction;
import com.github.phantomthief.util.ThrowableRunnable;
import com.google.common.util.concurrent.AbstractFuture;
import com.google.common.util.concurrent.AsyncFunction;
import com.google.common.util.concurrent.ExecutionError;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.UncheckedExecutionException;
import com.google.common.util.concurrent.UncheckedTimeoutException;

     */
    public static Future<?> scheduleWithDynamicDelay(@Nonnull ScheduledExecutorService executor,
            @Nullable Duration initDelay, @Nonnull Scheduled task) {
        checkNotNull(executor);
        checkNotNull(task);
        AtomicBoolean canceled = new AtomicBoolean(false);
        AbstractFuture<?> future = new AbstractFuture<Object>() {

            @Override
            public boolean cancel(boolean mayInterruptIfRunning) {
                canceled.set(true);
                return super.cancel(mayInterruptIfRunning);
            }
        };
        executor.schedule(new ScheduledTaskImpl(executor, task, canceled),
                initDelay == null ? 0 : initDelay.toMillis(), MILLISECONDS);
        return future;
    }

    /**
     * 执行一个计划任务，按照上一次计划任务返回的等待时间，来运行下一次任务
     *
     * @param executor 任务执行器，当任务执行器停止时，所有任务将停止运行
     * @param initialDelay 首次执行的延迟时间
     * @param delay 任务延迟提供器，用来设置任务执行之后下一次的执行间隔时间
     * @param task 执行的任务，在任务中抛出的异常会终止任务的运行，需谨慎处理
     * @return 执行任务的Future，可以用来取消任务
     */
    public static Future<?> scheduleWithDynamicDelay(@Nonnull ScheduledExecutorService executor,
            @Nonnull Duration initialDelay, @Nonnull Supplier<Duration> delay,
            @Nonnull ThrowableRunnable<Throwable> task) {