// 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;
     *  // don't try/catch the exception it throws.
     *  Map<Future<User>, User> success = tryWait(list, 1, SECONDS);
     * }</pre>
     *
     * @param futures 要获取值的多个{@link Future}
     * @param timeout 超时时间
     * @param unit 超时时间单位
     * @throws TryWaitFutureUncheckedException 当并非所有的{@link Future}都成功返回时，将会抛出此异常，
     * 可以通过此异常获取成功、异常、超时、取消的各个{@link Future}
     */
    @Nonnull
    public static <F extends Future<V>, V> Map<F, V> tryWait(@Nonnull Iterable<F> futures, @Nonnegative long timeout,
            @Nonnull TimeUnit unit) throws TryWaitFutureUncheckedException {
        checkNotNull(futures);
        checkArgument(timeout > 0);
        checkNotNull(unit);
        return tryWait(futures, timeout, unit, it -> it, TryWaitFutureUncheckedException::new);
    }

    /**
     * 同时获取并返回一批{@link Future}的操作结果值
     *
     * @param keys 要获取值的Key，作为输入值，通过asyncFunc参数传入的函数转换为Future对象
     * @param duration 获取值的超时时间
     * @param asyncFunc 异步转换函数，将输入的每一个Key值转换为{@link Future}
     * @throws TryWaitUncheckedException if not all calls are successful.
     * @see #tryWait(Iterable, long, TimeUnit, ThrowableFunction)
     */
    @Nonnull
    public static <K, V, X extends Throwable> Map<K, V> tryWait(@Nonnull Iterable<K> keys,
// 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;

     *  // don't try/catch the exception it throws.
     *  Map<Future<User>, User> success = tryWait(list, 1, SECONDS);
     * }</pre>
     *
     * @param futures 要获取值的多个{@link Future}
     * @param timeout 超时时间
     * @param unit 超时时间单位
     * @throws TryWaitFutureUncheckedException 当并非所有的{@link Future}都成功返回时，将会抛出此异常，
     * 可以通过此异常获取成功、异常、超时、取消的各个{@link Future}
     */
    @Nonnull
    public static <F extends Future<V>, V> Map<F, V> tryWait(@Nonnull Iterable<F> futures, @Nonnegative long timeout,
            @Nonnull TimeUnit unit) throws TryWaitFutureUncheckedException {
        checkNotNull(futures);
        checkArgument(timeout > 0);
        checkNotNull(unit);
        return tryWait(futures, timeout, unit, it -> it, TryWaitFutureUncheckedException::new);
    }

    /**
     * 同时获取并返回一批{@link Future}的操作结果值
     *
     * @param keys 要获取值的Key，作为输入值，通过asyncFunc参数传入的函数转换为Future对象
     * @param duration 获取值的超时时间
     * @param asyncFunc 异步转换函数，将输入的每一个Key值转换为{@link Future}
     * @throws TryWaitUncheckedException if not all calls are successful.
     * @see #tryWait(Iterable, long, TimeUnit, ThrowableFunction)
     */
    @Nonnull
    public static <K, V, X extends Throwable> Map<K, V> tryWait(@Nonnull Iterable<K> keys,
            @Nonnull Duration duration, @Nonnull ThrowableFunction<K, Future<V>, X> asyncFunc)