package com.googlecode.totallylazy; import com.googlecode.totallylazy.concurrent.NamedExecutors; import com.googlecode.totallylazy.functions.*; import java.util.concurrent.Callable; import java.util.concurrent.Executor; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; import java.util.concurrent.FutureTask; import java.util.concurrent.TimeUnit; import static com.googlecode.totallylazy.Sequences.sequence; public final class Callers { public static <T> Function0<T> callConcurrently(Callable<? extends T> callable) { ExecutorService service = executorService(); try { final Future<? extends T> future = service.submit(callable); return () -> future.get(); } finally { service.shutdown(); } } private static ExecutorService executorService() { return NamedExecutors.newCachedThreadPool(Callers.class); } public static <T> Sequence<T> callConcurrently(final Callable<? extends T> first, final Callable<? extends T> second) { return callConcurrently(sequence(first, second)); } public static <T> Sequence<T> callConcurrently(final Callable<? extends T> first, final Callable<? extends T> second, final Callable<? extends T> third) { return callConcurrently(sequence(first, second, third)); } public static <T> Sequence<T> callConcurrently(final Callable<? extends T> first, final Callable<? extends T> second, final Callable<? extends T> third, final Callable<? extends T> fourth) { return callConcurrently(sequence(first, second, third, fourth)); } public static <T> Sequence<T> callConcurrently(final Callable<? extends T> first, final Callable<? extends T> second, final Callable<? extends T> third, final Callable<? extends T> fourth, final Callable<? extends T> fifth) { return callConcurrently(sequence(first, second, third, fourth, fifth)); } @SafeVarargs public static <T> Sequence<T> callConcurrently(final Callable<? extends T>... callables) { return callConcurrently(sequence(callables)); } public static <T> Sequence<T> callConcurrently(final Iterable<? extends Callable<? extends T>> callables) { ExecutorService service = executorService(); try { return callConcurrently(callables, service); } finally { service.shutdown(); } } public static <T> Sequence<T> callConcurrently(final Iterable<? extends Callable<? extends T>> callables, final Executor executor) { return Sequences.sequence(callables).<Callable<T>>unsafeCast().map(Callers.<T>asFutureTask()). map(Callers.<T>executeWith(executor)). realise(). map(Callers.<T>realiseFuture()); } public static <T> Function1<FutureTask<T>, Future<T>> executeWith(final Executor executor) { return task -> { executor.execute(task); return task; }; } public static <T> Function1<Callable<T>, FutureTask<T>> asFutureTask() { return callable -> new FutureTask<T>(callable); } public static <T> Function1<Future<T>, T> realiseFuture() { return future -> future.get(); } public static <T> Function1<Future<T>, T> realiseFuture(final long timeout, final TimeUnit unit) { return future -> future.get(timeout, unit); } public static <T> T call(final Callable<? extends T> callable) { return Functions.call(callable); } public static <A, B> B call(final Function1<? super A, ? extends B> callable, final A a) { return Functions.call(callable, a); } public static <A, B, C> C call(final Function2<? super A, ? super B, ? extends C> callable, final A a, final B b) { return Functions.call(callable, a, b); } public static <A, B, C, D> D call(final Function3<? super A, ? super B, ? super C, ? extends D> callable, final A a, final B b, final C c) { return Functions.call(callable, a, b, c); } public static <A, B, C, D, E> E call(final Function4<? super A, ? super B, ? super C, ? super D, ? extends E> callable, final A a, final B b, final C c, final D d) { return Functions.call(callable, a, b, c, d); } public static <A, B, C, D, E, F> F call(final Function5<? super A, ? super B, ? super C, ? super D, ? super E, ? extends F> callable, final A a, final B b, final C c, final D d, final E e) { return Functions.call(callable, a, b, c, d, e); } }