2015-01-30 14:04:06 +01:00
|
|
|
/*
|
|
|
|
* Copyright 2015 The Netty Project
|
|
|
|
*
|
|
|
|
* The Netty Project licenses this file to you under the Apache License,
|
|
|
|
* version 2.0 (the "License"); you may not use this file except in compliance
|
|
|
|
* with the License. You may obtain a copy of the License at:
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
|
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
|
|
* License for the specific language governing permissions and limitations
|
|
|
|
* under the License.
|
|
|
|
*/
|
|
|
|
package io.netty.util.concurrent;
|
|
|
|
|
2017-11-11 08:09:32 +01:00
|
|
|
import io.netty.util.internal.DefaultPriorityQueue;
|
2015-01-30 14:04:06 +01:00
|
|
|
import io.netty.util.internal.ObjectUtil;
|
2017-11-11 08:09:32 +01:00
|
|
|
import io.netty.util.internal.PriorityQueue;
|
2019-01-23 08:32:05 +01:00
|
|
|
import io.netty.util.internal.PriorityQueueNode;
|
2015-01-30 14:04:06 +01:00
|
|
|
|
2017-11-11 08:09:32 +01:00
|
|
|
import java.util.Comparator;
|
2015-01-30 14:04:06 +01:00
|
|
|
import java.util.Queue;
|
|
|
|
import java.util.concurrent.Callable;
|
2019-01-23 08:32:05 +01:00
|
|
|
import java.util.concurrent.Delayed;
|
|
|
|
import java.util.concurrent.ExecutionException;
|
2015-01-30 14:04:06 +01:00
|
|
|
import java.util.concurrent.Executors;
|
|
|
|
import java.util.concurrent.TimeUnit;
|
2019-01-23 08:32:05 +01:00
|
|
|
import java.util.concurrent.TimeoutException;
|
2015-01-30 14:04:06 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Abstract base class for {@link EventExecutor}s that want to support scheduling.
|
|
|
|
*/
|
|
|
|
public abstract class AbstractScheduledEventExecutor extends AbstractEventExecutor {
|
2019-01-23 08:32:05 +01:00
|
|
|
static final long START_TIME = System.nanoTime();
|
2015-01-30 14:04:06 +01:00
|
|
|
|
2019-01-23 08:32:05 +01:00
|
|
|
private static final Comparator<RunnableScheduledFutureNode<?>> SCHEDULED_FUTURE_TASK_COMPARATOR =
|
|
|
|
new Comparator<RunnableScheduledFutureNode<?>>() {
|
2017-11-11 08:09:32 +01:00
|
|
|
@Override
|
2019-01-23 08:32:05 +01:00
|
|
|
public int compare(RunnableScheduledFutureNode<?> o1, RunnableScheduledFutureNode<?> o2) {
|
2017-11-11 08:09:32 +01:00
|
|
|
return o1.compareTo(o2);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2019-01-23 08:32:05 +01:00
|
|
|
private PriorityQueue<RunnableScheduledFutureNode<?>> scheduledTaskQueue;
|
2015-01-30 14:04:06 +01:00
|
|
|
|
|
|
|
protected AbstractScheduledEventExecutor() {
|
|
|
|
}
|
|
|
|
|
2019-01-23 08:32:05 +01:00
|
|
|
/**
|
|
|
|
* The time elapsed since initialization of this class in nanoseconds. This may return a negative number just like
|
|
|
|
* {@link System#nanoTime()}.
|
|
|
|
*/
|
|
|
|
public static long nanoTime() {
|
|
|
|
return System.nanoTime() - START_TIME;
|
2015-01-30 14:04:06 +01:00
|
|
|
}
|
|
|
|
|
2019-01-23 08:32:05 +01:00
|
|
|
/**
|
|
|
|
* The deadline (in nanoseconds) for a given delay (in nanoseconds).
|
|
|
|
*/
|
|
|
|
static long deadlineNanos(long delay) {
|
|
|
|
long deadlineNanos = nanoTime() + delay;
|
|
|
|
// Guard against overflow
|
|
|
|
return deadlineNanos < 0 ? Long.MAX_VALUE : deadlineNanos;
|
2015-01-30 14:04:06 +01:00
|
|
|
}
|
|
|
|
|
2019-01-23 08:32:05 +01:00
|
|
|
PriorityQueue<RunnableScheduledFutureNode<?>> scheduledTaskQueue() {
|
2015-01-30 14:04:06 +01:00
|
|
|
if (scheduledTaskQueue == null) {
|
2019-01-22 16:07:26 +01:00
|
|
|
scheduledTaskQueue = new DefaultPriorityQueue<>(
|
2017-11-11 08:09:32 +01:00
|
|
|
SCHEDULED_FUTURE_TASK_COMPARATOR,
|
|
|
|
// Use same initial capacity as java.util.PriorityQueue
|
|
|
|
11);
|
2015-01-30 14:04:06 +01:00
|
|
|
}
|
|
|
|
return scheduledTaskQueue;
|
|
|
|
}
|
|
|
|
|
2019-01-23 08:32:05 +01:00
|
|
|
private static boolean isNullOrEmpty(Queue<RunnableScheduledFutureNode<?>> queue) {
|
2015-01-30 14:04:06 +01:00
|
|
|
return queue == null || queue.isEmpty();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Cancel all scheduled tasks.
|
|
|
|
*
|
|
|
|
* This method MUST be called only when {@link #inEventLoop()} is {@code true}.
|
|
|
|
*/
|
2019-01-23 08:32:05 +01:00
|
|
|
protected final void cancelScheduledTasks() {
|
2015-01-30 14:04:06 +01:00
|
|
|
assert inEventLoop();
|
2019-01-23 08:32:05 +01:00
|
|
|
PriorityQueue<RunnableScheduledFutureNode<?>> scheduledTaskQueue = this.scheduledTaskQueue;
|
2015-01-30 14:04:06 +01:00
|
|
|
if (isNullOrEmpty(scheduledTaskQueue)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-01-23 08:32:05 +01:00
|
|
|
final RunnableScheduledFutureNode<?>[] scheduledTasks =
|
|
|
|
scheduledTaskQueue.toArray(new RunnableScheduledFutureNode<?>[0]);
|
2015-01-30 14:04:06 +01:00
|
|
|
|
2019-01-23 08:32:05 +01:00
|
|
|
for (RunnableScheduledFutureNode<?> task: scheduledTasks) {
|
|
|
|
task.cancel(false);
|
2015-01-30 14:04:06 +01:00
|
|
|
}
|
|
|
|
|
2017-11-11 08:09:32 +01:00
|
|
|
scheduledTaskQueue.clearIgnoringIndexes();
|
2015-01-30 14:04:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2017-02-21 21:27:23 +01:00
|
|
|
* @see #pollScheduledTask(long)
|
2015-01-30 14:04:06 +01:00
|
|
|
*/
|
2019-01-23 08:32:05 +01:00
|
|
|
protected final RunnableScheduledFuture<?> pollScheduledTask() {
|
2015-01-30 14:04:06 +01:00
|
|
|
return pollScheduledTask(nanoTime());
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return the {@link Runnable} which is ready to be executed with the given {@code nanoTime}.
|
2018-02-14 02:41:49 +01:00
|
|
|
* You should use {@link #nanoTime()} to retrieve the correct {@code nanoTime}.
|
2019-01-23 08:32:05 +01:00
|
|
|
*
|
|
|
|
* This method MUST be called only when {@link #inEventLoop()} is {@code true}.
|
2015-01-30 14:04:06 +01:00
|
|
|
*/
|
2019-01-23 08:32:05 +01:00
|
|
|
protected final RunnableScheduledFuture<?> pollScheduledTask(long nanoTime) {
|
2015-01-30 14:04:06 +01:00
|
|
|
assert inEventLoop();
|
|
|
|
|
2019-01-23 08:32:05 +01:00
|
|
|
Queue<RunnableScheduledFutureNode<?>> scheduledTaskQueue = this.scheduledTaskQueue;
|
|
|
|
RunnableScheduledFutureNode<?> scheduledTask = scheduledTaskQueue == null ? null : scheduledTaskQueue.peek();
|
2015-01-30 14:04:06 +01:00
|
|
|
if (scheduledTask == null) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (scheduledTask.deadlineNanos() <= nanoTime) {
|
|
|
|
scheduledTaskQueue.remove();
|
|
|
|
return scheduledTask;
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return the nanoseconds when the next scheduled task is ready to be run or {@code -1} if no task is scheduled.
|
2019-01-23 08:32:05 +01:00
|
|
|
*
|
|
|
|
* This method MUST be called only when {@link #inEventLoop()} is {@code true}.
|
2015-01-30 14:04:06 +01:00
|
|
|
*/
|
|
|
|
protected final long nextScheduledTaskNano() {
|
2019-01-23 08:32:05 +01:00
|
|
|
Queue<RunnableScheduledFutureNode<?>> scheduledTaskQueue = this.scheduledTaskQueue;
|
|
|
|
RunnableScheduledFutureNode<?> scheduledTask = scheduledTaskQueue == null ? null : scheduledTaskQueue.peek();
|
2015-01-30 14:04:06 +01:00
|
|
|
if (scheduledTask == null) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return Math.max(0, scheduledTask.deadlineNanos() - nanoTime());
|
|
|
|
}
|
|
|
|
|
2019-01-23 08:32:05 +01:00
|
|
|
final RunnableScheduledFuture<?> peekScheduledTask() {
|
|
|
|
Queue<RunnableScheduledFutureNode<?>> scheduledTaskQueue = this.scheduledTaskQueue;
|
2015-01-30 14:04:06 +01:00
|
|
|
if (scheduledTaskQueue == null) {
|
|
|
|
return null;
|
|
|
|
}
|
2019-01-23 08:32:05 +01:00
|
|
|
RunnableScheduledFutureNode<?> node = scheduledTaskQueue.peek();
|
|
|
|
if (node == null) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
return node;
|
2015-01-30 14:04:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns {@code true} if a scheduled task is ready for processing.
|
2019-01-23 08:32:05 +01:00
|
|
|
*
|
|
|
|
* This method MUST be called only when {@link #inEventLoop()} is {@code true}.
|
2015-01-30 14:04:06 +01:00
|
|
|
*/
|
|
|
|
protected final boolean hasScheduledTasks() {
|
2019-01-23 08:32:05 +01:00
|
|
|
assert inEventLoop();
|
|
|
|
Queue<RunnableScheduledFutureNode<?>> scheduledTaskQueue = this.scheduledTaskQueue;
|
|
|
|
RunnableScheduledFutureNode<?> scheduledTask = scheduledTaskQueue == null ? null : scheduledTaskQueue.peek();
|
2015-01-30 14:04:06 +01:00
|
|
|
return scheduledTask != null && scheduledTask.deadlineNanos() <= nanoTime();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2017-04-18 07:12:58 +02:00
|
|
|
public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) {
|
2015-01-30 14:04:06 +01:00
|
|
|
ObjectUtil.checkNotNull(command, "command");
|
|
|
|
ObjectUtil.checkNotNull(unit, "unit");
|
|
|
|
if (delay < 0) {
|
2017-04-18 07:12:58 +02:00
|
|
|
delay = 0;
|
2015-01-30 14:04:06 +01:00
|
|
|
}
|
2019-01-23 08:32:05 +01:00
|
|
|
RunnableScheduledFuture<?> task = newScheduledTaskFor(Executors.callable(command),
|
|
|
|
deadlineNanos(unit.toNanos(delay)), 0);
|
|
|
|
return schedule(task);
|
2015-01-30 14:04:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit) {
|
|
|
|
ObjectUtil.checkNotNull(callable, "callable");
|
|
|
|
ObjectUtil.checkNotNull(unit, "unit");
|
|
|
|
if (delay < 0) {
|
2017-04-18 07:12:58 +02:00
|
|
|
delay = 0;
|
2015-01-30 14:04:06 +01:00
|
|
|
}
|
2019-01-23 08:32:05 +01:00
|
|
|
RunnableScheduledFuture<V> task = newScheduledTaskFor(callable, deadlineNanos(unit.toNanos(delay)), 0);
|
|
|
|
return schedule(task);
|
2015-01-30 14:04:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) {
|
|
|
|
ObjectUtil.checkNotNull(command, "command");
|
|
|
|
ObjectUtil.checkNotNull(unit, "unit");
|
|
|
|
if (initialDelay < 0) {
|
|
|
|
throw new IllegalArgumentException(
|
|
|
|
String.format("initialDelay: %d (expected: >= 0)", initialDelay));
|
|
|
|
}
|
|
|
|
if (period <= 0) {
|
|
|
|
throw new IllegalArgumentException(
|
|
|
|
String.format("period: %d (expected: > 0)", period));
|
|
|
|
}
|
|
|
|
|
2019-01-23 08:32:05 +01:00
|
|
|
RunnableScheduledFuture<?> task = newScheduledTaskFor(Executors.<Void>callable(command, null),
|
|
|
|
deadlineNanos(unit.toNanos(initialDelay)), unit.toNanos(period));
|
|
|
|
return schedule(task);
|
2015-01-30 14:04:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) {
|
|
|
|
ObjectUtil.checkNotNull(command, "command");
|
|
|
|
ObjectUtil.checkNotNull(unit, "unit");
|
|
|
|
if (initialDelay < 0) {
|
|
|
|
throw new IllegalArgumentException(
|
|
|
|
String.format("initialDelay: %d (expected: >= 0)", initialDelay));
|
|
|
|
}
|
|
|
|
if (delay <= 0) {
|
|
|
|
throw new IllegalArgumentException(
|
|
|
|
String.format("delay: %d (expected: > 0)", delay));
|
|
|
|
}
|
|
|
|
|
2019-01-23 08:32:05 +01:00
|
|
|
RunnableScheduledFuture<?> task = newScheduledTaskFor(Executors.<Void>callable(command, null),
|
|
|
|
deadlineNanos(unit.toNanos(initialDelay)), -unit.toNanos(delay));
|
|
|
|
return schedule(task);
|
2018-05-30 11:11:42 +02:00
|
|
|
}
|
|
|
|
|
2018-04-24 11:15:20 +02:00
|
|
|
/**
|
2019-01-23 08:32:05 +01:00
|
|
|
* Add the {@link RunnableScheduledFuture} for execution.
|
2018-04-24 11:15:20 +02:00
|
|
|
*/
|
2019-01-23 08:32:05 +01:00
|
|
|
protected final <V> ScheduledFuture<V> schedule(final RunnableScheduledFuture<V> task) {
|
2015-01-30 14:04:06 +01:00
|
|
|
if (inEventLoop()) {
|
2019-01-23 08:32:05 +01:00
|
|
|
add0(task);
|
2015-01-30 14:04:06 +01:00
|
|
|
} else {
|
2016-03-27 14:25:39 +02:00
|
|
|
execute(new Runnable() {
|
2015-01-30 14:04:06 +01:00
|
|
|
@Override
|
|
|
|
public void run() {
|
2019-01-23 08:32:05 +01:00
|
|
|
add0(task);
|
2015-01-30 14:04:06 +01:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
return task;
|
|
|
|
}
|
|
|
|
|
2019-01-23 08:32:05 +01:00
|
|
|
private <V> void add0(RunnableScheduledFuture<V> task) {
|
|
|
|
final RunnableScheduledFutureNode node;
|
|
|
|
if (task instanceof RunnableScheduledFutureNode) {
|
|
|
|
node = (RunnableScheduledFutureNode) task;
|
|
|
|
} else {
|
|
|
|
node = new DefaultRunnableScheduledFutureNode<V>(task);
|
|
|
|
}
|
|
|
|
scheduledTaskQueue().add(node);
|
|
|
|
}
|
|
|
|
|
|
|
|
final void removeScheduled(final RunnableScheduledFutureNode<?> task) {
|
2015-07-18 20:50:34 +02:00
|
|
|
if (inEventLoop()) {
|
2017-11-11 08:09:32 +01:00
|
|
|
scheduledTaskQueue().removeTyped(task);
|
2015-07-18 20:50:34 +02:00
|
|
|
} else {
|
2016-03-27 14:25:39 +02:00
|
|
|
execute(new Runnable() {
|
2015-07-18 20:50:34 +02:00
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
removeScheduled(task);
|
|
|
|
}
|
|
|
|
});
|
2015-01-30 14:04:06 +01:00
|
|
|
}
|
|
|
|
}
|
2019-01-23 08:32:05 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns a new {@link RunnableFuture} build on top of the given {@link Promise} and {@link Callable}.
|
|
|
|
*
|
|
|
|
* This can be used if you want to override {@link #newTaskFor(Callable)} and return a different
|
|
|
|
* {@link RunnableFuture}.
|
|
|
|
*/
|
|
|
|
protected static <V> RunnableScheduledFuture<V> newRunnableScheduledFuture(
|
|
|
|
AbstractScheduledEventExecutor executor, Promise<V> promise, Callable<V> task,
|
|
|
|
long deadlineNanos, long periodNanos) {
|
|
|
|
return new RunnableScheduledFutureAdapter<V>(executor, promise, task, deadlineNanos, periodNanos);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns a {@code RunnableScheduledFuture} for the given values.
|
|
|
|
*/
|
|
|
|
protected <V> RunnableScheduledFuture<V> newScheduledTaskFor(
|
|
|
|
Callable<V> callable, long deadlineNanos, long period) {
|
|
|
|
return newRunnableScheduledFuture(this, this.newPromise(), callable, deadlineNanos, period);
|
|
|
|
}
|
|
|
|
|
|
|
|
interface RunnableScheduledFutureNode<V> extends PriorityQueueNode, RunnableScheduledFuture<V> { }
|
|
|
|
|
|
|
|
private static final class DefaultRunnableScheduledFutureNode<V> implements RunnableScheduledFutureNode<V> {
|
|
|
|
private final RunnableScheduledFuture<V> future;
|
|
|
|
private int queueIndex = INDEX_NOT_IN_QUEUE;
|
|
|
|
|
|
|
|
DefaultRunnableScheduledFutureNode(RunnableScheduledFuture<V> future) {
|
|
|
|
this.future = future;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public long deadlineNanos() {
|
|
|
|
return future.deadlineNanos();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public long delayNanos() {
|
|
|
|
return future.delayNanos();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public long delayNanos(long currentTimeNanos) {
|
|
|
|
return future.delayNanos(currentTimeNanos);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public RunnableScheduledFuture<V> addListener(
|
|
|
|
GenericFutureListener<? extends Future<? super V>> listener) {
|
|
|
|
future.addListener(listener);
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public RunnableScheduledFuture<V> addListeners(
|
|
|
|
GenericFutureListener<? extends Future<? super V>>... listeners) {
|
|
|
|
future.addListeners(listeners);
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public RunnableScheduledFuture<V> removeListener(
|
|
|
|
GenericFutureListener<? extends Future<? super V>> listener) {
|
|
|
|
future.removeListener(listener);
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public RunnableScheduledFuture<V> removeListeners(
|
|
|
|
GenericFutureListener<? extends Future<? super V>>... listeners) {
|
|
|
|
future.removeListeners(listeners);
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean isPeriodic() {
|
|
|
|
return future.isPeriodic();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public int priorityQueueIndex(DefaultPriorityQueue<?> queue) {
|
|
|
|
return queueIndex;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void priorityQueueIndex(DefaultPriorityQueue<?> queue, int i) {
|
|
|
|
queueIndex = i;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
future.run();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean cancel(boolean mayInterruptIfRunning) {
|
|
|
|
return future.cancel(mayInterruptIfRunning);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean isCancelled() {
|
|
|
|
return future.isCancelled();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean isDone() {
|
|
|
|
return future.isDone();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public V get() throws InterruptedException, ExecutionException {
|
|
|
|
return future.get();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
|
|
|
|
return future.get(timeout, unit);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public long getDelay(TimeUnit unit) {
|
|
|
|
return future.getDelay(unit);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public int compareTo(Delayed o) {
|
|
|
|
return future.compareTo(o);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public RunnableFuture<V> sync() throws InterruptedException {
|
|
|
|
future.sync();
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public RunnableFuture<V> syncUninterruptibly() {
|
|
|
|
future.syncUninterruptibly();
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public RunnableFuture<V> await() throws InterruptedException {
|
|
|
|
future.await();
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public RunnableFuture<V> awaitUninterruptibly() {
|
|
|
|
future.awaitUninterruptibly();
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean isSuccess() {
|
|
|
|
return future.isSuccess();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean isCancellable() {
|
|
|
|
return future.isCancellable();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public Throwable cause() {
|
|
|
|
return future.cause();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean await(long timeout, TimeUnit unit) throws InterruptedException {
|
|
|
|
return future.await(timeout, unit);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean await(long timeoutMillis) throws InterruptedException {
|
|
|
|
return future.await(timeoutMillis);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean awaitUninterruptibly(long timeout, TimeUnit unit) {
|
|
|
|
return future.awaitUninterruptibly(timeout, unit);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean awaitUninterruptibly(long timeoutMillis) {
|
|
|
|
return future.awaitUninterruptibly(timeoutMillis);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public V getNow() {
|
|
|
|
return future.getNow();
|
|
|
|
}
|
|
|
|
}
|
2015-01-30 14:04:06 +01:00
|
|
|
}
|