1 /*
2  * Copyright (c) 2008-2012 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_OBJECT__
22 #define __DISPATCH_OBJECT__
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 #if __has_include(<sys/qos.h>)
30 #include <sys/qos.h>
31 #endif
32 
33 DISPATCH_ASSUME_NONNULL_BEGIN
34 
35 /*!
36  * @typedef dispatch_object_t
37  *
38  * @abstract
39  * Abstract base type for all dispatch objects.
40  * The details of the type definition are language-specific.
41  *
42  * @discussion
43  * Dispatch objects are reference counted via calls to dispatch_retain() and
44  * dispatch_release().
45  */
46 
47 #if OS_OBJECT_USE_OBJC
48 /*
49  * By default, dispatch objects are declared as Objective-C types when building
50  * with an Objective-C compiler. This allows them to participate in ARC, in RR
51  * management by the Blocks runtime and in leaks checking by the static
52  * analyzer, and enables them to be added to Cocoa collections.
53  * See <os/object.h> for details.
54  */
55 OS_OBJECT_DECL_CLASS(dispatch_object);
56 
57 #if OS_OBJECT_SWIFT3
58 #define DISPATCH_DECL(name) OS_OBJECT_DECL_SUBCLASS_SWIFT(name, dispatch_object)
59 #define DISPATCH_DECL_SUBCLASS(name, base) OS_OBJECT_DECL_SUBCLASS_SWIFT(name, base)
60 #else // OS_OBJECT_SWIFT3
61 #define DISPATCH_DECL(name) OS_OBJECT_DECL_SUBCLASS(name, dispatch_object)
62 #define DISPATCH_DECL_SUBCLASS(name, base) OS_OBJECT_DECL_SUBCLASS(name, base)
63 
64 DISPATCH_INLINE DISPATCH_ALWAYS_INLINE DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
65 void
_dispatch_object_validate(dispatch_object_t object)66 _dispatch_object_validate(dispatch_object_t object)
67 {
68 	void *isa = *(void *volatile*)(OS_OBJECT_BRIDGE void*)object;
69 	(void)isa;
70 }
71 #endif // OS_OBJECT_SWIFT3
72 
73 #define DISPATCH_GLOBAL_OBJECT(type, object) ((OS_OBJECT_BRIDGE type)&(object))
74 #define DISPATCH_RETURNS_RETAINED OS_OBJECT_RETURNS_RETAINED
75 #elif defined(__cplusplus) && !defined(__DISPATCH_BUILDING_DISPATCH__)
76 /*
77  * Dispatch objects are NOT C++ objects. Nevertheless, we can at least keep C++
78  * aware of type compatibility.
79  */
80 typedef struct dispatch_object_s {
81 private:
82 	dispatch_object_s();
83 	~dispatch_object_s();
84 	dispatch_object_s(const dispatch_object_s &);
85 	void operator=(const dispatch_object_s &);
86 } *dispatch_object_t;
87 #define DISPATCH_DECL(name) \
88 		typedef struct name##_s : public dispatch_object_s {} *name##_t
89 #define DISPATCH_DECL_SUBCLASS(name, base) \
90 		typedef struct name##_s : public base##_s {} *name##_t
91 #define DISPATCH_GLOBAL_OBJECT(type, object) (static_cast<type>(&(object)))
92 #define DISPATCH_RETURNS_RETAINED
93 #else /* Plain C */
94 typedef union {
95 	struct _os_object_s *_os_obj;
96 	struct dispatch_object_s *_do;
97 	struct dispatch_queue_s *_dq;
98 	struct dispatch_queue_attr_s *_dqa;
99 	struct dispatch_group_s *_dg;
100 	struct dispatch_source_s *_ds;
101 	struct dispatch_channel_s *_dch;
102 	struct dispatch_mach_s *_dm;
103 	struct dispatch_mach_msg_s *_dmsg;
104 	struct dispatch_semaphore_s *_dsema;
105 	struct dispatch_data_s *_ddata;
106 	struct dispatch_io_s *_dchannel;
107 } dispatch_object_t DISPATCH_TRANSPARENT_UNION;
108 #define DISPATCH_DECL(name) typedef struct name##_s *name##_t
109 #define DISPATCH_DECL_SUBCLASS(name, base) typedef base##_t name##_t
110 #define DISPATCH_GLOBAL_OBJECT(type, object) ((type)&(object))
111 #define DISPATCH_RETURNS_RETAINED
112 #endif
113 
114 #if OS_OBJECT_SWIFT3 && OS_OBJECT_USE_OBJC
115 #define DISPATCH_SOURCE_TYPE_DECL(name) \
116 		DISPATCH_EXPORT struct dispatch_source_type_s \
117 				_dispatch_source_type_##name; \
118 		OS_OBJECT_DECL_PROTOCOL(dispatch_source_##name, <OS_dispatch_source>); \
119 		OS_OBJECT_CLASS_IMPLEMENTS_PROTOCOL( \
120 				dispatch_source, dispatch_source_##name)
121 #define DISPATCH_SOURCE_DECL(name) \
122 		DISPATCH_DECL(name); \
123 		OS_OBJECT_DECL_PROTOCOL(name, <NSObject>); \
124 		OS_OBJECT_CLASS_IMPLEMENTS_PROTOCOL(name, name)
125 #ifndef DISPATCH_DATA_DECL
126 #define DISPATCH_DATA_DECL(name) OS_OBJECT_DECL_SWIFT(name)
127 #endif // DISPATCH_DATA_DECL
128 #else
129 #define DISPATCH_SOURCE_DECL(name) \
130 		DISPATCH_DECL(name);
131 #define DISPATCH_DATA_DECL(name) DISPATCH_DECL(name)
132 #define DISPATCH_SOURCE_TYPE_DECL(name) \
133 		DISPATCH_EXPORT const struct dispatch_source_type_s \
134 		_dispatch_source_type_##name
135 #endif
136 
137 #ifdef __BLOCKS__
138 /*!
139  * @typedef dispatch_block_t
140  *
141  * @abstract
142  * The type of blocks submitted to dispatch queues, which take no arguments
143  * and have no return value.
144  *
145  * @discussion
146  * When not building with Objective-C ARC, a block object allocated on or
147  * copied to the heap must be released with a -[release] message or the
148  * Block_release() function.
149  *
150  * The declaration of a block literal allocates storage on the stack.
151  * Therefore, this is an invalid construct:
152  * <code>
153  * dispatch_block_t block;
154  * if (x) {
155  *     block = ^{ printf("true\n"); };
156  * } else {
157  *     block = ^{ printf("false\n"); };
158  * }
159  * block(); // unsafe!!!
160  * </code>
161  *
162  * What is happening behind the scenes:
163  * <code>
164  * if (x) {
165  *     struct Block __tmp_1 = ...; // setup details
166  *     block = &__tmp_1;
167  * } else {
168  *     struct Block __tmp_2 = ...; // setup details
169  *     block = &__tmp_2;
170  * }
171  * </code>
172  *
173  * As the example demonstrates, the address of a stack variable is escaping the
174  * scope in which it is allocated. That is a classic C bug.
175  *
176  * Instead, the block literal must be copied to the heap with the Block_copy()
177  * function or by sending it a -[copy] message.
178  */
179 typedef void (^dispatch_block_t)(void);
180 #endif // __BLOCKS__
181 
182 __BEGIN_DECLS
183 
184 /*!
185  * @typedef dispatch_qos_class_t
186  * Alias for qos_class_t type.
187  */
188 #if __has_include(<sys/qos.h>)
189 typedef qos_class_t dispatch_qos_class_t;
190 #else
191 typedef unsigned int dispatch_qos_class_t;
192 #endif
193 
194 /*!
195  * @function dispatch_retain
196  *
197  * @abstract
198  * Increment the reference count of a dispatch object.
199  *
200  * @discussion
201  * Calls to dispatch_retain() must be balanced with calls to
202  * dispatch_release().
203  *
204  * @param object
205  * The object to retain.
206  * The result of passing NULL in this parameter is undefined.
207  */
208 API_AVAILABLE(macos(10.6), ios(4.0))
209 DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
210 DISPATCH_SWIFT_UNAVAILABLE("Can't be used with ARC")
211 void
212 dispatch_retain(dispatch_object_t object);
213 #if OS_OBJECT_USE_OBJC_RETAIN_RELEASE
214 #undef dispatch_retain
215 #define dispatch_retain(object) \
216 		__extension__({ dispatch_object_t _o = (object); \
217 		_dispatch_object_validate(_o); (void)[_o retain]; })
218 #endif
219 
220 /*!
221  * @function dispatch_release
222  *
223  * @abstract
224  * Decrement the reference count of a dispatch object.
225  *
226  * @discussion
227  * A dispatch object is asynchronously deallocated once all references are
228  * released (i.e. the reference count becomes zero). The system does not
229  * guarantee that a given client is the last or only reference to a given
230  * object.
231  *
232  * @param object
233  * The object to release.
234  * The result of passing NULL in this parameter is undefined.
235  */
236 API_AVAILABLE(macos(10.6), ios(4.0))
237 DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
238 DISPATCH_SWIFT_UNAVAILABLE("Can't be used with ARC")
239 void
240 dispatch_release(dispatch_object_t object);
241 #if OS_OBJECT_USE_OBJC_RETAIN_RELEASE
242 #undef dispatch_release
243 #define dispatch_release(object) \
244 		__extension__({ dispatch_object_t _o = (object); \
245 		_dispatch_object_validate(_o); [_o release]; })
246 #endif
247 
248 /*!
249  * @function dispatch_get_context
250  *
251  * @abstract
252  * Returns the application defined context of the object.
253  *
254  * @param object
255  * The result of passing NULL in this parameter is undefined.
256  *
257  * @result
258  * The context of the object; may be NULL.
259  */
260 API_AVAILABLE(macos(10.6), ios(4.0))
261 DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_PURE DISPATCH_WARN_RESULT
262 DISPATCH_NOTHROW
263 void *_Nullable
264 dispatch_get_context(dispatch_object_t object);
265 
266 /*!
267  * @function dispatch_set_context
268  *
269  * @abstract
270  * Associates an application defined context with the object.
271  *
272  * @param object
273  * The result of passing NULL in this parameter is undefined.
274  *
275  * @param context
276  * The new client defined context for the object. This may be NULL.
277  *
278  */
279 API_AVAILABLE(macos(10.6), ios(4.0))
280 DISPATCH_EXPORT DISPATCH_NOTHROW
281 void
282 dispatch_set_context(dispatch_object_t object, void *_Nullable context);
283 
284 /*!
285  * @function dispatch_set_finalizer_f
286  *
287  * @abstract
288  * Set the finalizer function for a dispatch object.
289  *
290  * @param object
291  * The dispatch object to modify.
292  * The result of passing NULL in this parameter is undefined.
293  *
294  * @param finalizer
295  * The finalizer function pointer.
296  *
297  * @discussion
298  * A dispatch object's finalizer will be invoked on the object's target queue
299  * after all references to the object have been released. This finalizer may be
300  * used by the application to release any resources associated with the object,
301  * such as freeing the object's context.
302  * The context parameter passed to the finalizer function is the current
303  * context of the dispatch object at the time the finalizer call is made.
304  */
305 API_AVAILABLE(macos(10.6), ios(4.0))
306 DISPATCH_EXPORT DISPATCH_NOTHROW
307 void
308 dispatch_set_finalizer_f(dispatch_object_t object,
309 		dispatch_function_t _Nullable finalizer);
310 
311 /*!
312  * @function dispatch_activate
313  *
314  * @abstract
315  * Activates the specified dispatch object.
316  *
317  * @discussion
318  * Dispatch objects such as queues and sources may be created in an inactive
319  * state. Objects in this state have to be activated before any blocks
320  * associated with them will be invoked.
321  *
322  * The target queue of inactive objects can be changed using
323  * dispatch_set_target_queue(). Change of target queue is no longer permitted
324  * once an initially inactive object has been activated.
325  *
326  * Calling dispatch_activate() on an active object has no effect.
327  * Releasing the last reference count on an inactive object is undefined.
328  *
329  * @param object
330  * The object to be activated.
331  * The result of passing NULL in this parameter is undefined.
332  */
333 API_AVAILABLE(macos(10.12), ios(10.0), tvos(10.0), watchos(3.0))
334 DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
335 void
336 dispatch_activate(dispatch_object_t object);
337 
338 /*!
339  * @function dispatch_suspend
340  *
341  * @abstract
342  * Suspends the invocation of blocks on a dispatch object.
343  *
344  * @discussion
345  * A suspended object will not invoke any blocks associated with it. The
346  * suspension of an object will occur after any running block associated with
347  * the object completes.
348  *
349  * Calls to dispatch_suspend() must be balanced with calls
350  * to dispatch_resume().
351  *
352  * @param object
353  * The object to be suspended.
354  * The result of passing NULL in this parameter is undefined.
355  */
356 API_AVAILABLE(macos(10.6), ios(4.0))
357 DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
358 void
359 dispatch_suspend(dispatch_object_t object);
360 
361 /*!
362  * @function dispatch_resume
363  *
364  * @abstract
365  * Resumes the invocation of blocks on a dispatch object.
366  *
367  * @discussion
368  * Dispatch objects can be suspended with dispatch_suspend(), which increments
369  * an internal suspension count. dispatch_resume() is the inverse operation,
370  * and consumes suspension counts. When the last suspension count is consumed,
371  * blocks associated with the object will be invoked again.
372  *
373  * For backward compatibility reasons, dispatch_resume() on an inactive and not
374  * otherwise suspended dispatch source object has the same effect as calling
375  * dispatch_activate(). For new code, using dispatch_activate() is preferred.
376  *
377  * If the specified object has zero suspension count and is not an inactive
378  * source, this function will result in an assertion and the process being
379  * terminated.
380  *
381  * @param object
382  * The object to be resumed.
383  * The result of passing NULL in this parameter is undefined.
384  */
385 API_AVAILABLE(macos(10.6), ios(4.0))
386 DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
387 void
388 dispatch_resume(dispatch_object_t object);
389 
390 /*!
391  * @function dispatch_set_qos_class_floor
392  *
393  * @abstract
394  * Sets the QOS class floor on a dispatch queue, source or workloop.
395  *
396  * @discussion
397  * The QOS class of workitems submitted to this object asynchronously will be
398  * elevated to at least the specified QOS class floor. The QOS of the workitem
399  * will be used if higher than the floor even when the workitem has been created
400  * without "ENFORCE" semantics.
401  *
402  * Setting the QOS class floor is equivalent to the QOS effects of configuring
403  * a queue whose target queue has a QoS class set to the same value.
404  *
405  * @param object
406  * A dispatch queue, workloop, or source to configure.
407  * The object must be inactive.
408  *
409  * Passing another object type or an object that has been activated is undefined
410  * and will cause the process to be terminated.
411  *
412  * @param qos_class
413  * A QOS class value:
414  *  - QOS_CLASS_USER_INTERACTIVE
415  *  - QOS_CLASS_USER_INITIATED
416  *  - QOS_CLASS_DEFAULT
417  *  - QOS_CLASS_UTILITY
418  *  - QOS_CLASS_BACKGROUND
419  * Passing any other value is undefined.
420  *
421  * @param relative_priority
422  * A relative priority within the QOS class. This value is a negative
423  * offset from the maximum supported scheduler priority for the given class.
424  * Passing a value greater than zero or less than QOS_MIN_RELATIVE_PRIORITY
425  * is undefined.
426  */
427 API_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0))
428 DISPATCH_EXPORT DISPATCH_NOTHROW
429 void
430 dispatch_set_qos_class_floor(dispatch_object_t object,
431 		dispatch_qos_class_t qos_class, int relative_priority);
432 
433 #ifdef __BLOCKS__
434 /*!
435  * @function dispatch_wait
436  *
437  * @abstract
438  * Wait synchronously for an object or until the specified timeout has elapsed.
439  *
440  * @discussion
441  * Type-generic macro that maps to dispatch_block_wait, dispatch_group_wait or
442  * dispatch_semaphore_wait, depending on the type of the first argument.
443  * See documentation for these functions for more details.
444  * This function is unavailable for any other object type.
445  *
446  * @param object
447  * The object to wait on.
448  * The result of passing NULL in this parameter is undefined.
449  *
450  * @param timeout
451  * When to timeout (see dispatch_time). As a convenience, there are the
452  * DISPATCH_TIME_NOW and DISPATCH_TIME_FOREVER constants.
453  *
454  * @result
455  * Returns zero on success or non-zero on error (i.e. timed out).
456  */
457 DISPATCH_UNAVAILABLE
458 DISPATCH_EXPORT DISPATCH_NONNULL1 DISPATCH_NOTHROW
459 intptr_t
460 dispatch_wait(void *object, dispatch_time_t timeout);
461 #if __has_extension(c_generic_selections)
462 #define dispatch_wait(object, timeout) \
463 		_Generic((object), \
464 			dispatch_block_t:dispatch_block_wait, \
465 			dispatch_group_t:dispatch_group_wait, \
466 			dispatch_semaphore_t:dispatch_semaphore_wait \
467 		)((object),(timeout))
468 #endif
469 
470 /*!
471  * @function dispatch_notify
472  *
473  * @abstract
474  * Schedule a notification block to be submitted to a queue when the execution
475  * of a specified object has completed.
476  *
477  * @discussion
478  * Type-generic macro that maps to dispatch_block_notify or
479  * dispatch_group_notify, depending on the type of the first argument.
480  * See documentation for these functions for more details.
481  * This function is unavailable for any other object type.
482  *
483  * @param object
484  * The object to observe.
485  * The result of passing NULL in this parameter is undefined.
486  *
487  * @param queue
488  * The queue to which the supplied notification block will be submitted when
489  * the observed object completes.
490  *
491  * @param notification_block
492  * The block to submit when the observed object completes.
493  */
494 DISPATCH_UNAVAILABLE
495 DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
496 void
497 dispatch_notify(void *object, dispatch_object_t queue,
498 		dispatch_block_t notification_block);
499 #if __has_extension(c_generic_selections)
500 #define dispatch_notify(object, queue, notification_block) \
501 		_Generic((object), \
502 			dispatch_block_t:dispatch_block_notify, \
503 			dispatch_group_t:dispatch_group_notify \
504 		)((object),(queue), (notification_block))
505 #endif
506 
507 /*!
508  * @function dispatch_cancel
509  *
510  * @abstract
511  * Cancel the specified object.
512  *
513  * @discussion
514  * Type-generic macro that maps to dispatch_block_cancel or
515  * dispatch_source_cancel, depending on the type of the first argument.
516  * See documentation for these functions for more details.
517  * This function is unavailable for any other object type.
518  *
519  * @param object
520  * The object to cancel.
521  * The result of passing NULL in this parameter is undefined.
522  */
523 DISPATCH_UNAVAILABLE
524 DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
525 void
526 dispatch_cancel(void *object);
527 #if __has_extension(c_generic_selections)
528 #define dispatch_cancel(object) \
529 		_Generic((object), \
530 			dispatch_block_t:dispatch_block_cancel, \
531 			dispatch_source_t:dispatch_source_cancel \
532 		)((object))
533 #endif
534 
535 /*!
536  * @function dispatch_testcancel
537  *
538  * @abstract
539  * Test whether the specified object has been canceled
540  *
541  * @discussion
542  * Type-generic macro that maps to dispatch_block_testcancel or
543  * dispatch_source_testcancel, depending on the type of the first argument.
544  * See documentation for these functions for more details.
545  * This function is unavailable for any other object type.
546  *
547  * @param object
548  * The object to test.
549  * The result of passing NULL in this parameter is undefined.
550  *
551  * @result
552  * Non-zero if canceled and zero if not canceled.
553  */
554 DISPATCH_UNAVAILABLE
555 DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_WARN_RESULT DISPATCH_PURE
556 DISPATCH_NOTHROW
557 intptr_t
558 dispatch_testcancel(void *object);
559 #if __has_extension(c_generic_selections)
560 #define dispatch_testcancel(object) \
561 		_Generic((object), \
562 			dispatch_block_t:dispatch_block_testcancel, \
563 			dispatch_source_t:dispatch_source_testcancel \
564 		)((object))
565 #endif
566 #endif // __BLOCKS__
567 
568 /*!
569  * @function dispatch_debug
570  *
571  * @abstract
572  * Programmatically log debug information about a dispatch object.
573  *
574  * @discussion
575  * Programmatically log debug information about a dispatch object. By default,
576  * the log output is sent to syslog at notice level. In the debug version of
577  * the library, the log output is sent to a file in /var/tmp.
578  * The log output destination can be configured via the LIBDISPATCH_LOG
579  * environment variable, valid values are: YES, NO, syslog, stderr, file.
580  *
581  * This function is deprecated and will be removed in a future release.
582  * Objective-C callers may use -debugDescription instead.
583  *
584  * @param object
585  * The object to introspect.
586  *
587  * @param message
588  * The message to log above and beyond the introspection.
589  */
590 API_DEPRECATED("unsupported interface", macos(10.6,10.9), ios(4.0,6.0))
591 DISPATCH_EXPORT DISPATCH_NONNULL2 DISPATCH_NOTHROW DISPATCH_COLD
592 __attribute__((__format__(printf,2,3)))
593 void
594 dispatch_debug(dispatch_object_t object, const char *message, ...);
595 
596 API_DEPRECATED("unsupported interface", macos(10.6,10.9), ios(4.0,6.0))
597 DISPATCH_EXPORT DISPATCH_NONNULL2 DISPATCH_NOTHROW DISPATCH_COLD
598 __attribute__((__format__(printf,2,0)))
599 void
600 dispatch_debugv(dispatch_object_t object, const char *message, va_list ap);
601 
602 __END_DECLS
603 
604 DISPATCH_ASSUME_NONNULL_END
605 
606 #endif