xref: /NextBSD/lib/libdispatch/dispatch/object.h (revision 33da5adc555b3bc29986eeadca03829e4ad06b1e)
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 /*!
30  * @typedef dispatch_object_t
31  *
32  * @abstract
33  * Abstract base type for all dispatch objects.
34  * The details of the type definition are language-specific.
35  *
36  * @discussion
37  * Dispatch objects are reference counted via calls to dispatch_retain() and
38  * dispatch_release().
39  */
40 
41 #if OS_OBJECT_USE_OBJC
42 /*
43  * By default, dispatch objects are declared as Objective-C types when building
44  * with an Objective-C compiler. This allows them to participate in ARC, in RR
45  * management by the Blocks runtime and in leaks checking by the static
46  * analyzer, and enables them to be added to Cocoa collections.
47  * See <os/object.h> for details.
48  */
49 
50 OS_OBJECT_DECL(dispatch_object);
51 #define DISPATCH_DECL(name) OS_OBJECT_DECL_SUBCLASS(name, dispatch_object)
52 #define DISPATCH_GLOBAL_OBJECT(type, object) ((OS_OBJECT_BRIDGE type)&(object))
53 #define DISPATCH_RETURNS_RETAINED OS_OBJECT_RETURNS_RETAINED
54 DISPATCH_INLINE DISPATCH_ALWAYS_INLINE DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
55 void
_dispatch_object_validate(dispatch_object_t object)56 _dispatch_object_validate(dispatch_object_t object) {
57 	void *isa = *(void* volatile*)(OS_OBJECT_BRIDGE void*)object;
58 	(void)isa;
59 }
60 #elif defined(__cplusplus)
61 /*
62  * Dispatch objects are NOT C++ objects. Nevertheless, we can at least keep C++
63  * aware of type compatibility.
64  */
65 typedef struct dispatch_object_s {
66 private:
67 	dispatch_object_s();
68 	~dispatch_object_s();
69 	dispatch_object_s(const dispatch_object_s &);
70 	void operator=(const dispatch_object_s &);
71 } *dispatch_object_t;
72 #define DISPATCH_DECL(name) \
73 		typedef struct name##_s : public dispatch_object_s {} *name##_t
74 #define DISPATCH_GLOBAL_OBJECT(type, object) (&(object))
75 #define DISPATCH_RETURNS_RETAINED
76 #else /* Plain C */
77 typedef union {
78 	struct _os_object_s *_os_obj;
79 	struct dispatch_object_s *_do;
80 	struct dispatch_continuation_s *_dc;
81 	struct dispatch_queue_s *_dq;
82 	struct dispatch_queue_attr_s *_dqa;
83 	struct dispatch_group_s *_dg;
84 	struct dispatch_source_s *_ds;
85 	struct dispatch_mach_s *_dm;
86 	struct dispatch_mach_msg_s *_dmsg;
87 	struct dispatch_timer_aggregate_s *_dta;
88 	struct dispatch_source_attr_s *_dsa;
89 	struct dispatch_semaphore_s *_dsema;
90 	struct dispatch_data_s *_ddata;
91 	struct dispatch_io_s *_dchannel;
92 	struct dispatch_operation_s *_doperation;
93 	struct dispatch_disk_s *_ddisk;
94 } dispatch_object_t __attribute__((__transparent_union__));
95 /*! @parseOnly */
96 #define DISPATCH_DECL(name) typedef struct name##_s *name##_t
97 /*! @parseOnly */
98 #define DISPATCH_GLOBAL_OBJECT(t, x) (&(x))
99 /*! @parseOnly */
100 #define DISPATCH_RETURNS_RETAINED
101 #endif
102 
103 /*!
104  * @typedef dispatch_block_t
105  *
106  * @abstract
107  * The type of blocks submitted to dispatch queues, which take no arguments
108  * and have no return value.
109  *
110  * @discussion
111  * When not building with Objective-C ARC, a block object allocated on or
112  * copied to the heap must be released with a -[release] message or the
113  * Block_release() function.
114  *
115  * The declaration of a block literal allocates storage on the stack.
116  * Therefore, this is an invalid construct:
117  * <code>
118  * dispatch_block_t block;
119  * if (x) {
120  *     block = ^{ printf("true\n"); };
121  * } else {
122  *     block = ^{ printf("false\n"); };
123  * }
124  * block(); // unsafe!!!
125  * </code>
126  *
127  * What is happening behind the scenes:
128  * <code>
129  * if (x) {
130  *     struct Block __tmp_1 = ...; // setup details
131  *     block = &__tmp_1;
132  * } else {
133  *     struct Block __tmp_2 = ...; // setup details
134  *     block = &__tmp_2;
135  * }
136  * </code>
137  *
138  * As the example demonstrates, the address of a stack variable is escaping the
139  * scope in which it is allocated. That is a classic C bug.
140  *
141  * Instead, the block literal must be copied to the heap with the Block_copy()
142  * function or by sending it a -[copy] message.
143  */
144 typedef void (^dispatch_block_t)(void);
145 
146 __BEGIN_DECLS
147 
148 /*!
149  * @function dispatch_retain
150  *
151  * @abstract
152  * Increment the reference count of a dispatch object.
153  *
154  * @discussion
155  * Calls to dispatch_retain() must be balanced with calls to
156  * dispatch_release().
157  *
158  * @param object
159  * The object to retain.
160  * The result of passing NULL in this parameter is undefined.
161  */
162 __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_4_0)
163 DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
164 void
165 dispatch_retain(dispatch_object_t object);
166 #if OS_OBJECT_USE_OBJC_RETAIN_RELEASE
167 #undef dispatch_retain
168 #define dispatch_retain(object) ({ dispatch_object_t _o = (object); \
169 		_dispatch_object_validate(_o); (void)[_o retain]; })
170 #endif
171 
172 /*!
173  * @function dispatch_release
174  *
175  * @abstract
176  * Decrement the reference count of a dispatch object.
177  *
178  * @discussion
179  * A dispatch object is asynchronously deallocated once all references are
180  * released (i.e. the reference count becomes zero). The system does not
181  * guarantee that a given client is the last or only reference to a given
182  * object.
183  *
184  * @param object
185  * The object to release.
186  * The result of passing NULL in this parameter is undefined.
187  */
188 __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_4_0)
189 DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
190 void
191 dispatch_release(dispatch_object_t object);
192 #if OS_OBJECT_USE_OBJC_RETAIN_RELEASE
193 #undef dispatch_release
194 #define dispatch_release(object) ({ dispatch_object_t _o = (object); \
195 		_dispatch_object_validate(_o); [_o release]; })
196 #endif
197 
198 /*!
199  * @function dispatch_get_context
200  *
201  * @abstract
202  * Returns the application defined context of the object.
203  *
204  * @param object
205  * The result of passing NULL in this parameter is undefined.
206  *
207  * @result
208  * The context of the object; may be NULL.
209  */
210 __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_4_0)
211 DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_PURE DISPATCH_WARN_RESULT
212 DISPATCH_NOTHROW
213 void *
214 dispatch_get_context(dispatch_object_t object);
215 
216 /*!
217  * @function dispatch_set_context
218  *
219  * @abstract
220  * Associates an application defined context with the object.
221  *
222  * @param object
223  * The result of passing NULL in this parameter is undefined.
224  *
225  * @param context
226  * The new client defined context for the object. This may be NULL.
227  *
228  */
229 __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_4_0)
230 DISPATCH_EXPORT DISPATCH_NOTHROW //DISPATCH_NONNULL1
231 void
232 dispatch_set_context(dispatch_object_t object, void *context);
233 
234 /*!
235  * @function dispatch_set_finalizer_f
236  *
237  * @abstract
238  * Set the finalizer function for a dispatch object.
239  *
240  * @param object
241  * The dispatch object to modify.
242  * The result of passing NULL in this parameter is undefined.
243  *
244  * @param finalizer
245  * The finalizer function pointer.
246  *
247  * @discussion
248  * A dispatch object's finalizer will be invoked on the object's target queue
249  * after all references to the object have been released. This finalizer may be
250  * used by the application to release any resources associated with the object,
251  * such as freeing the object's context.
252  * The context parameter passed to the finalizer function is the current
253  * context of the dispatch object at the time the finalizer call is made.
254  */
255 __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_4_0)
256 DISPATCH_EXPORT DISPATCH_NOTHROW //DISPATCH_NONNULL1
257 void
258 dispatch_set_finalizer_f(dispatch_object_t object,
259 		dispatch_function_t finalizer);
260 
261 /*!
262  * @function dispatch_suspend
263  *
264  * @abstract
265  * Suspends the invocation of blocks on a dispatch object.
266  *
267  * @discussion
268  * A suspended object will not invoke any blocks associated with it. The
269  * suspension of an object will occur after any running block associated with
270  * the object completes.
271  *
272  * Calls to dispatch_suspend() must be balanced with calls
273  * to dispatch_resume().
274  *
275  * @param object
276  * The object to be suspended.
277  * The result of passing NULL in this parameter is undefined.
278  */
279 __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_4_0)
280 DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
281 void
282 dispatch_suspend(dispatch_object_t object);
283 
284 /*!
285  * @function dispatch_resume
286  *
287  * @abstract
288  * Resumes the invocation of blocks on a dispatch object.
289  *
290  * @param object
291  * The object to be resumed.
292  * The result of passing NULL in this parameter is undefined.
293  */
294 __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_4_0)
295 DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
296 void
297 dispatch_resume(dispatch_object_t object);
298 
299 /*!
300  * @function dispatch_wait
301  *
302  * @abstract
303  * Wait synchronously for an object or until the specified timeout has elapsed.
304  *
305  * @discussion
306  * Type-generic macro that maps to dispatch_block_wait, dispatch_group_wait or
307  * dispatch_semaphore_wait, depending on the type of the first argument.
308  * See documentation for these functions for more details.
309  * This function is unavailable for any other object type.
310  *
311  * @param object
312  * The object to wait on.
313  * The result of passing NULL in this parameter is undefined.
314  *
315  * @param timeout
316  * When to timeout (see dispatch_time). As a convenience, there are the
317  * DISPATCH_TIME_NOW and DISPATCH_TIME_FOREVER constants.
318  *
319  * @result
320  * Returns zero on success or non-zero on error (i.e. timed out).
321  */
322 DISPATCH_UNAVAILABLE
323 DISPATCH_EXPORT DISPATCH_NONNULL1 DISPATCH_NOTHROW
324 long
325 dispatch_wait(void *object, dispatch_time_t timeout);
326 #if __has_extension(c_generic_selections)
327 #define dispatch_wait(object, timeout) \
328 		_Generic((object), \
329 			dispatch_block_t:dispatch_block_wait, \
330 			dispatch_group_t:dispatch_group_wait, \
331 			dispatch_semaphore_t:dispatch_semaphore_wait \
332 		)((object),(timeout))
333 #endif
334 
335 /*!
336  * @function dispatch_notify
337  *
338  * @abstract
339  * Schedule a notification block to be submitted to a queue when the execution
340  * of a specified object has completed.
341  *
342  * @discussion
343  * Type-generic macro that maps to dispatch_block_notify or
344  * dispatch_group_notify, depending on the type of the first argument.
345  * See documentation for these functions for more details.
346  * This function is unavailable for any other object type.
347  *
348  * @param object
349  * The object to observe.
350  * The result of passing NULL in this parameter is undefined.
351  *
352  * @param queue
353  * The queue to which the supplied notification block will be submitted when
354  * the observed object completes.
355  *
356  * @param notification_block
357  * The block to submit when the observed object completes.
358  */
359 DISPATCH_UNAVAILABLE
360 DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
361 void
362 dispatch_notify(void *object, dispatch_object_t queue,
363 		dispatch_block_t notification_block);
364 #if __has_extension(c_generic_selections)
365 #define dispatch_notify(object, queue, notification_block) \
366 		_Generic((object), \
367 			dispatch_block_t:dispatch_block_notify, \
368 			dispatch_group_t:dispatch_group_notify \
369 		)((object),(queue), (notification_block))
370 #endif
371 
372 /*!
373  * @function dispatch_cancel
374  *
375  * @abstract
376  * Cancel the specified object.
377  *
378  * @discussion
379  * Type-generic macro that maps to dispatch_block_cancel or
380  * dispatch_source_cancel, depending on the type of the first argument.
381  * See documentation for these functions for more details.
382  * This function is unavailable for any other object type.
383  *
384  * @param object
385  * The object to cancel.
386  * The result of passing NULL in this parameter is undefined.
387  */
388 DISPATCH_UNAVAILABLE
389 DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
390 void
391 dispatch_cancel(void *object);
392 #if __has_extension(c_generic_selections)
393 #define dispatch_cancel(object) \
394 		_Generic((object), \
395 			dispatch_block_t:dispatch_block_cancel, \
396 			dispatch_source_t:dispatch_source_cancel \
397 		)((object))
398 #endif
399 
400 /*!
401  * @function dispatch_testcancel
402  *
403  * @abstract
404  * Test whether the specified object has been canceled
405  *
406  * @discussion
407  * Type-generic macro that maps to dispatch_block_testcancel or
408  * dispatch_source_testcancel, depending on the type of the first argument.
409  * See documentation for these functions for more details.
410  * This function is unavailable for any other object type.
411  *
412  * @param object
413  * The object to test.
414  * The result of passing NULL in this parameter is undefined.
415  *
416  * @result
417  * Non-zero if canceled and zero if not canceled.
418  */
419 DISPATCH_UNAVAILABLE
420 DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_WARN_RESULT DISPATCH_PURE
421 DISPATCH_NOTHROW
422 long
423 dispatch_testcancel(void *object);
424 #if __has_extension(c_generic_selections)
425 #define dispatch_testcancel(object) \
426 		_Generic((object), \
427 			dispatch_block_t:dispatch_block_testcancel, \
428 			dispatch_source_t:dispatch_source_testcancel \
429 		)((object))
430 #endif
431 
432 /*!
433  * @function dispatch_debug
434  *
435  * @abstract
436  * Programmatically log debug information about a dispatch object.
437  *
438  * @discussion
439  * Programmatically log debug information about a dispatch object. By default,
440  * the log output is sent to syslog at notice level. In the debug version of
441  * the library, the log output is sent to a file in /var/tmp.
442  * The log output destination can be configured via the LIBDISPATCH_LOG
443  * environment variable, valid values are: YES, NO, syslog, stderr, file.
444  *
445  * This function is deprecated and will be removed in a future release.
446  * Objective-C callers may use -debugDescription instead.
447  *
448  * @param object
449  * The object to introspect.
450  *
451  * @param message
452  * The message to log above and beyond the introspection.
453  */
454 __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_6,__MAC_10_9,__IPHONE_4_0,__IPHONE_6_0)
455 DISPATCH_EXPORT DISPATCH_NONNULL2 DISPATCH_NOTHROW
456 __attribute__((__format__(printf,2,3)))
457 void
458 dispatch_debug(dispatch_object_t object, const char *message, ...);
459 
460 __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_6,__MAC_10_9,__IPHONE_4_0,__IPHONE_6_0)
461 DISPATCH_EXPORT DISPATCH_NONNULL2 DISPATCH_NOTHROW
462 __attribute__((__format__(printf,2,0)))
463 void
464 dispatch_debugv(dispatch_object_t object, const char *message, va_list ap);
465 
466 __END_DECLS
467 
468 #endif
469