package io.futuristic;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.function.Consumer;
/**
* @autor: julio
*/
public final class Futures {
private static final Executor EXECUTOR = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
private Futures(){
}
/**
* Returns an object that has a trigger and a future. The future will be "known" when the trigger gets fired
* @param <T>
* @return
*/
public static <T> FutureWithTrigger<T> withTrigger(){
return new FutureWithTrigger<T>();
};
/**
* Returns a Future object that is triggered by the {@link Callback} passed to the
* {@link java.util.function.Consumer}
* @param consumer
* @param <T>
* @return
*/
public static <T> Future<T> withCallback(Consumer<Callback<T>> consumer){
FutureWithTrigger<T> futureWithTrigger = new FutureWithTrigger<>();
consumer.accept(futureWithTrigger.getTrigger());
return futureWithTrigger.getFuture();
};
/**
* Returns a future which value is already known
* @param value
* @param <T>
* @return
*/
public static <T> Future<T> withValue(T value){
return new FutureWithValue<>(value);
}
/**
* Returns a future which {@link java.lang.Exception} is already known.
* @param exception
* @param <T>
* @return
*/
public static <T> Future<T> withException(Exception exception){
return new FutureWithException<>(exception);
}
/**
* Executes the {@link java.util.concurrent.Callable} in a separate thread and the result will be exposed on the
* future that is returned from this function.
* @param callable
* @param <T>
* @return
*/
public static <T> Future<T> withCallable(Callable<T> callable){
return withCallable(EXECUTOR, callable);
}
/**
* Executes the {@link java.util.concurrent.Callable} in a separate thread and the result will be exposed on the
* future that is returned from this function.
* @param executor Executor to run the callable
* @param callable
* @param <T>
* @return
*/
public static <T> Future<T> withCallable(Executor executor, Callable<T> callable){
FutureWithTrigger<T> futureWithTrigger = new FutureWithTrigger<>();
executor.execute(() -> {
try {
T res = callable.call();
futureWithTrigger.getTrigger().completed(res);
} catch (Exception ex) {
futureWithTrigger.getTrigger().failed(ex);
}
});
return futureWithTrigger.getFuture();
}
/**
* Returns a future that will be known when all of the futures passed as arguments are known
* @param futures
* @param <T>
* @return a {@link java.util.Set} with the result of all the futures
*/
public static <T> Future<Set<T>> all(Future<T>... futures) {
FuturePool<T> pool = new FuturePool<>();
for(Future<T> future: futures) {
pool.listen(future);
}
return pool.all();
}
/**
* Returns a future that will be known when all of the futures passed as arguments are known
* @param futures
* @param <T>
* @return a {@link java.util.Set} with the result of all the futures
*/
public static <T> Future<Set<T>> all(Iterable<Future<T>> futures) {
FuturePool<T> pool = new FuturePool<>();
for(Future<T> future: futures) {
pool.listen(future);
}
return pool.all();
}
/**
* Returns a future that will be known when any of the futures passed as arguments are known
* @param futures
* @param <T>
* @return the result of the first future to be known
*/
public static <T> Future<T> any(Future<T>... futures) {
FuturePool<T> pool = new FuturePool<>();
for(Future<T> future: futures) {
pool.listen(future);
}
return pool.first();
}
/**
* Returns a future that will be known when any of the futures passed as arguments are known
* @param futures
* @param <T>
* @return the result of the first future to be known
*/
public static <T> Future<T> any(Iterable<Future<T>> futures) {
FuturePool<T> pool = new FuturePool<>();
for(Future<T> future: futures) {
pool.listen(future);
}
return pool.first();
}
}