All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.windmill.utils.Futures Maven / Gradle / Ivy

There is a newer version: 0.2
Show newest version
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