1 /* 2 * Copyright 2013 The Netty Project 3 * 4 * The Netty Project licenses this file to you under the Apache License, 5 * version 2.0 (the "License"); you may not use this file except in compliance 6 * with the License. You may obtain a copy of the License at: 7 * 8 * https://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, WITHOUT 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 * License for the specific language governing permissions and limitations 14 * under the License. 15 */ 16 package io.netty5.util.concurrent; 17 18 import io.netty5.util.internal.logging.InternalLogger; 19 import io.netty5.util.internal.logging.InternalLoggerFactory; 20 21 import java.util.concurrent.Callable; 22 import java.util.concurrent.Executors; 23 24 import static java.util.Objects.requireNonNull; 25 26 /** 27 * Abstract base class for {@link EventExecutor} implementations. 28 */ 29 public abstract class AbstractEventExecutor implements EventExecutor { 30 private static final InternalLogger logger = InternalLoggerFactory.getInstance(AbstractEventExecutor.class); 31 static final long DEFAULT_SHUTDOWN_QUIET_PERIOD = 2; 32 static final long DEFAULT_SHUTDOWN_TIMEOUT = 15; 33 34 private final Future<?> successfulVoidFuture = DefaultPromise.newSuccessfulPromise(this, null).asFuture(); 35 36 @Override 37 public <V> Future<V> newSucceededFuture(V result) { 38 if (result == null) { 39 @SuppressWarnings("unchecked") 40 Future<V> f = (Future<V>) successfulVoidFuture; 41 return f; 42 } 43 return EventExecutor.super.newSucceededFuture(result); 44 } 45 46 @Override 47 public final Future<Void> submit(Runnable task) { 48 var futureTask = newTaskFor(task, (Void) null); 49 execute(futureTask); 50 return futureTask; 51 } 52 53 @Override 54 public final <T> Future<T> submit(Runnable task, T result) { 55 var futureTask = newTaskFor(task, result); 56 execute(futureTask); 57 return futureTask; 58 } 59 60 @Override 61 public final <T> Future<T> submit(Callable<T> task) { 62 var futureTask = newTaskFor(task); 63 execute(futureTask); 64 return futureTask; 65 } 66 67 /** 68 * Decorate the given {@link Runnable} and its return value, as a {@link RunnableFuture}, such that the 69 * returned {@link RunnableFuture} completes with the given result at the end of executing its 70 * {@link RunnableFuture#run()} method. 71 * <p> 72 * The returned {@link RunnableFuture} is the task that will actually be run by a thread in this 73 * executor. 74 * <p> 75 * This method can be overridden by sub-classes to hook into the life cycle of the given task. 76 * 77 * @param runnable The task to be decorated. 78 * @param value The value that the returned future will complete with, assuming the given {@link Runnable} doesn't 79 * throw an exception. 80 * @param <T> The type of the result value. 81 * @return The decorated {@link Runnable} that is now also a {@link Future}. 82 */ 83 protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) { 84 return newRunnableFuture(newPromise(), runnable, value); 85 } 86 87 /** 88 * Decorate the given {@link Callable} and its return value, as a {@link RunnableFuture}, such that the 89 * returned {@link RunnableFuture} completes with the returned result from the {@link Callable} at the end of 90 * executing its {@link RunnableFuture#run()} method. 91 * <p> 92 * The returned {@link RunnableFuture} is the task that will actually be run by a thread in this 93 * executor. 94 * <p> 95 * This method can be overridden by sub-classes to hook into the life cycle of the given task. 96 * 97 * @param callable The task to be decorated. 98 * @param <T> The type of the result value. 99 * @return The decorated {@link Runnable} that is now also a {@link Future}. 100 */ 101 protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) { 102 return newRunnableFuture(newPromise(), callable); 103 } 104 105 /** 106 * Try to execute the given {@link Runnable} and just log if it throws a {@link Throwable}. 107 */ 108 static void safeExecute(Runnable task) { 109 try { 110 task.run(); 111 } catch (Throwable t) { 112 logger.warn("A task raised an exception. Task: {}", task, t); 113 } 114 } 115 116 /** 117 * Returns a new {@link RunnableFuture} build on top of the given {@link Promise} and {@link Callable}. 118 * 119 * This can be used if you want to override {@link #newTaskFor(Callable)} and return a different 120 * {@link RunnableFuture}. 121 */ 122 private static <V> RunnableFuture<V> newRunnableFuture(Promise<V> promise, Callable<V> task) { 123 return new RunnableFutureAdapter<>(promise, requireNonNull(task, "task")); 124 } 125 126 /** 127 * Returns a new {@link RunnableFuture} build on top of the given {@link Promise} and {@link Runnable} and 128 * {@code value}. 129 */ 130 private static <V> RunnableFuture<V> newRunnableFuture(Promise<V> promise, Runnable task, V value) { 131 return new RunnableFutureAdapter<>(promise, Executors.callable(requireNonNull(task, "task"), value)); 132 } 133 }