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