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
019 package org.fusesource.hawtdispatch;
020
021 import org.fusesource.hawtdispatch.internal.DispatcherConfig;
022
023 import java.nio.channels.SelectableChannel;
024 import java.nio.channels.SelectionKey;
025 import 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 */
069 public 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 * A Runnable task that does nothing.
259 */
260 public static final Task NOOP = new Task() {
261 public void run() {}
262 };
263 }