package org.threadly.concurrent.future; import static org.threadly.concurrent.future.InternalFutureUtils.invokeCompletedDirectly; import java.util.Collections; import java.util.Enumeration; import java.util.Iterator; import java.util.List; import java.util.ListIterator; import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.SortedMap; import java.util.SortedSet; import java.util.concurrent.Executor; import java.util.concurrent.TimeUnit; import java.util.function.Consumer; import java.util.function.Function; /** * Completed implementation of {@link ListenableFuture} that will immediately return a result. * Meaning listeners added will immediately be ran/executed, {@link FutureCallback}'s will * immediately get called with the result provided, and {@link #get()} calls will never block. * * @since 1.3.0 * @param <T> The result object type returned by this future */ public class ImmediateResultListenableFuture<T> extends AbstractCompletedListenableFuture<T> { /** * Static instance of {@link ImmediateResultListenableFuture} which provides a {@code null} * result. Since this is a common case this can avoid GC overhead. If you want to get this in * any generic type use {@link FutureUtils#immediateResultFuture(Object)}, which when provided a * {@code null} will always return this static instance. * * @since 4.2.0 */ public static final ImmediateResultListenableFuture<?> NULL_RESULT = new ImmediateResultListenableFuture<>(null); /** * Static instance of {@link ImmediateResultListenableFuture} which provides a {@link Boolean} * in the {@code true} state as the result. * * @since 5.6 */ public static final ImmediateResultListenableFuture<Boolean> BOOLEAN_TRUE_RESULT = new ImmediateResultListenableFuture<>(Boolean.TRUE); /** * Static instance of {@link ImmediateResultListenableFuture} which provides a {@link Boolean} * in the {@code false} state as the result. * * @since 5.6 */ public static final ImmediateResultListenableFuture<Boolean> BOOLEAN_FALSE_RESULT = new ImmediateResultListenableFuture<>(Boolean.FALSE); /** * Static instance of {@link ImmediateResultListenableFuture} which provides an empty * {@link String} as the result. * * @since 5.34 */ public static final ImmediateResultListenableFuture<String> EMPTY_STRING_RESULT = new ImmediateResultListenableFuture<>(""); /** * Static instance of {@link ImmediateResultListenableFuture} which provides an empty * {@link Optional} from {@link Optional#empty()} as the result. * * @since 5.34 */ public static final ImmediateResultListenableFuture<? extends Optional<?>> EMPTY_OPTIONAL_RESULT = new ImmediateResultListenableFuture<>(Optional.empty()); /** * Static instance of {@link ImmediateResultListenableFuture} which provides an empty * {@link List} from {@link Collections#emptyList()} as the result. * * @since 5.34 */ public static final ImmediateResultListenableFuture<? extends List<?>> EMPTY_LIST_RESULT = new ImmediateResultListenableFuture<>(Collections.emptyList()); /** * Static instance of {@link ImmediateResultListenableFuture} which provides an empty * {@link Map} from {@link Collections#emptyMap()} as the result. * * @since 5.34 */ public static final ImmediateResultListenableFuture<? extends Map<?, ?>> EMPTY_MAP_RESULT = new ImmediateResultListenableFuture<>(Collections.emptyMap()); /** * Static instance of {@link ImmediateResultListenableFuture} which provides an empty * {@link SortedMap} from {@link Collections#emptyMap()} as the result. * * @since 5.34 */ public static final ImmediateResultListenableFuture<? extends SortedMap<?, ?>> EMPTY_SORTED_MAP_RESULT = new ImmediateResultListenableFuture<>(Collections.emptySortedMap()); /** * Static instance of {@link ImmediateResultListenableFuture} which provides an empty * {@link Set} from {@link Collections#emptySet()} as the result. * * @since 5.34 */ public static final ImmediateResultListenableFuture<? extends Set<?>> EMPTY_SET_RESULT = new ImmediateResultListenableFuture<>(Collections.emptySet()); /** * Static instance of {@link ImmediateResultListenableFuture} which provides an empty * {@link SortedSet} from {@link Collections#emptySet()} as the result. * * @since 5.34 */ public static final ImmediateResultListenableFuture<? extends SortedSet<?>> EMPTY_SORTED_SET_RESULT = new ImmediateResultListenableFuture<>(Collections.emptySortedSet()); /** * Static instance of {@link ImmediateResultListenableFuture} which provides an empty * {@link Iterator} from {@link Collections#emptyIterator()} as the result. * * @since 5.34 */ public static final ImmediateResultListenableFuture<? extends Iterator<?>> EMPTY_ITERATOR_RESULT = new ImmediateResultListenableFuture<>(Collections.emptyIterator()); /** * Static instance of {@link ImmediateResultListenableFuture} which provides an empty * {@link ListIterator} from {@link Collections#emptyListIterator()} as the result. * * @since 5.34 */ public static final ImmediateResultListenableFuture<? extends ListIterator<?>> EMPTY_LIST_ITERATOR_RESULT = new ImmediateResultListenableFuture<>(Collections.emptyListIterator()); /** * Static instance of {@link ImmediateResultListenableFuture} which provides an empty * {@link Enumeration} from {@link Collections#emptyEnumeration()} as the result. * * @since 5.34 */ public static final ImmediateResultListenableFuture<? extends Enumeration<?>> EMPTY_ENUMERATION_RESULT = new ImmediateResultListenableFuture<>(Collections.emptyEnumeration()); protected final T result; /** * Constructs a completed future that will return the provided result. * * @param result Result that is returned by future */ public ImmediateResultListenableFuture(T result) { this.result = result; } @Override public boolean isCompletedExceptionally() { return false; } @Override public <TT extends Throwable> ListenableFuture<T> mapFailure(Class<TT> throwableType, Function<? super TT, ? extends T> mapper) { return this; // nothing to map, we are not in error } @Override public <TT extends Throwable> ListenableFuture<T> mapFailure(Class<TT> throwableType, Function<? super TT, ? extends T> mapper, Executor executor) { return this; // nothing to map, we are not in error } @Override public <TT extends Throwable> ListenableFuture<T> mapFailure(Class<TT> throwableType, Function<? super TT, ? extends T> mapper, Executor executor, ListenerOptimizationStrategy optimizeExecution) { return this; // nothing to map, we are not in error } @Override public <TT extends Throwable> ListenableFuture<T> flatMapFailure(Class<TT> throwableType, Function<? super TT, ListenableFuture<T>> mapper) { return this; // nothing to map, we are not in error } @Override public <TT extends Throwable> ListenableFuture<T> flatMapFailure(Class<TT> throwableType, Function<? super TT, ListenableFuture<T>> mapper, Executor executor) { return this; // nothing to map, we are not in error } @Override public <TT extends Throwable> ListenableFuture<T> flatMapFailure(Class<TT> throwableType, Function<? super TT, ListenableFuture<T>> mapper, Executor executor, ListenerOptimizationStrategy optimizeExecution) { return this; // nothing to map, we are not in error } @Override public ListenableFuture<T> callback(FutureCallback<? super T> callback, Executor executor, ListenerOptimizationStrategy optimize) { if (invokeCompletedDirectly(executor, optimize)) { callback.handleResult(result); } else { executor.execute(() -> callback.handleResult(result)); } return this; } @Override public ListenableFuture<T> resultCallback(Consumer<? super T> callback, Executor executor, ListenerOptimizationStrategy optimize) { if (invokeCompletedDirectly(executor, optimize)) { callback.accept(result); } else { executor.execute(() -> callback.accept(result)); } return this; } @Override public ListenableFuture<T> failureCallback(Consumer<Throwable> callback, Executor executor, ListenerOptimizationStrategy optimize) { // ignored return this; } @Override public T get() { return result; } @Override public T get(long timeout, TimeUnit unit) { return result; } @Override public Throwable getFailure() { return null; } @Override public Throwable getFailure(long timeout, TimeUnit unit) { return null; } }