io.windmill.utils.Futures Maven / Gradle / Ivy
package io.windmill.utils;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import io.windmill.core.CPU;
import io.windmill.core.Future;
public class Futures
{
private Futures()
{}
public static T await(Future future) throws Throwable
{
AtomicReference value = new AtomicReference<>();
AtomicReference exception = new AtomicReference<>();
CountDownLatch latch = new CountDownLatch(1);
future.onSuccess(value::set);
future.onFailure(exception::set);
future.onComplete(latch::countDown);
awaitUninterruptibly(latch);
if (future.isFailure())
throw exception.get();
return value.get();
}
public static Future voidFuture(CPU cpu)
{
return constantFuture(cpu, null);
}
public static Future constantFuture(CPU cpu, T value)
{
return new ConstantFuture<>(cpu, value);
}
public static Future failedFuture(CPU cpu, Throwable e)
{
return new FailedFuture<>(cpu, e);
}
private static class FailedFuture extends Future
{
public FailedFuture(CPU cpu, Throwable e)
{
super(cpu);
setFailure(e);
}
}
private static class ConstantFuture extends Future
{
public ConstantFuture(CPU cpu, T value)
{
super(cpu);
setValue(value);
}
}
/* await/sleep methods where taken from Guava utilities and slightly modified */
/**
* Invokes {@code latch.}{@link CountDownLatch#await() await()} uninterruptibly.
*
* @param latch The latch to wait on
*/
public static void awaitUninterruptibly(CountDownLatch latch)
{
boolean interrupted = false;
try
{
while (true)
{
try
{
latch.await();
return;
}
catch (InterruptedException e)
{
interrupted = true;
}
}
}
finally
{
if (interrupted)
Thread.currentThread().interrupt();
}
}
/**
* Invokes {@code latch.}{@link CountDownLatch#await(long, TimeUnit) await(timeout, unit)} uninterruptibly.
*
* @param latch The latch to wait on
* @param timeout The amount of time to wait on the given latch
* @param unit The time unit of the timeout
*
* @return true if latch waiting completed successfully, false otherwise.
*/
public static boolean awaitUninterruptibly(CountDownLatch latch, long timeout, TimeUnit unit)
{
boolean interrupted = false;
try
{
long remainingNanos = unit.toNanos(timeout);
long end = System.nanoTime() + remainingNanos;
while (true)
{
try
{
// CountDownLatch treats negative timeouts just like zero.
return latch.await(remainingNanos, TimeUnit.NANOSECONDS);
}
catch (InterruptedException e)
{
interrupted = true;
remainingNanos = end - System.nanoTime();
}
}
}
finally
{
if (interrupted)
Thread.currentThread().interrupt();
}
}
/**
* Invokes {@code unit.}{@link TimeUnit#sleep(long) sleep(sleepFor)} uninterruptibly.
*
* @param sleepFor The amount of type to sleep
* @param unit The time unit of the sleep duration
*/
public static void sleepUninterruptibly(long sleepFor, TimeUnit unit)
{
boolean interrupted = false;
try
{
long remainingNanos = unit.toNanos(sleepFor);
long end = System.nanoTime() + remainingNanos;
while (true)
{
try
{
// TimeUnit.sleep() treats negative timeouts just like zero.
TimeUnit.NANOSECONDS.sleep(remainingNanos);
return;
}
catch (InterruptedException e)
{
interrupted = true;
remainingNanos = end - System.nanoTime();
}
}
}
finally
{
if (interrupted)
Thread.currentThread().interrupt();
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy