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 }