Example usage for com.google.common.util.concurrent ValueFuture create

List of usage examples for com.google.common.util.concurrent ValueFuture create

Introduction

In this page you can find the example usage for com.google.common.util.concurrent ValueFuture create.

Prototype

public static <T> ValueFuture<T> create() 

Source Link

Document

Creates a new ValueFuture in the default state.

Usage

From source file:de.cosmocode.palava.cache.AbstractComputingCacheService.java

@Override
public final <V> V computeAndStore(Serializable key, Callable<? extends V> callable, CacheExpiration expiration)
        throws CancellationException, ExecutionException {

    Preconditions.checkNotNull(key, "Key");
    Preconditions.checkNotNull(callable, "Callable");
    Preconditions.checkNotNull(expiration, "Expiration");

    final Collection<ValueFuture<Object>> futures = computations.get(key);
    final ValueFuture<Object> future = ValueFuture.create();

    // it's important to do this asap, to allow other callers
    // to wait on read instead of starting the same computation
    futures.add(future);/*from  www.j  a  v  a 2s. co m*/

    try {
        log.trace("Computing value for key '{}' using {}", key, callable);
        final V value = callable.call();

        if (future.isCancelled()) {
            log.warn("{} has been cancelled", future);
        } else if (future.isDone()) {
            log.trace("Another computation was faster and already computed a value for key '{}'", key);
        } else {
            log.trace("Computed value '{}' for key '{}'", value, key);
            future.set(value);
            for (ValueFuture<Object> other : futures) {
                if (other == future) {
                    // every computation after this is newer
                    break;
                } else if (other.isDone()) {
                    log.trace("Skipping finished computation: {}", other);
                    continue;
                } else {
                    // make older and still running computations use my computed value
                    log.trace("Setting faster computed value '{}' on {}", value, other);
                    other.set(value);
                }
            }
            log.trace("Storing '{}' to '{}' in underlying store", key, value);
            doStore(key, value, expiration);
        }

        final V returned = this.<V>cast(future.get());
        if (returned == null) {
            log.trace("Key '{}' has been removed during computation, returning value '{}'", key, value);
            return value;
        } else {
            log.trace("Returning value '{}' for key '{}'", returned, key);
            return returned;
        }
    } catch (ExecutionException e) {
        log.warn("Exception during {}.call()", callable);
        future.setException(e.getCause());
        throw e;
        /* CHECKSTYLE:OFF */
    } catch (Exception e) {
        /* CHECKSTYLE:ON */
        log.warn("Exception during {}.call()", callable);
        future.setException(e);
        throw new ExecutionException(e);
    } finally {
        futures.remove(future);
    }
}

From source file:de.cosmocode.palava.cache.DefaultComputingCacheRegion.java

@Override
public V computeAndPut(K key, Callable<? extends V> computation, CacheExpiration expiration)
        throws ExecutionException {

    Preconditions.checkNotNull(key, "Key");
    Preconditions.checkNotNull(computation, "Computation");
    Preconditions.checkNotNull(expiration, "Expiration");

    final Collection<ValueFuture<V>> futures = computations.get(key);
    final ValueFuture<V> future = ValueFuture.create();

    // it's important to do this asap, to allow other callers
    // to wait on read instead of starting the same computation
    futures.add(future);//ww  w . java2s  .c  o m

    try {
        LOG.trace("Computing value for key '{}' using {}", key, computation);
        final V value = computation.call();

        if (future.isCancelled()) {
            LOG.warn("{} has been cancelled", future);
        } else if (future.isDone()) {
            LOG.trace("Another computation was faster and already computed a value for key '{}'", key);
        } else {
            LOG.trace("Computed value '{}' for key '{}'", value, key);
            future.set(value);
            for (ValueFuture<V> other : futures) {
                if (other == future) {
                    // every computation after this is newer
                    break;
                } else if (other.isDone()) {
                    LOG.trace("Skipping finished computation: {}", other);
                    continue;
                } else {
                    // make older and still running computations use my
                    // computed value
                    LOG.trace("Setting faster computed value '{}' on {}", value, other);
                    other.set(value);
                }
            }
            LOG.trace("Storing '{}' to '{}' in underlying store", key, value);
            region.put(key, value, expiration);
        }

        final V returned = future.get();
        if (returned == null) {
            LOG.trace("Key '{}' has been removed during computation, returning computed value '{}'", key,
                    value);
            return value;
        } else {
            LOG.trace("Returning value '{}' for key '{}'", returned, key);
            return returned;
        }
    } catch (ExecutionException e) {
        LOG.warn("Exception during {}.call()", computation);
        future.setException(e.getCause());
        throw e;
        /* CHECKSTYLE:OFF */
    } catch (Exception e) {
        /* CHECKSTYLE:ON */
        LOG.warn("Exception during {}.call()", computation);
        future.setException(e);
        throw new ExecutionException(e);
    } finally {
        futures.remove(future);
    }

}