package io.trane.future; import java.time.Duration; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import java.util.logging.Level; import java.util.logging.Logger; interface SatisfiedFuture<T> extends Future<T> { static final Logger logger = Logger.getLogger(SatisfiedFuture.class.getName()); @Override default Future<T> ensure(final Runnable r) { try { r.run(); } catch (final Throwable ex) { logger.log(Level.WARNING, "Error when executing `respond` callback " + r + "for" + this, ex); NonFatalException.verify(ex); } return this; } @Override default void raise(final Throwable ex) { } @Override default Future<T> interruptible() { return this; } @Override default boolean isDefined() { return true; } @Override default void proxyTo(final Promise<T> p) { if (!p.becomeIfEmpty(this)) throw new IllegalStateException("Cannot call proxyTo on an already satisfied Promise."); } @Override default Future<T> delayed(final Duration delay, final ScheduledExecutorService scheduler) { final DelayedSatisfiedFuture<T> p = new DelayedSatisfiedFuture<>(this); scheduler.schedule(p, delay.toMillis(), TimeUnit.MILLISECONDS); return p; } @Override default Future<T> within(final Duration timeout, final ScheduledExecutorService scheduler, final Throwable exception) { return this; } @Override default void join(final Duration timeout) { } } final class DelayedSatisfiedFuture<T> extends Promise<T> implements Runnable { private final SatisfiedFuture<T> result; public DelayedSatisfiedFuture(final SatisfiedFuture<T> result) { this.result = result; } @Override public final void run() { become(result); } }