xref: /trueos/lib/libdispatch/dispatch/block.h (revision bf5f91cb28c5878845eb00fbf329c042f6c643c9)
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  */
100 DISPATCH_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)
166 DISPATCH_EXPORT DISPATCH_NONNULL2 DISPATCH_RETURNS_RETAINED_BLOCK
167 DISPATCH_WARN_RESULT DISPATCH_NOTHROW
168 dispatch_block_t
169 dispatch_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)
238 DISPATCH_EXPORT DISPATCH_NONNULL4 DISPATCH_RETURNS_RETAINED_BLOCK
239 DISPATCH_WARN_RESULT DISPATCH_NOTHROW
240 dispatch_block_t
241 dispatch_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)
271 DISPATCH_EXPORT DISPATCH_NONNULL2 DISPATCH_NOTHROW
272 void
273 dispatch_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)
321 DISPATCH_EXPORT DISPATCH_NONNULL1 DISPATCH_NOTHROW
322 long
323 dispatch_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)
362 DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
363 void
364 dispatch_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)
394 DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
395 void
396 dispatch_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)
413 DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_WARN_RESULT DISPATCH_PURE
414 DISPATCH_NOTHROW
415 long
416 dispatch_block_testcancel(dispatch_block_t block);
417 
418 __END_DECLS
419 
420 #endif // __BLOCKS__
421 
422 #endif // __DISPATCH_BLOCK__
423