Skip to content

Commit

Permalink
Add Futures.submit().
Browse files Browse the repository at this point in the history
RELNOTES=`util.concurrent`: Added `Futures.submit()`

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=271840585
  • Loading branch information
mverver-google authored and cpovirk committed Sep 30, 2019
1 parent 5a8f19b commit c7ef0cc
Show file tree
Hide file tree
Showing 5 changed files with 316 additions and 0 deletions.
Expand Up @@ -35,6 +35,7 @@
import static com.google.common.util.concurrent.Futures.lazyTransform;
import static com.google.common.util.concurrent.Futures.nonCancellationPropagating;
import static com.google.common.util.concurrent.Futures.scheduleAsync;
import static com.google.common.util.concurrent.Futures.submit;
import static com.google.common.util.concurrent.Futures.submitAsync;
import static com.google.common.util.concurrent.Futures.successfulAsList;
import static com.google.common.util.concurrent.Futures.transform;
Expand Down Expand Up @@ -1937,6 +1938,82 @@ public void testSubmitAsync_asyncCallable_returnsInterruptedFuture() throws Inte
assertThat(Thread.interrupted()).isFalse();
}

public void testSubmit_callable_returnsValue() throws Exception {
Callable<Integer> callable =
new Callable<Integer>() {
@Override
public Integer call() {
return 42;
}
};
ListenableFuture<Integer> future = submit(callable, directExecutor());
assertThat(future.isDone()).isTrue();
assertThat(getDone(future)).isEqualTo(42);
}

public void testSubmit_callable_throwsException() {
final Exception exception = new Exception("Exception for testing");
Callable<Integer> callable =
new Callable<Integer>() {
@Override
public Integer call() throws Exception {
throw exception;
}
};
ListenableFuture<Integer> future = submit(callable, directExecutor());
try {
getDone(future);
fail();
} catch (ExecutionException expected) {
assertThat(expected).hasCauseThat().isSameInstanceAs(exception);
}
}

public void testSubmit_runnable_completesAfterRun() throws Exception {
final List<Runnable> pendingRunnables = newArrayList();
final List<Runnable> executedRunnables = newArrayList();
Runnable runnable =
new Runnable() {
@Override
public void run() {
executedRunnables.add(this);
}
};
Executor executor =
new Executor() {
@Override
public void execute(Runnable runnable) {
pendingRunnables.add(runnable);
}
};
ListenableFuture<Void> future = submit(runnable, executor);
assertThat(future.isDone()).isFalse();
assertThat(executedRunnables).isEmpty();
assertThat(pendingRunnables).hasSize(1);
pendingRunnables.remove(0).run();
assertThat(future.isDone()).isTrue();
assertThat(executedRunnables).containsExactly(runnable);
assertThat(pendingRunnables).isEmpty();
}

public void testSubmit_runnable_throwsException() throws Exception {
final RuntimeException exception = new RuntimeException("Exception for testing");
Runnable runnable =
new Runnable() {
@Override
public void run() {
throw exception;
}
};
ListenableFuture<Void> future = submit(runnable, directExecutor());
try {
getDone(future);
fail();
} catch (ExecutionException expected) {
assertThat(expected).hasCauseThat().isSameInstanceAs(exception);
}
}

@GwtIncompatible // threads

public void testScheduleAsync_asyncCallable_error() throws InterruptedException {
Expand Down
27 changes: 27 additions & 0 deletions android/guava/src/com/google/common/util/concurrent/Futures.java
Expand Up @@ -154,6 +154,33 @@ public static <V> ListenableFuture<V> immediateCancelledFuture() {
return new ImmediateCancelledFuture<V>();
}

/**
* Executes {@code callable} on the specified {@code executor}, returning a {@code Future}.
*
* @throws RejectedExecutionException if the task cannot be scheduled for execution
* @since NEXT
*/
@Beta
public static <O> ListenableFuture<O> submit(Callable<O> callable, Executor executor) {
TrustedListenableFutureTask<O> task = TrustedListenableFutureTask.create(callable);
executor.execute(task);
return task;
}

/**
* Executes {@code runnable} on the specified {@code executor}, returning a {@code Future} that
* will complete after execution.
*
* @throws RejectedExecutionException if the task cannot be scheduled for execution
* @since NEXT
*/
@Beta
public static ListenableFuture<Void> submit(Runnable runnable, Executor executor) {
TrustedListenableFutureTask<Void> task = TrustedListenableFutureTask.create(runnable, null);
executor.execute(task);
return task;
}

/**
* Executes {@code callable} on the specified {@code executor}, returning a {@code Future}.
*
Expand Down
108 changes: 108 additions & 0 deletions guava-gwt/test/com/google/common/util/concurrent/FuturesTest_gwt.java
Expand Up @@ -1908,6 +1908,114 @@ public void testSubmitAsync_asyncCallable_nullInsteadOfFuture() throws Exception
}
}

public void testSubmit_callable_returnsValue() throws Exception {
com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
testCase.setUp();
Throwable failure = null;
try {
testCase.testSubmit_callable_returnsValue();
} catch (Throwable t) {
failure = t;
}
try {
testCase.tearDown();
} catch (Throwable t) {
if (failure == null) {
failure = t;
}
}
if (failure instanceof Exception) {
throw (Exception) failure;
}
if (failure instanceof Error) {
throw (Error) failure;
}
if (failure != null) {
throw new RuntimeException(failure);
}
}

public void testSubmit_callable_throwsException() throws Exception {
com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
testCase.setUp();
Throwable failure = null;
try {
testCase.testSubmit_callable_throwsException();
} catch (Throwable t) {
failure = t;
}
try {
testCase.tearDown();
} catch (Throwable t) {
if (failure == null) {
failure = t;
}
}
if (failure instanceof Exception) {
throw (Exception) failure;
}
if (failure instanceof Error) {
throw (Error) failure;
}
if (failure != null) {
throw new RuntimeException(failure);
}
}

public void testSubmit_runnable_completesAfterRun() throws Exception {
com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
testCase.setUp();
Throwable failure = null;
try {
testCase.testSubmit_runnable_completesAfterRun();
} catch (Throwable t) {
failure = t;
}
try {
testCase.tearDown();
} catch (Throwable t) {
if (failure == null) {
failure = t;
}
}
if (failure instanceof Exception) {
throw (Exception) failure;
}
if (failure instanceof Error) {
throw (Error) failure;
}
if (failure != null) {
throw new RuntimeException(failure);
}
}

public void testSubmit_runnable_throwsException() throws Exception {
com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
testCase.setUp();
Throwable failure = null;
try {
testCase.testSubmit_runnable_throwsException();
} catch (Throwable t) {
failure = t;
}
try {
testCase.tearDown();
} catch (Throwable t) {
if (failure == null) {
failure = t;
}
}
if (failure instanceof Exception) {
throw (Exception) failure;
}
if (failure instanceof Error) {
throw (Error) failure;
}
if (failure != null) {
throw new RuntimeException(failure);
}
}

public void testSuccessfulAsList() throws Exception {
com.google.common.util.concurrent.FuturesTest testCase = new com.google.common.util.concurrent.FuturesTest();
testCase.setUp();
Expand Down
Expand Up @@ -35,6 +35,7 @@
import static com.google.common.util.concurrent.Futures.lazyTransform;
import static com.google.common.util.concurrent.Futures.nonCancellationPropagating;
import static com.google.common.util.concurrent.Futures.scheduleAsync;
import static com.google.common.util.concurrent.Futures.submit;
import static com.google.common.util.concurrent.Futures.submitAsync;
import static com.google.common.util.concurrent.Futures.successfulAsList;
import static com.google.common.util.concurrent.Futures.transform;
Expand Down Expand Up @@ -1937,6 +1938,82 @@ public void testSubmitAsync_asyncCallable_returnsInterruptedFuture() throws Inte
assertThat(Thread.interrupted()).isFalse();
}

public void testSubmit_callable_returnsValue() throws Exception {
Callable<Integer> callable =
new Callable<Integer>() {
@Override
public Integer call() {
return 42;
}
};
ListenableFuture<Integer> future = submit(callable, directExecutor());
assertThat(future.isDone()).isTrue();
assertThat(getDone(future)).isEqualTo(42);
}

public void testSubmit_callable_throwsException() {
final Exception exception = new Exception("Exception for testing");
Callable<Integer> callable =
new Callable<Integer>() {
@Override
public Integer call() throws Exception {
throw exception;
}
};
ListenableFuture<Integer> future = submit(callable, directExecutor());
try {
getDone(future);
fail();
} catch (ExecutionException expected) {
assertThat(expected).hasCauseThat().isSameInstanceAs(exception);
}
}

public void testSubmit_runnable_completesAfterRun() throws Exception {
final List<Runnable> pendingRunnables = newArrayList();
final List<Runnable> executedRunnables = newArrayList();
Runnable runnable =
new Runnable() {
@Override
public void run() {
executedRunnables.add(this);
}
};
Executor executor =
new Executor() {
@Override
public void execute(Runnable runnable) {
pendingRunnables.add(runnable);
}
};
ListenableFuture<Void> future = submit(runnable, executor);
assertThat(future.isDone()).isFalse();
assertThat(executedRunnables).isEmpty();
assertThat(pendingRunnables).hasSize(1);
pendingRunnables.remove(0).run();
assertThat(future.isDone()).isTrue();
assertThat(executedRunnables).containsExactly(runnable);
assertThat(pendingRunnables).isEmpty();
}

public void testSubmit_runnable_throwsException() throws Exception {
final RuntimeException exception = new RuntimeException("Exception for testing");
Runnable runnable =
new Runnable() {
@Override
public void run() {
throw exception;
}
};
ListenableFuture<Void> future = submit(runnable, directExecutor());
try {
getDone(future);
fail();
} catch (ExecutionException expected) {
assertThat(expected).hasCauseThat().isSameInstanceAs(exception);
}
}

@GwtIncompatible // threads

public void testScheduleAsync_asyncCallable_error() throws InterruptedException {
Expand Down
27 changes: 27 additions & 0 deletions guava/src/com/google/common/util/concurrent/Futures.java
Expand Up @@ -156,6 +156,33 @@ public static <V> ListenableFuture<V> immediateCancelledFuture() {
return new ImmediateCancelledFuture<V>();
}

/**
* Executes {@code callable} on the specified {@code executor}, returning a {@code Future}.
*
* @throws RejectedExecutionException if the task cannot be scheduled for execution
* @since NEXT
*/
@Beta
public static <O> ListenableFuture<O> submit(Callable<O> callable, Executor executor) {
TrustedListenableFutureTask<O> task = TrustedListenableFutureTask.create(callable);
executor.execute(task);
return task;
}

/**
* Executes {@code runnable} on the specified {@code executor}, returning a {@code Future} that
* will complete after execution.
*
* @throws RejectedExecutionException if the task cannot be scheduled for execution
* @since NEXT
*/
@Beta
public static ListenableFuture<Void> submit(Runnable runnable, Executor executor) {
TrustedListenableFutureTask<Void> task = TrustedListenableFutureTask.create(runnable, null);
executor.execute(task);
return task;
}

/**
* Executes {@code callable} on the specified {@code executor}, returning a {@code Future}.
*
Expand Down

0 comments on commit c7ef0cc

Please sign in to comment.