1/*
2 * Copyright (c) 2014 Apple Inc. All rights reserved.
3 *
4 * @APPLE_APACHE_LICENSE_HEADER_START@
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 *     http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 * @APPLE_APACHE_LICENSE_HEADER_END@
19 */
20
21#ifndef __DISPATCH_BLOCK__
22#define __DISPATCH_BLOCK__
23
24#ifndef __DISPATCH_INDIRECT__
25#error "Please #include <dispatch/dispatch.h> instead of this file directly."
26#include <dispatch/base.h> // for HeaderDoc
27#endif
28
29#ifdef __BLOCKS__
30
31/*!
32 * @group Dispatch block objects
33 */
34
35__BEGIN_DECLS
36
37/*!
38 * @typedef dispatch_block_flags_t
39 * Flags to pass to the dispatch_block_create* functions.
40 *
41 * @const DISPATCH_BLOCK_BARRIER
42 * Flag indicating that a dispatch block object should act as a barrier block
43 * when submitted to a DISPATCH_QUEUE_CONCURRENT queue.
44 * See dispatch_barrier_async() for details.
45 * This flag has no effect when the dispatch block object is invoked directly.
46 *
47 * @const DISPATCH_BLOCK_DETACHED
48 * Flag indicating that a dispatch block object should execute disassociated
49 * from current execution context attributes such as QOS class, os_activity_t
50 * and properties of the current IPC request (if any). If invoked directly, the
51 * block object will remove these attributes from the calling thread for the
52 * duration of the block body (before applying attributes assigned to the block
53 * object, if any). If submitted to a queue, the block object will be executed
54 * with the attributes of the queue (or any attributes specifically assigned to
55 * the block object).
56 *
57 * @const DISPATCH_BLOCK_ASSIGN_CURRENT
58 * Flag indicating that a dispatch block object should be assigned the execution
59 * context attributes that are current at the time the block object is created.
60 * This applies to attributes such as QOS class, os_activity_t and properties of
61 * the current IPC request (if any). If invoked directly, the block object will
62 * apply these attributes to the calling thread for the duration of the block
63 * body. If the block object is submitted to a queue, this flag replaces the
64 * default behavior of associating the submitted block instance with the
65 * execution context attributes that are current at the time of submission.
66 * If a specific QOS class is assigned with DISPATCH_BLOCK_NO_QOS_CLASS or
67 * dispatch_block_create_with_qos_class(), that QOS class takes precedence over
68 * the QOS class assignment indicated by this flag.
69 *
70 * @const DISPATCH_BLOCK_NO_QOS_CLASS
71 * Flag indicating that a dispatch block object should be not be assigned a QOS
72 * class. If invoked directly, the block object will be executed with the QOS
73 * class of the calling thread. If the block object is submitted to a queue,
74 * this replaces the default behavior of associating the submitted block
75 * instance with the QOS class current at the time of submission.
76 * This flag is ignored if a specific QOS class is assigned with
77 * dispatch_block_create_with_qos_class().
78 *
79 * @const DISPATCH_BLOCK_INHERIT_QOS_CLASS
80 * Flag indicating that execution of a dispatch block object submitted to a
81 * queue should prefer the QOS class assigned to the queue over the QOS class
82 * assigned to the block (resp. associated with the block at the time of
83 * submission). The latter will only be used if the queue in question does not
84 * have an assigned QOS class, as long as doing so does not result in a QOS
85 * class lower than the QOS class inherited from the queue's target queue.
86 * This flag is the default when a dispatch block object is submitted to a queue
87 * for asynchronous execution and has no effect when the dispatch block object
88 * is invoked directly. It is ignored if DISPATCH_BLOCK_ENFORCE_QOS_CLASS is
89 * also passed.
90 *
91 * @const DISPATCH_BLOCK_ENFORCE_QOS_CLASS
92 * Flag indicating that execution of a dispatch block object submitted to a
93 * queue should prefer the QOS class assigned to the block (resp. associated
94 * with the block at the time of submission) over the QOS class assigned to the
95 * queue, as long as doing so will not result in a lower QOS class.
96 * This flag is the default when a dispatch block object is submitted to a queue
97 * for synchronous execution or when the dispatch block object is invoked
98 * directly.
99 */
100DISPATCH_ENUM(dispatch_block_flags, unsigned long,
101	DISPATCH_BLOCK_BARRIER
102			DISPATCH_ENUM_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_8_0) = 0x1,
103	DISPATCH_BLOCK_DETACHED
104			DISPATCH_ENUM_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_8_0) = 0x2,
105	DISPATCH_BLOCK_ASSIGN_CURRENT
106			DISPATCH_ENUM_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_8_0) = 0x4,
107	DISPATCH_BLOCK_NO_QOS_CLASS
108			DISPATCH_ENUM_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_8_0) = 0x8,
109	DISPATCH_BLOCK_INHERIT_QOS_CLASS
110			DISPATCH_ENUM_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_8_0) = 0x10,
111	DISPATCH_BLOCK_ENFORCE_QOS_CLASS
112			DISPATCH_ENUM_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_8_0) = 0x20,
113);
114
115/*!
116 * @function dispatch_block_create
117 *
118 * @abstract
119 * Create a new dispatch block object on the heap from an existing block and
120 * the given flags.
121 *
122 * @discussion
123 * The provided block is Block_copy'ed to the heap and retained by the newly
124 * created dispatch block object.
125 *
126 * The returned dispatch block object is intended to be submitted to a dispatch
127 * queue with dispatch_async() and related functions, but may also be invoked
128 * directly. Both operations can be performed an arbitrary number of times but
129 * only the first completed execution of a dispatch block object can be waited
130 * on with dispatch_block_wait() or observed with dispatch_block_notify().
131 *
132 * If the returned dispatch block object is submitted to a dispatch queue, the
133 * submitted block instance will be associated with the QOS class current at the
134 * time of submission, unless one of the following flags assigned a specific QOS
135 * class (or no QOS class) at the time of block creation:
136 *  - DISPATCH_BLOCK_ASSIGN_CURRENT
137 *  - DISPATCH_BLOCK_NO_QOS_CLASS
138 *  - DISPATCH_BLOCK_DETACHED
139 * The QOS class the block object will be executed with also depends on the QOS
140 * class assigned to the queue and which of the following flags was specified or
141 * defaulted to:
142 *  - DISPATCH_BLOCK_INHERIT_QOS_CLASS (default for asynchronous execution)
143 *  - DISPATCH_BLOCK_ENFORCE_QOS_CLASS (default for synchronous execution)
144 * See description of dispatch_block_flags_t for details.
145 *
146 * If the returned dispatch block object is submitted directly to a serial queue
147 * and is configured to execute with a specific QOS class, the system will make
148 * a best effort to apply the necessary QOS overrides to ensure that blocks
149 * submitted earlier to the serial queue are executed at that same QOS class or
150 * higher.
151 *
152 * @param flags
153 * Configuration flags for the block object.
154 * Passing a value that is not a bitwise OR of flags from dispatch_block_flags_t
155 * results in NULL being returned.
156 *
157 * @param block
158 * The block to create the dispatch block object from.
159 *
160 * @result
161 * The newly created dispatch block object, or NULL.
162 * When not building with Objective-C ARC, must be released with a -[release]
163 * message or the Block_release() function.
164 */
165__OSX_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_8_0)
166DISPATCH_EXPORT DISPATCH_NONNULL2 DISPATCH_RETURNS_RETAINED_BLOCK
167DISPATCH_WARN_RESULT DISPATCH_NOTHROW
168dispatch_block_t
169dispatch_block_create(dispatch_block_flags_t flags, dispatch_block_t block);
170
171/*!
172 * @function dispatch_block_create_with_qos_class
173 *
174 * @abstract
175 * Create a new dispatch block object on the heap from an existing block and
176 * the given flags, and assign it the specified QOS class and relative priority.
177 *
178 * @discussion
179 * The provided block is Block_copy'ed to the heap and retained by the newly
180 * created dispatch block object.
181 *
182 * The returned dispatch block object is intended to be submitted to a dispatch
183 * queue with dispatch_async() and related functions, but may also be invoked
184 * directly. Both operations can be performed an arbitrary number of times but
185 * only the first completed execution of a dispatch block object can be waited
186 * on with dispatch_block_wait() or observed with dispatch_block_notify().
187 *
188 * If invoked directly, the returned dispatch block object will be executed with
189 * the assigned QOS class as long as that does not result in a lower QOS class
190 * than what is current on the calling thread.
191 *
192 * If the returned dispatch block object is submitted to a dispatch queue, the
193 * QOS class it will be executed with depends on the QOS class assigned to the
194 * block, the QOS class assigned to the queue and which of the following flags
195 * was specified or defaulted to:
196 *  - DISPATCH_BLOCK_INHERIT_QOS_CLASS: default for asynchronous execution
197 *  - DISPATCH_BLOCK_ENFORCE_QOS_CLASS: default for synchronous execution
198 * See description of dispatch_block_flags_t for details.
199 *
200 * If the returned dispatch block object is submitted directly to a serial queue
201 * and is configured to execute with a specific QOS class, the system will make
202 * a best effort to apply the necessary QOS overrides to ensure that blocks
203 * submitted earlier to the serial queue are executed at that same QOS class or
204 * higher.
205 *
206 * @param flags
207 * Configuration flags for the new block object.
208 * Passing a value that is not a bitwise OR of flags from dispatch_block_flags_t
209 * results in NULL being returned.
210 *
211 * @param qos_class
212 * A QOS class value:
213 *  - QOS_CLASS_USER_INTERACTIVE
214 *  - QOS_CLASS_USER_INITIATED
215 *  - QOS_CLASS_DEFAULT
216 *  - QOS_CLASS_UTILITY
217 *  - QOS_CLASS_BACKGROUND
218 *  - QOS_CLASS_UNSPECIFIED
219 * Passing QOS_CLASS_UNSPECIFIED is equivalent to specifying the
220 * DISPATCH_BLOCK_NO_QOS_CLASS flag. Passing any other value results in NULL
221 * being returned.
222 *
223 * @param relative_priority
224 * A relative priority within the QOS class. This value is a negative
225 * offset from the maximum supported scheduler priority for the given class.
226 * Passing a value greater than zero or less than QOS_MIN_RELATIVE_PRIORITY
227 * results in NULL being returned.
228 *
229 * @param block
230 * The block to create the dispatch block object from.
231 *
232 * @result
233 * The newly created dispatch block object, or NULL.
234 * When not building with Objective-C ARC, must be released with a -[release]
235 * message or the Block_release() function.
236 */
237__OSX_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_8_0)
238DISPATCH_EXPORT DISPATCH_NONNULL4 DISPATCH_RETURNS_RETAINED_BLOCK
239DISPATCH_WARN_RESULT DISPATCH_NOTHROW
240dispatch_block_t
241dispatch_block_create_with_qos_class(dispatch_block_flags_t flags,
242		dispatch_qos_class_t qos_class, int relative_priority,
243		dispatch_block_t block);
244
245/*!
246 * @function dispatch_block_perform
247 *
248 * @abstract
249 * Create, synchronously execute and release a dispatch block object from the
250 * specified block and flags.
251 *
252 * @discussion
253 * Behaves identically to the sequence
254 * <code>
255 * dispatch_block_t b = dispatch_block_create(flags, block);
256 * b();
257 * Block_release(b);
258 * </code>
259 * but may be implemented more efficiently internally by not requiring a copy
260 * to the heap of the specified block or the allocation of a new block object.
261 *
262 * @param flags
263 * Configuration flags for the temporary block object.
264 * The result of passing a value that is not a bitwise OR of flags from
265 * dispatch_block_flags_t is undefined.
266 *
267 * @param block
268 * The block to create the temporary block object from.
269 */
270__OSX_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_8_0)
271DISPATCH_EXPORT DISPATCH_NONNULL2 DISPATCH_NOTHROW
272void
273dispatch_block_perform(dispatch_block_flags_t flags, dispatch_block_t block);
274
275/*!
276 * @function dispatch_block_wait
277 *
278 * @abstract
279 * Wait synchronously until execution of the specified dispatch block object has
280 * completed or until the specified timeout has elapsed.
281 *
282 * @discussion
283 * This function will return immediately if execution of the block object has
284 * already completed.
285 *
286 * It is not possible to wait for multiple executions of the same block object
287 * with this interface; use dispatch_group_wait() for that purpose. A single
288 * dispatch block object may either be waited on once and executed once,
289 * or it may be executed any number of times. The behavior of any other
290 * combination is undefined. Submission to a dispatch queue counts as an
291 * execution, even if cancelation (dispatch_block_cancel) means the block's
292 * code never runs.
293 *
294 * The result of calling this function from multiple threads simultaneously
295 * with the same dispatch block object is undefined, but note that doing so
296 * would violate the rules described in the previous paragraph.
297 *
298 * If this function returns indicating that the specified timeout has elapsed,
299 * then that invocation does not count as the one allowed wait.
300 *
301 * If at the time this function is called, the specified dispatch block object
302 * has been submitted directly to a serial queue, the system will make a best
303 * effort to apply the necessary QOS overrides to ensure that the block and any
304 * blocks submitted earlier to that serial queue are executed at the QOS class
305 * (or higher) of the thread calling dispatch_block_wait().
306 *
307 * @param block
308 * The dispatch block object to wait on.
309 * The result of passing NULL or a block object not returned by one of the
310 * dispatch_block_create* functions is undefined.
311 *
312 * @param timeout
313 * When to timeout (see dispatch_time). As a convenience, there are the
314 * DISPATCH_TIME_NOW and DISPATCH_TIME_FOREVER constants.
315 *
316 * @result
317 * Returns zero on success (the dispatch block object completed within the
318 * specified timeout) or non-zero on error (i.e. timed out).
319 */
320__OSX_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_8_0)
321DISPATCH_EXPORT DISPATCH_NONNULL1 DISPATCH_NOTHROW
322long
323dispatch_block_wait(dispatch_block_t block, dispatch_time_t timeout);
324
325/*!
326 * @function dispatch_block_notify
327 *
328 * @abstract
329 * Schedule a notification block to be submitted to a queue when the execution
330 * of a specified dispatch block object has completed.
331 *
332 * @discussion
333 * This function will submit the notification block immediately if execution of
334 * the observed block object has already completed.
335 *
336 * It is not possible to be notified of multiple executions of the same block
337 * object with this interface, use dispatch_group_notify() for that purpose.
338 *
339 * A single dispatch block object may either be observed one or more times
340 * and executed once, or it may be executed any number of times. The behavior
341 * of any other combination is undefined. Submission to a dispatch queue
342 * counts as an execution, even if cancellation (dispatch_block_cancel) means
343 * the block's code never runs.
344 *
345 * If multiple notification blocks are scheduled for a single block object,
346 * there is no defined order in which the notification blocks will be submitted
347 * to their associated queues.
348 *
349 * @param block
350 * The dispatch block object to observe.
351 * The result of passing NULL or a block object not returned by one of the
352 * dispatch_block_create* functions is undefined.
353 *
354 * @param queue
355 * The queue to which the supplied notification block will be submitted when
356 * the observed block completes.
357 *
358 * @param notification_block
359 * The notification block to submit when the observed block object completes.
360 */
361__OSX_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_8_0)
362DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
363void
364dispatch_block_notify(dispatch_block_t block, dispatch_queue_t queue,
365		dispatch_block_t notification_block);
366
367/*!
368 * @function dispatch_block_cancel
369 *
370 * @abstract
371 * Asynchronously cancel the specified dispatch block object.
372 *
373 * @discussion
374 * Cancellation causes any future execution of the dispatch block object to
375 * return immediately, but does not affect any execution of the block object
376 * that is already in progress.
377 *
378 * Release of any resources associated with the block object will be delayed
379 * until execution of the block object is next attempted (or any execution
380 * already in progress completes).
381 *
382 * NOTE: care needs to be taken to ensure that a block object that may be
383 *       canceled does not capture any resources that require execution of the
384 *       block body in order to be released (e.g. memory allocated with
385 *       malloc(3) that the block body calls free(3) on). Such resources will
386 *       be leaked if the block body is never executed due to cancellation.
387 *
388 * @param block
389 * The dispatch block object to cancel.
390 * The result of passing NULL or a block object not returned by one of the
391 * dispatch_block_create* functions is undefined.
392 */
393__OSX_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_8_0)
394DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
395void
396dispatch_block_cancel(dispatch_block_t block);
397
398/*!
399 * @function dispatch_block_testcancel
400 *
401 * @abstract
402 * Tests whether the given dispatch block object has been canceled.
403 *
404 * @param block
405 * The dispatch block object to test.
406 * The result of passing NULL or a block object not returned by one of the
407 * dispatch_block_create* functions is undefined.
408 *
409 * @result
410 * Non-zero if canceled and zero if not canceled.
411 */
412__OSX_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_8_0)
413DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_WARN_RESULT DISPATCH_PURE
414DISPATCH_NOTHROW
415long
416dispatch_block_testcancel(dispatch_block_t block);
417
418__END_DECLS
419
420#endif // __BLOCKS__
421
422#endif // __DISPATCH_BLOCK__
423