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.ScheduledExecutorService; 13 14 import hunt.concurrency.ExecutorService; 15 import hunt.concurrency.Delayed; 16 17 import hunt.util.Common; 18 19 import core.time; 20 21 /** 22 * An {@link ExecutorService} that can schedule commands to run after a given 23 * delay, or to execute periodically. 24 * 25 * <p>The {@code schedule} methods create tasks with various delays 26 * and return a task object that can be used to cancel or check 27 * execution. The {@code scheduleAtFixedRate} and 28 * {@code scheduleWithFixedDelay} methods create and execute tasks 29 * that run periodically until cancelled. 30 * 31 * <p>Commands submitted using the {@link Executor#execute(Runnable)} 32 * and {@link ExecutorService} {@code submit} methods are scheduled 33 * with a requested delay of zero. Zero and negative delays (but not 34 * periods) are also allowed in {@code schedule} methods, and are 35 * treated as requests for immediate execution. 36 * 37 * <p>All {@code schedule} methods accept <em>relative</em> delays and 38 * periods as arguments, not absolute times or dates. It is a simple 39 * matter to transform an absolute time represented as a {@link 40 * java.util.Date} to the required form. For example, to schedule at 41 * a certain future {@code date}, you can use: {@code schedule(task, 42 * date.getTime() - System.currentTimeMillis(), 43 * TimeUnit.MILLISECONDS)}. Beware however that expiration of a 44 * relative delay need not coincide with the current {@code Date} at 45 * which the task is enabled due to network time synchronization 46 * protocols, clock drift, or other factors. 47 * 48 * <p>The {@link Executors} class provides convenient factory methods for 49 * the ScheduledExecutorService implementations provided in this package. 50 * 51 * <h3>Usage Example</h3> 52 * 53 * Here is a class with a method that sets up a ScheduledExecutorService 54 * to beep every ten seconds for an hour: 55 * 56 * <pre> {@code 57 * import static hunt.concurrency.TimeUnit.*; 58 * class BeeperControl { 59 * private final ScheduledExecutorService scheduler = 60 * Executors.newScheduledThreadPool(1); 61 * 62 * public void beepForAnHour() { 63 * Runnable beeper = () -> System.out.println("beep"); 64 * ScheduledFuture<?> beeperHandle = 65 * scheduler.scheduleAtFixedRate(beeper, 10, 10, SECONDS); 66 * Runnable canceller = () -> beeperHandle.cancel(false); 67 * scheduler.schedule(canceller, 1, HOURS); 68 * } 69 * }}</pre> 70 * 71 * @author Doug Lea 72 */ 73 interface ScheduledExecutorService : ExecutorService { 74 75 /** 76 * Submits a one-shot task that becomes enabled after the given delay. 77 * 78 * @param command the task to execute 79 * @param delay the time from now to delay execution 80 * @param unit the time unit of the delay parameter 81 * @return a ScheduledFuture representing pending completion of 82 * the task and whose {@code get()} method will return 83 * {@code null} upon completion 84 * @throws RejectedExecutionException if the task cannot be 85 * scheduled for execution 86 * @throws NullPointerException if command or unit is null 87 */ 88 ScheduledFuture!void schedule(Runnable command, Duration delay); 89 90 // /** 91 // * Submits a value-returning one-shot task that becomes enabled 92 // * after the given delay. 93 // * 94 // * @param callable the function to execute 95 // * @param delay the time from now to delay execution 96 // * @param unit the time unit of the delay parameter 97 // * @param (V) the type of the callable's result 98 // * @return a ScheduledFuture that can be used to extract result or cancel 99 // * @throws RejectedExecutionException if the task cannot be 100 // * scheduled for execution 101 // * @throws NullPointerException if callable or unit is null 102 // */ 103 // !(V) ScheduledFuture!(V) schedule(Callable!(V) callable, Duration delay); 104 105 /** 106 * Submits a periodic action that becomes enabled first after the 107 * given initial delay, and subsequently with the given period; 108 * that is, executions will commence after 109 * {@code initialDelay}, then {@code initialDelay + period}, then 110 * {@code initialDelay + 2 * period}, and so on. 111 * 112 * <p>The sequence of task executions continues indefinitely until 113 * one of the following exceptional completions occur: 114 * <ul> 115 * <li>The task is {@linkplain Future#cancel explicitly cancelled} 116 * via the returned future. 117 * <li>The executor terminates, also resulting in task cancellation. 118 * <li>An execution of the task throws an exception. In this case 119 * calling {@link Future#get() get} on the returned future will throw 120 * {@link ExecutionException}, holding the exception as its cause. 121 * </ul> 122 * Subsequent executions are suppressed. Subsequent calls to 123 * {@link Future#isDone isDone()} on the returned future will 124 * return {@code true}. 125 * 126 * <p>If any execution of this task takes longer than its period, then 127 * subsequent executions may start late, but will not concurrently 128 * execute. 129 * 130 * @param command the task to execute 131 * @param initialDelay the time to delay first execution 132 * @param period the period between successive executions 133 * @param unit the time unit of the initialDelay and period parameters 134 * @return a ScheduledFuture representing pending completion of 135 * the series of repeated tasks. The future's {@link 136 * Future#get() get()} method will never return normally, 137 * and will throw an exception upon task cancellation or 138 * abnormal termination of a task execution. 139 * @throws RejectedExecutionException if the task cannot be 140 * scheduled for execution 141 * @throws NullPointerException if command or unit is null 142 * @throws IllegalArgumentException if period less than or equal to zero 143 */ 144 ScheduledFuture!void scheduleAtFixedRate(Runnable command, 145 Duration initialDelay, 146 Duration period); 147 148 /** 149 * Submits a periodic action that becomes enabled first after the 150 * given initial delay, and subsequently with the given delay 151 * between the termination of one execution and the commencement of 152 * the next. 153 * 154 * <p>The sequence of task executions continues indefinitely until 155 * one of the following exceptional completions occur: 156 * <ul> 157 * <li>The task is {@linkplain Future#cancel explicitly cancelled} 158 * via the returned future. 159 * <li>The executor terminates, also resulting in task cancellation. 160 * <li>An execution of the task throws an exception. In this case 161 * calling {@link Future#get() get} on the returned future will throw 162 * {@link ExecutionException}, holding the exception as its cause. 163 * </ul> 164 * Subsequent executions are suppressed. Subsequent calls to 165 * {@link Future#isDone isDone()} on the returned future will 166 * return {@code true}. 167 * 168 * @param command the task to execute 169 * @param initialDelay the time to delay first execution 170 * @param delay the delay between the termination of one 171 * execution and the commencement of the next 172 * @param unit the time unit of the initialDelay and delay parameters 173 * @return a ScheduledFuture representing pending completion of 174 * the series of repeated tasks. The future's {@link 175 * Future#get() get()} method will never return normally, 176 * and will throw an exception upon task cancellation or 177 * abnormal termination of a task execution. 178 * @throws RejectedExecutionException if the task cannot be 179 * scheduled for execution 180 * @throws NullPointerException if command or unit is null 181 * @throws IllegalArgumentException if delay less than or equal to zero 182 */ 183 ScheduledFuture!void scheduleWithFixedDelay(Runnable command, 184 Duration initialDelay, 185 Duration delay); 186 187 }