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 }