View Javadoc
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 }