Skip to content

Commit e7714b0

Browse files
java-team-github-botGoogle Java Core Libraries
authored and
Google Java Core Libraries
committedJun 2, 2023
Add Duration-based default methods to ListeningExecutorService
They just delegate to the existing methods from the interface, using the existing saturated conversion to nanoseconds. This matches existing `Duration`-based overloads of `(long, TimeUnit)` methods in the same package. RELNOTES=`util.concurrent`: Added `Duration`-based `default` methods to `ListeningExecutorService`. PiperOrigin-RevId: 537286950
1 parent 5c23590 commit e7714b0

File tree

2 files changed

+174
-0
lines changed

2 files changed

+174
-0
lines changed
 
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
/*
2+
* Copyright (C) 2020 The Guava Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.common.util.concurrent;
18+
19+
import static com.google.common.truth.Truth.assertThat;
20+
import static com.google.common.util.concurrent.Futures.immediateFailedFuture;
21+
import static com.google.common.util.concurrent.Futures.immediateFuture;
22+
import static java.util.concurrent.TimeUnit.NANOSECONDS;
23+
24+
import java.time.Duration;
25+
import java.util.Collection;
26+
import java.util.Collections;
27+
import java.util.List;
28+
import java.util.Set;
29+
import java.util.concurrent.Callable;
30+
import java.util.concurrent.ExecutionException;
31+
import java.util.concurrent.Future;
32+
import java.util.concurrent.TimeUnit;
33+
import java.util.concurrent.TimeoutException;
34+
import junit.framework.TestCase;
35+
36+
public final class ListeningExecutorServiceTest extends TestCase {
37+
38+
private Collection<? extends Callable<?>> recordedTasks;
39+
private long recordedTimeout;
40+
private TimeUnit recordedTimeUnit;
41+
42+
private final ListeningExecutorService executorService = new FakeExecutorService();
43+
44+
public void testInvokeAny() throws Exception {
45+
Set<Callable<String>> tasks = Collections.singleton(() -> "invokeAny");
46+
47+
String result = executorService.invokeAny(tasks, Duration.ofSeconds(7));
48+
49+
assertThat(result).isEqualTo("invokeAny");
50+
assertThat(recordedTasks).isSameInstanceAs(tasks);
51+
assertThat(recordedTimeUnit).isEqualTo(NANOSECONDS);
52+
assertThat(Duration.ofNanos(recordedTimeout)).isEqualTo(Duration.ofSeconds(7));
53+
}
54+
55+
public void testInvokeAll() throws Exception {
56+
Set<Callable<String>> tasks = Collections.singleton(() -> "invokeAll");
57+
58+
List<Future<String>> result = executorService.invokeAll(tasks, Duration.ofDays(365));
59+
60+
assertThat(result).hasSize(1);
61+
assertThat(Futures.getDone(result.get(0))).isEqualTo("invokeAll");
62+
assertThat(recordedTasks).isSameInstanceAs(tasks);
63+
assertThat(recordedTimeUnit).isEqualTo(NANOSECONDS);
64+
assertThat(Duration.ofNanos(recordedTimeout)).isEqualTo(Duration.ofDays(365));
65+
}
66+
67+
public void testAwaitTermination() throws Exception {
68+
boolean result = executorService.awaitTermination(Duration.ofMinutes(144));
69+
70+
assertThat(result).isTrue();
71+
assertThat(recordedTimeUnit).isEqualTo(NANOSECONDS);
72+
assertThat(Duration.ofNanos(recordedTimeout)).isEqualTo(Duration.ofMinutes(144));
73+
}
74+
75+
private class FakeExecutorService extends AbstractListeningExecutorService {
76+
@Override
77+
public <T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit)
78+
throws InterruptedException, ExecutionException, TimeoutException {
79+
recordedTasks = tasks;
80+
recordedTimeout = timeout;
81+
recordedTimeUnit = unit;
82+
try {
83+
return tasks.iterator().next().call();
84+
} catch (Exception e) {
85+
throw new ExecutionException(e);
86+
}
87+
}
88+
89+
@Override
90+
public <T> List<Future<T>> invokeAll(
91+
Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit)
92+
throws InterruptedException {
93+
recordedTasks = tasks;
94+
recordedTimeout = timeout;
95+
recordedTimeUnit = unit;
96+
try {
97+
return Collections.singletonList(immediateFuture(tasks.iterator().next().call()));
98+
} catch (Exception e) {
99+
return Collections.singletonList(immediateFailedFuture(e));
100+
}
101+
}
102+
103+
@Override
104+
public boolean awaitTermination(long timeout, TimeUnit unit) {
105+
recordedTimeout = timeout;
106+
recordedTimeUnit = unit;
107+
return true;
108+
}
109+
110+
@Override
111+
public void execute(Runnable runnable) {
112+
throw new UnsupportedOperationException();
113+
}
114+
115+
@Override
116+
public void shutdown() {
117+
throw new UnsupportedOperationException();
118+
}
119+
120+
@Override
121+
public List<Runnable> shutdownNow() {
122+
throw new UnsupportedOperationException();
123+
}
124+
125+
@Override
126+
public boolean isShutdown() {
127+
throw new UnsupportedOperationException();
128+
}
129+
130+
@Override
131+
public boolean isTerminated() {
132+
throw new UnsupportedOperationException();
133+
}
134+
}
135+
}

‎guava/src/com/google/common/util/concurrent/ListeningExecutorService.java

+39
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,21 @@
1414

1515
package com.google.common.util.concurrent;
1616

17+
import static com.google.common.util.concurrent.Internal.toNanosSaturated;
18+
1719
import com.google.common.annotations.GwtIncompatible;
20+
import com.google.common.annotations.J2ktIncompatible;
1821
import com.google.errorprone.annotations.DoNotMock;
22+
import java.time.Duration;
1923
import java.util.Collection;
2024
import java.util.List;
2125
import java.util.concurrent.Callable;
26+
import java.util.concurrent.ExecutionException;
2227
import java.util.concurrent.ExecutorService;
2328
import java.util.concurrent.Future;
2429
import java.util.concurrent.RejectedExecutionException;
2530
import java.util.concurrent.TimeUnit;
31+
import java.util.concurrent.TimeoutException;
2632
import org.checkerframework.checker.nullness.qual.Nullable;
2733

2834
/**
@@ -106,4 +112,37 @@ public interface ListeningExecutorService extends ExecutorService {
106112
<T extends @Nullable Object> List<Future<T>> invokeAll(
107113
Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit)
108114
throws InterruptedException;
115+
116+
/**
117+
* Duration-based overload of {@link #invokeAll(Collection, long, TimeUnit)}.
118+
*
119+
* @since NEXT
120+
*/
121+
@J2ktIncompatible
122+
default <T extends @Nullable Object> List<Future<T>> invokeAll(
123+
Collection<? extends Callable<T>> tasks, Duration timeout) throws InterruptedException {
124+
return invokeAll(tasks, toNanosSaturated(timeout), TimeUnit.NANOSECONDS);
125+
}
126+
127+
/**
128+
* Duration-based overload of {@link #invokeAny(Collection, long, TimeUnit)}.
129+
*
130+
* @since NEXT
131+
*/
132+
@J2ktIncompatible
133+
default <T extends @Nullable Object> T invokeAny(
134+
Collection<? extends Callable<T>> tasks, Duration timeout)
135+
throws InterruptedException, ExecutionException, TimeoutException {
136+
return invokeAny(tasks, toNanosSaturated(timeout), TimeUnit.NANOSECONDS);
137+
}
138+
139+
/**
140+
* Duration-based overload of {@link #awaitTermination(long, TimeUnit)}.
141+
*
142+
* @since NEXT
143+
*/
144+
@J2ktIncompatible
145+
default boolean awaitTermination(Duration timeout) throws InterruptedException {
146+
return awaitTermination(toNanosSaturated(timeout), TimeUnit.NANOSECONDS);
147+
}
109148
}

0 commit comments

Comments
 (0)
Please sign in to comment.