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