1 /*
2  * Hunt - A refined core library for D programming language.
3  *
4  * Copyright (C) 2018-2019 HuntLabs
5  *
6  * Website: https://www.huntlabs.net/
7  *
8  * Licensed under the Apache-2.0 License.
9  *
10  */
11 
12 module hunt.concurrency.ExecutorService;
13 
14 import hunt.collection.Collection;
15 import hunt.collection.List;
16 import hunt.Functions;
17 import hunt.util.Runnable;
18 import hunt.util.Common;
19 
20 import std.datetime;
21 
22 /**
23  * An {@link Executor} that provides methods to manage termination and
24  * methods that can produce a {@link Future} for tracking progress of
25  * one or more asynchronous tasks.
26  *
27  * <p>An {@code ExecutorService} can be shut down, which will cause
28  * it to reject new tasks.  Two different methods are provided for
29  * shutting down an {@code ExecutorService}. The {@link #shutdown}
30  * method will allow previously submitted tasks to execute before
31  * terminating, while the {@link #shutdownNow} method prevents waiting
32  * tasks from starting and attempts to stop currently executing tasks.
33  * Upon termination, an executor has no tasks actively executing, no
34  * tasks awaiting execution, and no new tasks can be submitted.  An
35  * unused {@code ExecutorService} should be shut down to allow
36  * reclamation of its resources.
37  *
38  * <p>Method {@code submit} extends base method {@link
39  * Executor#execute(Runnable)} by creating and returning a {@link Future}
40  * that can be used to cancel execution and/or wait for completion.
41  * Methods {@code invokeAny} and {@code invokeAll} perform the most
42  * commonly useful forms of bulk execution, executing a collection of
43  * tasks and then waiting for at least one, or all, to
44  * complete. (Class {@link ExecutorCompletionService} can be used to
45  * write customized variants of these methods.)
46  *
47  * <p>The {@link Executors} class provides factory methods for the
48  * executor services provided in this package.
49  *
50  * <h3>Usage Examples</h3>
51  *
52  * Here is a sketch of a network service in which threads in a thread
53  * pool service incoming requests. It uses the preconfigured {@link
54  * Executors#newFixedThreadPool} factory method:
55  *
56  * <pre> {@code
57  * class NetworkService implements Runnable {
58  *   private final ServerSocket serverSocket;
59  *   private final ExecutorService pool;
60  *
61  *   public NetworkService(int port, int poolSize)
62  *       throws IOException {
63  *     serverSocket = new ServerSocket(port);
64  *     pool = Executors.newFixedThreadPool(poolSize);
65  *   }
66  *
67  *   public void run() { // run the service
68  *     try {
69  *       for (;;) {
70  *         pool.execute(new Handler(serverSocket.accept()));
71  *       }
72  *     } catch (IOException ex) {
73  *       pool.shutdown();
74  *     }
75  *   }
76  * }
77  *
78  * class Handler implements Runnable {
79  *   private final Socket socket;
80  *   Handler(Socket socket) { this.socket = socket; }
81  *   public void run() {
82  *     // read and service request on socket
83  *   }
84  * }}</pre>
85  *
86  * The following method shuts down an {@code ExecutorService} in two phases,
87  * first by calling {@code shutdown} to reject incoming tasks, and then
88  * calling {@code shutdownNow}, if necessary, to cancel any lingering tasks:
89  *
90  * <pre> {@code
91  * void shutdownAndAwaitTermination(ExecutorService pool) {
92  *   pool.shutdown(); // Disable new tasks from being submitted
93  *   try {
94  *     // Wait a while for existing tasks to terminate
95  *     if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
96  *       pool.shutdownNow(); // Cancel currently executing tasks
97  *       // Wait a while for tasks to respond to being cancelled
98  *       if (!pool.awaitTermination(60, TimeUnit.SECONDS))
99  *           System.err.println("Pool did not terminate");
100  *     }
101  *   } catch (InterruptedException ie) {
102  *     // (Re-)Cancel if current thread also interrupted
103  *     pool.shutdownNow();
104  *     // Preserve interrupt status
105  *     Thread.currentThread().interrupt();
106  *   }
107  * }}</pre>
108  *
109  * <p>Memory consistency effects: Actions in a thread prior to the
110  * submission of a {@code Runnable} or {@code Callable} task to an
111  * {@code ExecutorService}
112  * <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
113  * any actions taken by that task, which in turn <i>happen-before</i> the
114  * result is retrieved via {@code Future.get()}.
115  *
116  * @author Doug Lea
117  */
118 interface ExecutorService : Executor {
119 
120     /**
121      * Initiates an orderly shutdown in which previously submitted
122      * tasks are executed, but no new tasks will be accepted.
123      * Invocation has no additional effect if already shut down.
124      *
125      * <p>This method does not wait for previously submitted tasks to
126      * complete execution.  Use {@link #awaitTermination awaitTermination}
127      * to do that.
128      *
129      * @throws SecurityException if a security manager exists and
130      *         shutting down this ExecutorService may manipulate
131      *         threads that the caller is not permitted to modify
132      *         because it does not hold {@link
133      *         java.lang.RuntimePermission}{@code ("modifyThread")},
134      *         or the security manager's {@code checkAccess} method
135      *         denies access.
136      */
137     void shutdown();
138 
139     /**
140      * Attempts to stop all actively executing tasks, halts the
141      * processing of waiting tasks, and returns a list of the tasks
142      * that were awaiting execution.
143      *
144      * <p>This method does not wait for actively executing tasks to
145      * terminate.  Use {@link #awaitTermination awaitTermination} to
146      * do that.
147      *
148      * <p>There are no guarantees beyond best-effort attempts to stop
149      * processing actively executing tasks.  For example, typical
150      * implementations will cancel via {@link Thread#interrupt}, so any
151      * task that fails to respond to interrupts may never terminate.
152      *
153      * @return list of tasks that never commenced execution
154      * @throws SecurityException if a security manager exists and
155      *         shutting down this ExecutorService may manipulate
156      *         threads that the caller is not permitted to modify
157      *         because it does not hold {@link
158      *         java.lang.RuntimePermission}{@code ("modifyThread")},
159      *         or the security manager's {@code checkAccess} method
160      *         denies access.
161      */
162     List!(Runnable) shutdownNow();
163 
164     /**
165      * Returns {@code true} if this executor has been shut down.
166      *
167      * @return {@code true} if this executor has been shut down
168      */
169     bool isShutdown();
170 
171     /**
172      * Returns {@code true} if all tasks have completed following shut down.
173      * Note that {@code isTerminated} is never {@code true} unless
174      * either {@code shutdown} or {@code shutdownNow} was called first.
175      *
176      * @return {@code true} if all tasks have completed following shut down
177      */
178     bool isTerminated();
179 
180     /**
181      * Blocks until all tasks have completed execution after a shutdown
182      * request, or the timeout occurs, or the current thread is
183      * interrupted, whichever happens first.
184      *
185      * @param timeout the maximum time to wait
186      * @param unit the time unit of the timeout argument
187      * @return {@code true} if this executor terminated and
188      *         {@code false} if the timeout elapsed before termination
189      * @throws InterruptedException if interrupted while waiting
190      */
191     bool awaitTermination(Duration timeout);
192 
193     /**
194      * Submits a value-returning task for execution and returns a
195      * Future representing the pending results of the task. The
196      * Future's {@code get} method will return the task's result upon
197      * successful completion.
198      *
199      * <p>
200      * If you would like to immediately block waiting
201      * for a task, you can use constructions of the form
202      * {@code result = exec.submit(aCallable).get();}
203      *
204      * <p>Note: The {@link Executors} class includes a set of methods
205      * that can convert some other common closure-like objects,
206      * for example, {@link java.security.PrivilegedAction} to
207      * {@link Callable} form so they can be submitted.
208      *
209      * @param task the task to submit
210      * @param (T) the type of the task's result
211      * @return a Future representing pending completion of the task
212      * @throws RejectedExecutionException if the task cannot be
213      *         scheduled for execution
214      * @throws NullPointerException if the task is null
215      */
216     // Future!(T) submit(Callable!(T) task);
217 
218     /**
219      * Submits a Runnable task for execution and returns a Future
220      * representing that task. The Future's {@code get} method will
221      * return the given result upon successful completion.
222      *
223      * @param task the task to submit
224      * @param result the result to return
225      * @param (T) the type of the result
226      * @return a Future representing pending completion of the task
227      * @throws RejectedExecutionException if the task cannot be
228      *         scheduled for execution
229      * @throws NullPointerException if the task is null
230      */
231     // Future!(T) submit(Runnable task, T result);
232 
233     /**
234      * Submits a Runnable task for execution and returns a Future
235      * representing that task. The Future's {@code get} method will
236      * return {@code null} upon <em>successful</em> completion.
237      *
238      * @param task the task to submit
239      * @return a Future representing pending completion of the task
240      * @throws RejectedExecutionException if the task cannot be
241      *         scheduled for execution
242      * @throws NullPointerException if the task is null
243      */
244     // Future!(T) submit(Runnable task);
245 
246     /**
247      * Executes the given tasks, returning a list of Futures holding
248      * their status and results when all complete.
249      * {@link Future#isDone} is {@code true} for each
250      * element of the returned list.
251      * Note that a <em>completed</em> task could have
252      * terminated either normally or by throwing an exception.
253      * The results of this method are undefined if the given
254      * collection is modified while this operation is in progress.
255      *
256      * @param tasks the collection of tasks
257      * @param (T) the type of the values returned from the tasks
258      * @return a list of Futures representing the tasks, in the same
259      *         sequential order as produced by the iterator for the
260      *         given task list, each of which has completed
261      * @throws InterruptedException if interrupted while waiting, in
262      *         which case unfinished tasks are cancelled
263      * @throws NullPointerException if tasks or any of its elements are {@code null}
264      * @throws RejectedExecutionException if any task cannot be
265      *         scheduled for execution
266      */
267     // List!(Future!(T)) invokeAll(Collection!(Callable!(T)) tasks);
268 
269     /**
270      * Executes the given tasks, returning a list of Futures holding
271      * their status and results
272      * when all complete or the timeout expires, whichever happens first.
273      * {@link Future#isDone} is {@code true} for each
274      * element of the returned list.
275      * Upon return, tasks that have not completed are cancelled.
276      * Note that a <em>completed</em> task could have
277      * terminated either normally or by throwing an exception.
278      * The results of this method are undefined if the given
279      * collection is modified while this operation is in progress.
280      *
281      * @param tasks the collection of tasks
282      * @param timeout the maximum time to wait
283      * @param unit the time unit of the timeout argument
284      * @param (T) the type of the values returned from the tasks
285      * @return a list of Futures representing the tasks, in the same
286      *         sequential order as produced by the iterator for the
287      *         given task list. If the operation did not time out,
288      *         each task will have completed. If it did time out, some
289      *         of these tasks will not have completed.
290      * @throws InterruptedException if interrupted while waiting, in
291      *         which case unfinished tasks are cancelled
292      * @throws NullPointerException if tasks, any of its elements, or
293      *         unit are {@code null}
294      * @throws RejectedExecutionException if any task cannot be scheduled
295      *         for execution
296      */
297     // List!(Future!(T)) invokeAll(Collection!(Callable!(T)) tasks,
298     //                               Duration timeout);
299 
300     /**
301      * Executes the given tasks, returning the result
302      * of one that has completed successfully (i.e., without throwing
303      * an exception), if any do. Upon normal or exceptional return,
304      * tasks that have not completed are cancelled.
305      * The results of this method are undefined if the given
306      * collection is modified while this operation is in progress.
307      *
308      * @param tasks the collection of tasks
309      * @param (T) the type of the values returned from the tasks
310      * @return the result returned by one of the tasks
311      * @throws InterruptedException if interrupted while waiting
312      * @throws NullPointerException if tasks or any element task
313      *         subject to execution is {@code null}
314      * @throws IllegalArgumentException if tasks is empty
315      * @throws ExecutionException if no task successfully completes
316      * @throws RejectedExecutionException if tasks cannot be scheduled
317      *         for execution
318      */
319     // T invokeAny(Collection!(Callable!(T)) tasks);
320 
321     /**
322      * Executes the given tasks, returning the result
323      * of one that has completed successfully (i.e., without throwing
324      * an exception), if any do before the given timeout elapses.
325      * Upon normal or exceptional return, tasks that have not
326      * completed are cancelled.
327      * The results of this method are undefined if the given
328      * collection is modified while this operation is in progress.
329      *
330      * @param tasks the collection of tasks
331      * @param timeout the maximum time to wait
332      * @param unit the time unit of the timeout argument
333      * @param (T) the type of the values returned from the tasks
334      * @return the result returned by one of the tasks
335      * @throws InterruptedException if interrupted while waiting
336      * @throws NullPointerException if tasks, or unit, or any element
337      *         task subject to execution is {@code null}
338      * @throws TimeoutException if the given timeout elapses before
339      *         any task successfully completes
340      * @throws ExecutionException if no task successfully completes
341      * @throws RejectedExecutionException if tasks cannot be scheduled
342      *         for execution
343      */
344     // T invokeAny(Collection!(Callable!(T)) tasks,
345     //                 Duration timeout);
346 }