| // Copyright 2016 Google Inc. All Rights Reserved. |
| package com.android.contacts.util.concurrent; |
| |
| import android.os.Handler; |
| |
| import com.google.common.util.concurrent.AsyncFunction; |
| import com.google.common.util.concurrent.Futures; |
| import com.google.common.util.concurrent.ListenableFuture; |
| import com.google.common.util.concurrent.MoreExecutors; |
| |
| import java.util.concurrent.CancellationException; |
| import java.util.concurrent.ScheduledExecutorService; |
| import java.util.concurrent.TimeUnit; |
| import java.util.concurrent.TimeoutException; |
| import java.util.concurrent.atomic.AtomicBoolean; |
| |
| /** |
| * Has utility methods for operating on ListenableFutures |
| */ |
| public class FuturesUtil { |
| |
| /** |
| * See |
| * {@link FuturesUtil#withTimeout(ListenableFuture, long, TimeUnit, ScheduledExecutorService)} |
| */ |
| public static <V> ListenableFuture<V> withTimeout(final ListenableFuture<V> future, long time, |
| TimeUnit unit, Handler handler) { |
| return withTimeout(future, time, unit, ContactsExecutors.newHandlerExecutor(handler)); |
| } |
| |
| /** |
| * Returns a future that completes with the result from the input future unless the specified |
| * time elapses before it finishes in which case the result will contain a TimeoutException and |
| * the input future will be canceled. |
| * |
| * <p>Guava has Futures.withTimeout but it isn't available until v19.0 and we depend on v14.0 |
| * right now. Replace usages of this method if we upgrade our dependency.</p> |
| */ |
| public static <V> ListenableFuture<V> withTimeout(final ListenableFuture<V> future, long time, |
| TimeUnit unit, ScheduledExecutorService executor) { |
| final AtomicBoolean didTimeout = new AtomicBoolean(false); |
| executor.schedule(new Runnable() { |
| @Override |
| public void run() { |
| didTimeout.set(!future.isDone() && !future.isCancelled()); |
| future.cancel(true); |
| } |
| }, time, unit); |
| |
| return Futures.catchingAsync(future, Throwable.class, new AsyncFunction<Throwable, V>() { |
| @Override |
| public ListenableFuture<V> apply(Throwable t) throws Exception { |
| if ((t instanceof CancellationException) && didTimeout.get()) { |
| return Futures.immediateFailedFuture(new TimeoutException("Timeout expired")); |
| } |
| return Futures.immediateFailedFuture(t); |
| } |
| }, MoreExecutors.directExecutor()); |
| } |
| } |