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.concurrency.Executor; 15 import hunt.collection.Collection; 16 import hunt.collection.List; 17 import hunt.Functions; 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 * @since 1.5 117 * @author Doug Lea 118 */ 119 interface ExecutorService : Executor { 120 121 /** 122 * Initiates an orderly shutdown in which previously submitted 123 * tasks are executed, but no new tasks will be accepted. 124 * Invocation has no additional effect if already shut down. 125 * 126 * <p>This method does not wait for previously submitted tasks to 127 * complete execution. Use {@link #awaitTermination awaitTermination} 128 * to do that. 129 * 130 * @throws SecurityException if a security manager exists and 131 * shutting down this ExecutorService may manipulate 132 * threads that the caller is not permitted to modify 133 * because it does not hold {@link 134 * java.lang.RuntimePermission}{@code ("modifyThread")}, 135 * or the security manager's {@code checkAccess} method 136 * denies access. 137 */ 138 void shutdown(); 139 140 /** 141 * Attempts to stop all actively executing tasks, halts the 142 * processing of waiting tasks, and returns a list of the tasks 143 * that were awaiting execution. 144 * 145 * <p>This method does not wait for actively executing tasks to 146 * terminate. Use {@link #awaitTermination awaitTermination} to 147 * do that. 148 * 149 * <p>There are no guarantees beyond best-effort attempts to stop 150 * processing actively executing tasks. For example, typical 151 * implementations will cancel via {@link Thread#interrupt}, so any 152 * task that fails to respond to interrupts may never terminate. 153 * 154 * @return list of tasks that never commenced execution 155 * @throws SecurityException if a security manager exists and 156 * shutting down this ExecutorService may manipulate 157 * threads that the caller is not permitted to modify 158 * because it does not hold {@link 159 * java.lang.RuntimePermission}{@code ("modifyThread")}, 160 * or the security manager's {@code checkAccess} method 161 * denies access. 162 */ 163 List!(Runnable) shutdownNow(); 164 165 /** 166 * Returns {@code true} if this executor has been shut down. 167 * 168 * @return {@code true} if this executor has been shut down 169 */ 170 bool isShutdown(); 171 172 /** 173 * Returns {@code true} if all tasks have completed following shut down. 174 * Note that {@code isTerminated} is never {@code true} unless 175 * either {@code shutdown} or {@code shutdownNow} was called first. 176 * 177 * @return {@code true} if all tasks have completed following shut down 178 */ 179 bool isTerminated(); 180 181 /** 182 * Blocks until all tasks have completed execution after a shutdown 183 * request, or the timeout occurs, or the current thread is 184 * interrupted, whichever happens first. 185 * 186 * @param timeout the maximum time to wait 187 * @param unit the time unit of the timeout argument 188 * @return {@code true} if this executor terminated and 189 * {@code false} if the timeout elapsed before termination 190 * @throws InterruptedException if interrupted while waiting 191 */ 192 bool awaitTermination(Duration timeout); 193 194 /** 195 * Submits a value-returning task for execution and returns a 196 * Future representing the pending results of the task. The 197 * Future's {@code get} method will return the task's result upon 198 * successful completion. 199 * 200 * <p> 201 * If you would like to immediately block waiting 202 * for a task, you can use constructions of the form 203 * {@code result = exec.submit(aCallable).get();} 204 * 205 * <p>Note: The {@link Executors} class includes a set of methods 206 * that can convert some other common closure-like objects, 207 * for example, {@link java.security.PrivilegedAction} to 208 * {@link Callable} form so they can be submitted. 209 * 210 * @param task the task to submit 211 * @param (T) the type of the task's result 212 * @return a Future representing pending completion of the task 213 * @throws RejectedExecutionException if the task cannot be 214 * scheduled for execution 215 * @throws NullPointerException if the task is null 216 */ 217 // Future!(T) submit(Callable!(T) task); 218 219 /** 220 * Submits a Runnable task for execution and returns a Future 221 * representing that task. The Future's {@code get} method will 222 * return the given result upon successful completion. 223 * 224 * @param task the task to submit 225 * @param result the result to return 226 * @param (T) the type of the result 227 * @return a Future representing pending completion of the task 228 * @throws RejectedExecutionException if the task cannot be 229 * scheduled for execution 230 * @throws NullPointerException if the task is null 231 */ 232 // Future!(T) submit(Runnable task, T result); 233 234 /** 235 * Submits a Runnable task for execution and returns a Future 236 * representing that task. The Future's {@code get} method will 237 * return {@code null} upon <em>successful</em> completion. 238 * 239 * @param task the task to submit 240 * @return a Future representing pending completion of the task 241 * @throws RejectedExecutionException if the task cannot be 242 * scheduled for execution 243 * @throws NullPointerException if the task is null 244 */ 245 // Future!(T) submit(Runnable task); 246 247 /** 248 * Executes the given tasks, returning a list of Futures holding 249 * their status and results when all complete. 250 * {@link Future#isDone} is {@code true} for each 251 * element of the returned list. 252 * Note that a <em>completed</em> task could have 253 * terminated either normally or by throwing an exception. 254 * The results of this method are undefined if the given 255 * collection is modified while this operation is in progress. 256 * 257 * @param tasks the collection of tasks 258 * @param (T) the type of the values returned from the tasks 259 * @return a list of Futures representing the tasks, in the same 260 * sequential order as produced by the iterator for the 261 * given task list, each of which has completed 262 * @throws InterruptedException if interrupted while waiting, in 263 * which case unfinished tasks are cancelled 264 * @throws NullPointerException if tasks or any of its elements are {@code null} 265 * @throws RejectedExecutionException if any task cannot be 266 * scheduled for execution 267 */ 268 // List!(Future!(T)) invokeAll(Collection!(Callable!(T)) tasks); 269 270 /** 271 * Executes the given tasks, returning a list of Futures holding 272 * their status and results 273 * when all complete or the timeout expires, whichever happens first. 274 * {@link Future#isDone} is {@code true} for each 275 * element of the returned list. 276 * Upon return, tasks that have not completed are cancelled. 277 * Note that a <em>completed</em> task could have 278 * terminated either normally or by throwing an exception. 279 * The results of this method are undefined if the given 280 * collection is modified while this operation is in progress. 281 * 282 * @param tasks the collection of tasks 283 * @param timeout the maximum time to wait 284 * @param unit the time unit of the timeout argument 285 * @param (T) the type of the values returned from the tasks 286 * @return a list of Futures representing the tasks, in the same 287 * sequential order as produced by the iterator for the 288 * given task list. If the operation did not time out, 289 * each task will have completed. If it did time out, some 290 * of these tasks will not have completed. 291 * @throws InterruptedException if interrupted while waiting, in 292 * which case unfinished tasks are cancelled 293 * @throws NullPointerException if tasks, any of its elements, or 294 * unit are {@code null} 295 * @throws RejectedExecutionException if any task cannot be scheduled 296 * for execution 297 */ 298 // List!(Future!(T)) invokeAll(Collection!(Callable!(T)) tasks, 299 // Duration timeout); 300 301 /** 302 * Executes the given tasks, returning the result 303 * of one that has completed successfully (i.e., without throwing 304 * an exception), if any do. Upon normal or exceptional return, 305 * tasks that have not completed are cancelled. 306 * The results of this method are undefined if the given 307 * collection is modified while this operation is in progress. 308 * 309 * @param tasks the collection of tasks 310 * @param (T) the type of the values returned from the tasks 311 * @return the result returned by one of the tasks 312 * @throws InterruptedException if interrupted while waiting 313 * @throws NullPointerException if tasks or any element task 314 * subject to execution is {@code null} 315 * @throws IllegalArgumentException if tasks is empty 316 * @throws ExecutionException if no task successfully completes 317 * @throws RejectedExecutionException if tasks cannot be scheduled 318 * for execution 319 */ 320 // T invokeAny(Collection!(Callable!(T)) tasks); 321 322 /** 323 * Executes the given tasks, returning the result 324 * of one that has completed successfully (i.e., without throwing 325 * an exception), if any do before the given timeout elapses. 326 * Upon normal or exceptional return, tasks that have not 327 * completed are cancelled. 328 * The results of this method are undefined if the given 329 * collection is modified while this operation is in progress. 330 * 331 * @param tasks the collection of tasks 332 * @param timeout the maximum time to wait 333 * @param unit the time unit of the timeout argument 334 * @param (T) the type of the values returned from the tasks 335 * @return the result returned by one of the tasks 336 * @throws InterruptedException if interrupted while waiting 337 * @throws NullPointerException if tasks, or unit, or any element 338 * task subject to execution is {@code null} 339 * @throws TimeoutException if the given timeout elapses before 340 * any task successfully completes 341 * @throws ExecutionException if no task successfully completes 342 * @throws RejectedExecutionException if tasks cannot be scheduled 343 * for execution 344 */ 345 // T invokeAny(Collection!(Callable!(T)) tasks, 346 // Duration timeout); 347 }