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

com.databasesandlife.util.Future Maven / Gradle / Ivy

package com.databasesandlife.util;

import java.util.Iterator;

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;

/**
 * A future is the response of a calculation which is done in the background (in a thread).
 *     

* A future has the method {@link #get()} which waits for the calculation to complete, and returns the result. * The client must create a subclass and implement the method {@link #populate()} which will be run in the thread. *

* The reason for the creation of this class is the JVM-supplied {@link java.util.concurrent.Future} object seemed too complex. * * @author This source is copyright Adrian Smith and licensed under the LGPL 3. * @see Project on GitHub */ @SuppressWarnings("serial") public abstract class Future { T result = null; RuntimeException exception = null; Thread thread; /** Calculate the result and return it. Must not return null. */ protected abstract T populate(); public static class FutureComputationTimedOutException extends Exception { } @SuppressFBWarnings("SC_START_IN_CTOR") public Future() { thread = new Thread(new Runnable() { @Override public void run() { try { T localResult = populate(); synchronized (Future.this) { result = localResult; } } catch (RuntimeException e) { synchronized (Future.this) { exception = e; } } } }, getThreadName()); thread.start(); } protected String getThreadName() { return "Future-" + getClass().getSimpleName(); } /** Same as {@link #get()} but times out after 'seconds' seconds. */ public T getOrTimeoutAfterSeconds(float seconds) throws FutureComputationTimedOutException { try { thread.join((int) (1000000 * seconds)); } catch (InterruptedException e) { throw new RuntimeException(e); } synchronized (this) { if (result == null && exception == null) throw new FutureComputationTimedOutException(); if (exception != null) throw new RuntimeException(exception); // wrap exception to preserve its stack backtrace return result; } } /** Returns the object, waiting for its computation to be completed if necessary. */ public T get() { try { return getOrTimeoutAfterSeconds(0); } catch (FutureComputationTimedOutException e) { throw new RuntimeException("impossible", e); } } /** * An iterable whose values are computed in the background. * The populate method must return an iterable. */ public abstract static class IterableFuture extends Future> implements Iterable { @Override public Iterator iterator() { return get().iterator(); } } }