001/** 002 * Copyright (c) 2008-2009 Apple Inc. All rights reserved. 003 * Copyright (C) 2012 FuseSource, Inc. 004 * http://fusesource.com 005 * 006 * Licensed under the Apache License, Version 2.0 (the "License"); 007 * you may not use this file except in compliance with the License. 008 * You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 019package org.fusesource.hawtdispatch; 020 021import org.fusesource.hawtdispatch.internal.DispatcherConfig; 022 023import java.nio.channels.SelectableChannel; 024import java.nio.channels.SelectionKey; 025import java.util.List; 026 027/** 028 * <p> 029 * The Dispatch class is used to get or create dispatch objects such 030 * as global queues, thread queues, serial queues, or dispatch sources. 031 * </p><p> 032 * It is encouraged that end users of this api do a static import of the 033 * methods defined in this class. 034 * <pre> 035 * import static org.fusesource.hawtdispatch.Dispatch.*; 036 * </pre> 037 * </p><p> 038 * The dispatch queues are {@link java.util.concurrent.Executor} 039 * objects that execute tasks asynchronously on thread pools managed by the 040 * Dispatcher. 041 * 042 * <ul> 043 * <li> 044 * <b>Global Queues:</b> The tasks submitted to a concurrent dispatch 045 * queue will execute concurrently on the first available thread of 046 * the thread pool. The order of execution of the tasks is non 047 * deterministic. 048 * </li><li> 049 * <b>Thread Queues:</b> The tasks submitted to a thread dispatch 050 * queue will execute serially (FIFO order) on a single thread of 051 * the thread pool. 052 * </li><li> 053 * <b>Serial Queues:</b> The tasks submitted to a serial dispatch 054 * queue will execute serially (FIFO order) on the first available 055 * thread of the thread pool. 056 * </li> 057 * </p><p> 058 * All dispatch queues use a shared fixed size thread pool to execute 059 * tasks. All tasks submitted on a dispatch queue should be non-blocking 060 * and wait free. 061 * </p><p> 062 * Dispatch sources provide a way to trigger execution of a user task on 063 * on a user selected dispatch queue in response to NIO or application 064 * defined events. 065 * </p> 066 * 067 * @author <a href="http://hiramchirino.com">Hiram Chirino</a> 068 */ 069public class Dispatch { 070 071 final private static Dispatcher DISPATCHER = DispatcherConfig.getDefaultDispatcher(); 072 073 public static final DispatchPriority HIGH = DispatchPriority.HIGH; 074 public static final DispatchPriority DEFAULT = DispatchPriority.DEFAULT; 075 public static final DispatchPriority LOW = DispatchPriority.LOW; 076 077 /** 078 * <p> 079 * Returns the global concurrent queue of default priority. 080 * </p> 081 * 082 * @see #getGlobalQueue(DispatchPriority) 083 * @return the default priority global queue. 084 */ 085 public static DispatchQueue getGlobalQueue() { 086 return DISPATCHER.getGlobalQueue(); 087 } 088 089 /** 090 * <p> 091 * Returns a well-known global concurrent queue of a given priority level. 092 * </p><p> 093 * The well-known global concurrent queues may not be modified. Calls to 094 * {@link Suspendable#suspend()}, {@link Suspendable#resume()}, etc., will 095 * have no effect when used with queues returned by this function. 096 * </p> 097 * 098 * @param priority 099 * A priority defined in dispatch_queue_priority_t 100 * @return the requested global queue. 101 */ 102 public static DispatchQueue getGlobalQueue(DispatchPriority priority) { 103 return DISPATCHER.getGlobalQueue(priority); 104 } 105 106 /** 107 * <p> 108 * Creates a new serial dispatch queue to which runnable objects may be submitted. 109 * </p><p> 110 * Serial dispatch queues execute runnables submitted to them serially in FIFO order. A 111 * queue will only invoke one runnable at a time, but independent queues may each 112 * execute their runnables concurrently with respect to each other. 113 * </p><p> 114 * Conceptually a dispatch queue may have its own thread of execution, and 115 * interaction between queues is highly asynchronous. 116 * </p><p> 117 * 118 * @param label the label to assign the dispatch queue, can be null 119 * @return the newly created dispatch queue 120 */ 121 public static DispatchQueue createQueue(String label) { 122 return DISPATCHER.createQueue(label); 123 } 124 125 /** 126 * <p> 127 * Creates a new serial dispatch queue to which runnable objects may be submitted. 128 * </p> 129 * <p> 130 * Same thing as <code>createQueue(null)</code> 131 * </p> 132 * @see #createQueue(String) 133 * @return the newly created dispatch queue 134 */ 135 public static DispatchQueue createQueue() { 136 return DISPATCHER.createQueue(null); 137 } 138 139 /** 140 * <p> 141 * Returns the queue on which the currently executing runnable is running. 142 * </p><p> 143 * When {@link #getCurrentQueue()} is called outside of the context of a 144 * submitted runnable, it will return null. 145 * </p> 146 * 147 * @return the queue on which the currently executing runnable is running. 148 */ 149 public static DispatchQueue getCurrentQueue() { 150 return DISPATCHER.getCurrentQueue(); 151 } 152 153 /** 154 * <p> 155 * Creates a new {@link DispatchSource} to monitor {@link SelectableChannel} objects and 156 * automatically submit a handler runnable to a dispatch queue in response to events. 157 * </p><p> 158 * You are allowed to create multiple dispatch sources to the same {@link SelectableChannel} 159 * object. 160 * </p> 161 * 162 * @param channel the channel to monitor. 163 * @param interestOps A mask of interest ops ({@link SelectionKey#OP_ACCEPT}, 164 * {@link SelectionKey#OP_CONNECT}, {@link SelectionKey#OP_READ}, or 165 * {@link SelectionKey#OP_WRITE}) specifying which events are desired. 166 * @param queue The dispatch queue to which the event handler tasks will be submited. 167 * 168 * @return the newly created DispatchSource 169 */ 170 public static DispatchSource createSource(SelectableChannel channel, int interestOps, DispatchQueue queue) { 171 return DISPATCHER.createSource(channel, interestOps, queue); 172 } 173 174 /** 175 * <p> 176 * Creates a new {@link CustomDispatchSource} to monitor events merged into 177 * the dispatch source and automatically submit a handler runnable to a dispatch queue 178 * in response to the events. 179 * </p> 180 * 181 * @param aggregator the data aggregation strategy to use. 182 * @param queue The dispatch queue to which the event handler tasks will be submited. 183 * 184 * @return the newly created CustomDispatchSource 185 */ 186 public static <Event, MergedEvent> CustomDispatchSource<Event, MergedEvent> createSource(EventAggregator<Event, MergedEvent> aggregator, DispatchQueue queue) { 187 return DISPATCHER.createSource(aggregator, queue); 188 } 189 190 /** 191 * @return the thread level dispatch queues for a given dispatch priority. 192 */ 193 public static DispatchQueue[] getThreadQueues(DispatchPriority priority) { 194 return DISPATCHER.getThreadQueues(priority); 195 } 196 197 /** 198 * 199 * @return the current thread queue or null of not executing on a thread queue. 200 */ 201 public static DispatchQueue getCurrentThreadQueue() { 202 return DISPATCHER.getCurrentThreadQueue(); 203 } 204 205// Being able to execute stuff on the main thread is critical for some GUI implementations. For now 206// we will not expose these interfaces until are fully cooked / have good test cases for them. 207// 208// /** 209// * <p> 210// * Returns the default queue that is bound to the main thread. 211// * </p><p> 212// * In order to invoke runnables submitted to the main queue, the application must 213// * call {@link #dispatchMain()}}. 214// * </p> 215// * 216// * @return the main queue. 217// */ 218// public static DispatchQueue getMainQueue() { 219// return DISPATCHER.getMainQueue(); 220// } 221// 222// /** 223// * <p> 224// * Execute runnables submitted to the main queue. 225// * </p><p> 226// * This function "parks" the main thread and waits for runnables to be submitted 227// * to the main queue. This function never returns. 228// * </p> 229// */ 230// public static void dispatchMain() { 231// DISPATCHER.dispatchMain(); 232// } 233// 234 235 /** 236 * If enabled then it enables profiling on the global 237 * queues and any newly created queues. If not enabled 238 * then it disables profiling support on all the currently 239 * profiled queues and any queues created in the future. 240 * 241 * @param enabled 242 */ 243 public static void profile(boolean enabled) { 244 DISPATCHER.profile(enabled); 245 } 246 247 /** 248 * Used to get profiling metrics for all the queues 249 * currently being profiled. 250 * 251 * @return 252 */ 253 public static List<Metrics> metrics() { 254 return DISPATCHER.metrics(); 255 } 256 257 /** 258 * Shutdown default dispatcher instance. 259 */ 260 public static void shutdown() { 261 DISPATCHER.shutdown(); 262 } 263 264 /** 265 * Restart default dispatcher instance. 266 */ 267 public static void restart() { 268 DISPATCHER.restart(); 269 } 270 271 /** 272 * A Runnable task that does nothing. 273 */ 274 public static final Task NOOP = new Task() { 275 public void run() {} 276 }; 277}