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.Executor; 13 14 import hunt.Exceptions; 15 16 /** 17 * An object that executes submitted {@link Runnable} tasks. This 18 * interface provides a way of decoupling task submission from the 19 * mechanics of how each task will be run, including details of thread 20 * use, scheduling, etc. An {@code Executor} is normally used 21 * instead of explicitly creating threads. For example, rather than 22 * invoking {@code new Thread(new RunnableTask()).start()} for each 23 * of a set of tasks, you might use: 24 * 25 * <pre> {@code 26 * Executor executor = anExecutor(); 27 * executor.execute(new RunnableTask1()); 28 * executor.execute(new RunnableTask2()); 29 * ...}</pre> 30 * 31 * However, the {@code Executor} interface does not strictly require 32 * that execution be asynchronous. In the simplest case, an executor 33 * can run the submitted task immediately in the caller's thread: 34 * 35 * <pre> {@code 36 * class DirectExecutor implements Executor { 37 * public void execute(Runnable r) { 38 * r.run(); 39 * } 40 * }}</pre> 41 * 42 * More typically, tasks are executed in some thread other than the 43 * caller's thread. The executor below spawns a new thread for each 44 * task. 45 * 46 * <pre> {@code 47 * class ThreadPerTaskExecutor implements Executor { 48 * public void execute(Runnable r) { 49 * new Thread(r).start(); 50 * } 51 * }}</pre> 52 * 53 * Many {@code Executor} implementations impose some sort of 54 * limitation on how and when tasks are scheduled. The executor below 55 * serializes the submission of tasks to a second executor, 56 * illustrating a composite executor. 57 * 58 * <pre> {@code 59 * class SerialExecutor implements Executor { 60 * final Queue!(Runnable) tasks = new ArrayDeque<>(); 61 * final Executor executor; 62 * Runnable active; 63 * 64 * SerialExecutor(Executor executor) { 65 * this.executor = executor; 66 * } 67 * 68 * public synchronized void execute(Runnable r) { 69 * tasks.add(() -> { 70 * try { 71 * r.run(); 72 * } finally { 73 * scheduleNext(); 74 * } 75 * }); 76 * if (active is null) { 77 * scheduleNext(); 78 * } 79 * } 80 * 81 * protected synchronized void scheduleNext() { 82 * if ((active = tasks.poll()) !is null) { 83 * executor.execute(active); 84 * } 85 * } 86 * }}</pre> 87 * 88 * The {@code Executor} implementations provided in this package 89 * implement {@link ExecutorService}, which is a more extensive 90 * interface. The {@link ThreadPoolExecutor} class provides an 91 * extensible thread pool implementation. The {@link Executors} class 92 * provides convenient factory methods for these Executors. 93 * 94 * <p>Memory consistency effects: Actions in a thread prior to 95 * submitting a {@code Runnable} object to an {@code Executor} 96 * <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a> 97 * its execution begins, perhaps in another thread. 98 * 99 * @since 1.5 100 * @author Doug Lea 101 */ 102 // interface Executor { 103 104 // /** 105 // * Executes the given command at some time in the future. The command 106 // * may execute in a new thread, in a pooled thread, or in the calling 107 // * thread, at the discretion of the {@code Executor} implementation. 108 // * 109 // * @param command the runnable task 110 // * @throws RejectedExecutionException if this task cannot be 111 // * accepted for execution 112 // * @throws NullPointerException if command is null 113 // */ 114 // void execute(Runnable command); 115 // }