1 /* 2 * Copyright 2012 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 java.util.Iterator; 19 import java.util.concurrent.Callable; 20 import java.util.concurrent.Executor; 21 import java.util.concurrent.TimeUnit; 22 23 import static io.netty5.util.concurrent.AbstractEventExecutor.DEFAULT_SHUTDOWN_QUIET_PERIOD; 24 import static io.netty5.util.concurrent.AbstractEventExecutor.DEFAULT_SHUTDOWN_TIMEOUT; 25 26 /** 27 * The {@link EventExecutorGroup} is responsible for providing the {@link EventExecutor}'s to use 28 * via its {@link #next()} method. Besides this, it is also responsible for handling their 29 * life-cycle and allows shutting them down in a global fashion. 30 * 31 */ 32 public interface EventExecutorGroup extends Iterable<EventExecutor>, Executor { 33 /** 34 * Returns {@code true} if and only if all {@link EventExecutor}s managed by this {@link EventExecutorGroup} 35 * are being {@linkplain #shutdownGracefully() shut down gracefully} or was {@linkplain #isShutdown() shut down}. 36 * <p> 37 * An executor group that "is shutting down" can still accept new tasks for a little while (the grace period), 38 * but will eventually start rejecting new tasks. 39 * At that point, the executor group will be {@linkplain #isShutdown() shut down}. 40 * 41 * @return {@code true} if all executors in this group have at least started shutting down, otherwise {@code false}. 42 */ 43 boolean isShuttingDown(); 44 45 /** 46 * Returns {@code true} if all {@link EventExecutor}s managed by this {@link EventExecutorGroup} have been 47 * {@linkplain #shutdownGracefully() shut down gracefully} and moved past the grace period so that they are no 48 * longer accepting any new tasks. 49 * <p> 50 * An executor group that "is shut down" might still be executing tasks that it has queued up, but it will no 51 * longer be accepting any new tasks. 52 * Once all running and queued tasks have completed, the executor group will be 53 * {@linkplain #isTerminated() terminated}. 54 * 55 * @return {@code true} if all executors in this group have shut down and are no longer accepting any new tasks. 56 */ 57 boolean isShutdown(); 58 59 /** 60 * Returns {@code true} if all {@link EventExecutor}s managed by this {@link EventExecutorGroup} are 61 * {@linkplain #isShutdown() shut down}, and all of their tasks have completed. 62 * 63 * @return {@code true} if all executors in this group have terminated. 64 */ 65 default boolean isTerminated() { 66 return terminationFuture().isDone(); 67 } 68 69 /** 70 * Wait for this {@link EventExecutorGroup} to {@linkplain #isTerminated() terminate}, up to the given timeout. 71 * 72 * @param timeout The non-negative maximum amount of time to wait for the executor group to terminate. 73 * @param unit The non-null time unit of the timeout. 74 * @return {@code true} if the executor group terminated within the specific timeout. 75 * @throws InterruptedException If this thread was {@linkplain Thread#interrupt() interrupted} while waiting for 76 * executor group to terminate. 77 */ 78 default boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException { 79 return terminationFuture().asStage().await(timeout, unit); 80 } 81 82 /** 83 * Shortcut method for {@link #shutdownGracefully(long, long, TimeUnit)} with sensible default values. 84 * 85 * @return the {@link #terminationFuture()} 86 */ 87 default Future<Void> shutdownGracefully() { 88 return shutdownGracefully(DEFAULT_SHUTDOWN_QUIET_PERIOD, DEFAULT_SHUTDOWN_TIMEOUT, TimeUnit.SECONDS); 89 } 90 91 /** 92 * Signals this executor that the caller wants the executor to be shut down. Once this method is called, 93 * {@link #isShuttingDown()} starts to return {@code true}, and the executor prepares to shut itself down. 94 * This method ensures that no tasks are submitted for <i>'the quiet period'</i> (usually a couple seconds) before 95 * it shuts itself down. If a task is submitted during the quiet period, it is guaranteed to be accepted and the 96 * quiet period will start over. 97 * 98 * @param quietPeriod the quiet period as described in the documentation 99 * @param timeout the maximum amount of time to wait until the executor is 100 * {@linkplain #isShuttingDown() shutting down} regardless if a task was submitted during the quiet period. 101 * @param unit the unit of {@code quietPeriod} and {@code timeout} 102 * 103 * @return the {@link #terminationFuture()} 104 */ 105 Future<Void> shutdownGracefully(long quietPeriod, long timeout, TimeUnit unit); 106 107 /** 108 * Returns the {@link Future} which is notified when all {@link EventExecutor}s managed by this 109 * {@link EventExecutorGroup} have been terminated. 110 * 111 * @return The {@link Future} representing the termination of this {@link EventExecutorGroup}. 112 */ 113 Future<Void> terminationFuture(); 114 115 /** 116 * Returns one of the {@link EventExecutor}s managed by this {@link EventExecutorGroup}. 117 */ 118 EventExecutor next(); 119 120 @Override 121 Iterator<EventExecutor> iterator(); 122 123 /** 124 * Submit the given task for execution in the next available {@link EventExecutor} in this group, 125 * and return a future that produces a {@code null} result when the task completes. 126 * 127 * @param task The task that should be executed in this {@link EventExecutorGroup}. 128 * @return A future that represents the completion of the submitted task. 129 */ 130 default Future<Void> submit(Runnable task) { 131 return next().submit(task); 132 } 133 134 /** 135 * Submit the given task for execution in the next available {@link EventExecutor} in this group, 136 * and return a future that produces the given result when the task completes. 137 * 138 * @param task The task that should be executed in this {@link EventExecutorGroup}. 139 * @param result The value that the returned future will complete with, if the task completes successfully. 140 * @param <T> The type of the future result. 141 * @return A future that represents the completion of the submitted task. 142 */ 143 default <T> Future<T> submit(Runnable task, T result) { 144 return next().submit(task, result); 145 } 146 147 /** 148 * Submit the given task for execution in the next available {@link EventExecutor} in this group, 149 * and return a future that will return the result of the callable when the task completes. 150 * 151 * @param task The task that should be executed in this {@link EventExecutorGroup}. 152 * @param <T> The type of the future result. 153 * @return A future that represents the completion of the submitted task. 154 */ 155 default <T> Future<T> submit(Callable<T> task) { 156 return next().submit(task); 157 } 158 159 /** 160 * Schedule the given task for execution after the given delay, in the next available {@link EventExecutor} 161 * in this group, and return a future that produces a {@code null} result when the task completes. 162 * 163 * @param task The task that should be executed in this {@link EventExecutorGroup} after the given delay. 164 * @param delay A positive time delay, in the given time unit. 165 * @param unit The non-null time unit for the delay. 166 * @return A future that represents the completion of the scheduled task. 167 */ 168 default Future<Void> schedule(Runnable task, long delay, TimeUnit unit) { 169 return next().schedule(task, delay, unit); 170 } 171 172 /** 173 * Schedule the given task for execution after the given delay, in the next available {@link EventExecutor} 174 * in this group, and return a future that will return the result of the callable when the task completes. 175 * 176 * @param task The task that should be executed in this {@link EventExecutorGroup} after the given delay. 177 * @param delay A positive time delay, in the given time unit. 178 * @param unit The non-null time unit for the delay. 179 * @param <V> The type of the future result. 180 * @return A future that represents the completion of the scheduled task. 181 */ 182 default <V> Future<V> schedule(Callable<V> task, long delay, TimeUnit unit) { 183 return next().schedule(task, delay, unit); 184 } 185 186 /** 187 * Schedule the given task for periodic execution in the next available {@link EventExecutor}. 188 * The first execution will occur after the given initial delay, and the following repeated executions will occur 189 * with the given period of time between each execution is started. 190 * If the task takes longer to complete than the requested period, then the following executions will be delayed, 191 * rather than allowing multiple instances of the task to run concurrently. 192 * <p> 193 * The task will be executed repeatedly until it either fails with an exception, or its future is 194 * {@linkplain Future#cancel() cancelled}. The future thus will never complete successfully. 195 * 196 * @param task The task that should be scheduled to execute at a fixed rate in this {@link EventExecutorGroup}. 197 * @param initialDelay The positive initial delay for the first task execution, in terms of the given time unit. 198 * @param period The positive period for the execution frequency to use after the first execution has started, 199 * in terms of the given time unit. 200 * @param unit The non-null time unit for the delay and period. 201 * @return A future that represents the recurring task, and which can be cancelled to stop future executions. 202 */ 203 default Future<Void> scheduleAtFixedRate(Runnable task, long initialDelay, long period, TimeUnit unit) { 204 return next().scheduleAtFixedRate(task, initialDelay, period, unit); 205 } 206 207 /** 208 * Schedule the given task for periodic execution in the next available {@link EventExecutor}. 209 * The first execution will occur after the given initial delay, and the following repeated executions will occur 210 * with the given subsequent delay between one task completing and the next task starting. 211 * The delay from the completion of one task, to the start of the next, stays unchanged regardless of how long a 212 * task takes to complete. 213 * <p> 214 * This is in contrast to {@link #scheduleAtFixedRate(Runnable, long, long, TimeUnit)} which varies the delays 215 * between the tasks in order to hit a given frequency. 216 * <p> 217 * The task will be executed repeatedly until it either fails with an exception, or its future is 218 * {@linkplain Future#cancel() cancelled}. The future thus will never complete successfully. 219 * 220 * @param task The task that should be scheduled to execute with fixed delays in this {@link EventExecutorGroup}. 221 * @param initialDelay The positive initial delay for the first task execution, in terms of the given time unit. 222 * @param delay The positive subsequent delay between task, to use after the first execution has completed, 223 * in terms of the given time unit. 224 * @param unit The non-null time unit for the delays. 225 * @return A future that represents the recurring task, and which can be cancelled to stop future executions. 226 */ 227 default Future<Void> scheduleWithFixedDelay(Runnable task, long initialDelay, long delay, TimeUnit unit) { 228 return next().scheduleWithFixedDelay(task, initialDelay, delay, unit); 229 } 230 231 @Override 232 default void execute(Runnable task) { 233 next().execute(task); 234 } 235 }