]> git.saurik.com Git - apple/libdispatch.git/blob - src/object_internal.h
libdispatch-501.40.12.tar.gz
[apple/libdispatch.git] / src / object_internal.h
1 /*
2 * Copyright (c) 2008-2013 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 /*
22 * IMPORTANT: This header file describes INTERNAL interfaces to libdispatch
23 * which are subject to change in future releases of Mac OS X. Any applications
24 * relying on these interfaces WILL break.
25 */
26
27 #ifndef __DISPATCH_OBJECT_INTERNAL__
28 #define __DISPATCH_OBJECT_INTERNAL__
29
30 #if OS_OBJECT_USE_OBJC
31 #define DISPATCH_DECL_INTERNAL_SUBCLASS(name, super) \
32 OS_OBJECT_DECL_SUBCLASS(name, super)
33 #define DISPATCH_DECL_INTERNAL(name) \
34 DISPATCH_DECL_INTERNAL_SUBCLASS(name, dispatch_object)
35 #define DISPATCH_DECL_SUBCLASS_INTERFACE(name, super) \
36 _OS_OBJECT_DECL_SUBCLASS_INTERFACE(name, super)
37 #else
38 #define DISPATCH_DECL_INTERNAL_SUBCLASS(name, super) DISPATCH_DECL(name)
39 #define DISPATCH_DECL_INTERNAL(name) DISPATCH_DECL(name)
40 #define DISPATCH_DECL_SUBCLASS_INTERFACE(name, super)
41 #endif // OS_OBJECT_USE_OBJC
42
43 DISPATCH_ENUM(dispatch_invoke_flags, unsigned long,
44 DISPATCH_INVOKE_NONE = 0x00,
45 /* This invoke is a stealer, meaning that it doesn't own the
46 * enqueue lock, and is not allowed to requeue elsewhere
47 */
48 DISPATCH_INVOKE_STEALING = 0x01,
49 /* The `dc` argument is a dispatch continuation wrapper
50 * created by _dispatch_queue_push_override
51 */
52 DISPATCH_INVOKE_OVERRIDING = 0x02,
53 );
54
55 #if USE_OBJC
56 #define DISPATCH_CLASS(name) OS_OBJECT_CLASS(dispatch_##name)
57 // ObjC classes and dispatch vtables are co-located via linker order and alias
58 // files rdar://10640168
59 #define DISPATCH_VTABLE_SUBCLASS_INSTANCE(name, super, ...) \
60 __attribute__((section("__DATA,__objc_data"), used)) \
61 static const struct { \
62 DISPATCH_VTABLE_HEADER(super); \
63 } DISPATCH_CONCAT(_,DISPATCH_CLASS(name##_vtable)) = { \
64 __VA_ARGS__ \
65 }
66 #else
67 #define DISPATCH_VTABLE_SUBCLASS_INSTANCE(name, super, ...) \
68 DISPATCH_CONST_STRUCT_INSTANCE(dispatch_##super##_vtable_s, \
69 _dispatch_##name##_vtable, \
70 ._os_obj_xref_dispose = _dispatch_xref_dispose, \
71 ._os_obj_dispose = _dispatch_dispose, \
72 __VA_ARGS__)
73 #endif // USE_OBJC
74
75 #define DISPATCH_SUBCLASS_DECL(name, super) \
76 DISPATCH_DECL_SUBCLASS_INTERFACE(dispatch_##name, super) \
77 struct dispatch_##name##_s; \
78 extern DISPATCH_CONST_STRUCT_DECL(dispatch_##name##_vtable_s, \
79 _dispatch_##name##_vtable, \
80 { \
81 _OS_OBJECT_CLASS_HEADER(); \
82 DISPATCH_VTABLE_HEADER(name); \
83 })
84 #define DISPATCH_CLASS_DECL(name) DISPATCH_SUBCLASS_DECL(name, dispatch_object)
85 #define DISPATCH_INTERNAL_SUBCLASS_DECL(name, super) \
86 DISPATCH_DECL_INTERNAL_SUBCLASS(dispatch_##name, dispatch_##super); \
87 DISPATCH_DECL_SUBCLASS_INTERFACE(dispatch_##name, dispatch_##super) \
88 extern DISPATCH_CONST_STRUCT_DECL(dispatch_##super##_vtable_s, \
89 _dispatch_##name##_vtable)
90 #define DISPATCH_VTABLE_INSTANCE(name, ...) \
91 DISPATCH_VTABLE_SUBCLASS_INSTANCE(name, name, __VA_ARGS__)
92 #define DISPATCH_VTABLE(name) &_dispatch_##name##_vtable
93
94 #if !TARGET_OS_WIN32
95 #define DISPATCH_VTABLE_HEADER(x) \
96 unsigned long const do_type; \
97 const char *const do_kind; \
98 size_t (*const do_debug)(struct dispatch_##x##_s *, char *, size_t); \
99 void (*const do_invoke)(struct dispatch_##x##_s *, dispatch_object_t dc, \
100 dispatch_invoke_flags_t); \
101 unsigned long (*const do_probe)(struct dispatch_##x##_s *); \
102 void (*const do_dispose)(struct dispatch_##x##_s *);
103 #else
104 // Cannot be const on Win32 because we initialize at runtime.
105 #define DISPATCH_VTABLE_HEADER(x) \
106 unsigned long do_type; \
107 const char *do_kind; \
108 size_t (*do_debug)(struct dispatch_##x##_s *, char *, size_t); \
109 void (*do_invoke)(struct dispatch_##x##_s *, dispatch_object_t dc, \
110 dispatch_invoke_flags_t); \
111 unsigned long (*do_probe)(struct dispatch_##x##_s *); \
112 void (*do_dispose)(struct dispatch_##x##_s *);
113 #endif
114
115 #define dx_type(x) (x)->do_vtable->do_type
116 #define dx_metatype(x) ((x)->do_vtable->do_type & _DISPATCH_META_TYPE_MASK)
117 #define dx_kind(x) (x)->do_vtable->do_kind
118 #define dx_debug(x, y, z) (x)->do_vtable->do_debug((x), (y), (z))
119 #define dx_dispose(x) (x)->do_vtable->do_dispose(x)
120 #define dx_invoke(x, y, z) (x)->do_vtable->do_invoke(x, y, z)
121 #define dx_probe(x) (x)->do_vtable->do_probe(x)
122
123 #define DISPATCH_STRUCT_HEADER(x) \
124 _OS_OBJECT_HEADER( \
125 const struct dispatch_##x##_vtable_s *do_vtable, \
126 do_ref_cnt, \
127 do_xref_cnt); \
128 struct dispatch_##x##_s *volatile do_next; \
129 struct dispatch_queue_s *do_targetq; \
130 void *do_ctxt; \
131 void *do_finalizer; \
132 unsigned int volatile do_suspend_cnt;
133
134 #define DISPATCH_OBJECT_GLOBAL_REFCNT _OS_OBJECT_GLOBAL_REFCNT
135 // "word and bit" must be a power of two to be safely subtracted
136 #define DISPATCH_OBJECT_SUSPEND_LOCK 1u
137 #define DISPATCH_OBJECT_SUSPEND_INTERVAL 2u
138 #define DISPATCH_OBJECT_SUSPENDED(x) \
139 ((x)->do_suspend_cnt >= DISPATCH_OBJECT_SUSPEND_INTERVAL)
140 #ifdef __LP64__
141 // the bottom nibble must not be zero, the rest of the bits should be random
142 // we sign extend the 64-bit version so that a better instruction encoding is
143 // generated on Intel
144 #define DISPATCH_OBJECT_LISTLESS ((void *)0xffffffff89abcdef)
145 #else
146 #define DISPATCH_OBJECT_LISTLESS ((void *)0x89abcdef)
147 #endif
148
149 enum {
150 _DISPATCH_CONTINUATION_TYPE = 0x00000, // meta-type for continuations
151 _DISPATCH_QUEUE_TYPE = 0x10000, // meta-type for queues
152 _DISPATCH_SOURCE_TYPE = 0x20000, // meta-type for sources
153 _DISPATCH_SEMAPHORE_TYPE = 0x30000, // meta-type for semaphores
154 _DISPATCH_NODE_TYPE = 0x40000, // meta-type for data node
155 _DISPATCH_IO_TYPE = 0x50000, // meta-type for io channels
156 _DISPATCH_OPERATION_TYPE = 0x60000, // meta-type for io operations
157 _DISPATCH_DISK_TYPE = 0x70000, // meta-type for io disks
158 _DISPATCH_META_TYPE_MASK = 0xfff0000, // mask for object meta-types
159 _DISPATCH_ATTR_TYPE = 0x10000000, // meta-type for attributes
160
161 DISPATCH_CONTINUATION_TYPE = _DISPATCH_CONTINUATION_TYPE,
162
163 DISPATCH_DATA_TYPE = 1 | _DISPATCH_NODE_TYPE,
164 DISPATCH_MACH_MSG_TYPE = 2 | _DISPATCH_NODE_TYPE,
165
166 DISPATCH_IO_TYPE = _DISPATCH_IO_TYPE,
167 DISPATCH_OPERATION_TYPE = _DISPATCH_OPERATION_TYPE,
168 DISPATCH_DISK_TYPE = _DISPATCH_DISK_TYPE,
169
170 DISPATCH_QUEUE_ATTR_TYPE = _DISPATCH_QUEUE_TYPE |_DISPATCH_ATTR_TYPE,
171
172 DISPATCH_QUEUE_TYPE = 1 | _DISPATCH_QUEUE_TYPE,
173 DISPATCH_QUEUE_ROOT_TYPE = 2 | _DISPATCH_QUEUE_TYPE,
174 DISPATCH_QUEUE_MGR_TYPE = 3 | _DISPATCH_QUEUE_TYPE,
175 DISPATCH_QUEUE_SPECIFIC_TYPE = 4 | _DISPATCH_QUEUE_TYPE,
176
177 DISPATCH_SEMAPHORE_TYPE = 1 | _DISPATCH_SEMAPHORE_TYPE,
178 DISPATCH_GROUP_TYPE = 2 | _DISPATCH_SEMAPHORE_TYPE,
179
180 DISPATCH_SOURCE_KEVENT_TYPE = 1 | _DISPATCH_SOURCE_TYPE,
181 DISPATCH_MACH_CHANNEL_TYPE = 2 | _DISPATCH_SOURCE_TYPE,
182 };
183
184 DISPATCH_SUBCLASS_DECL(object, object);
185 struct dispatch_object_s {
186 DISPATCH_STRUCT_HEADER(object);
187 };
188
189 size_t _dispatch_object_debug_attr(dispatch_object_t dou, char* buf,
190 size_t bufsiz);
191 void *_dispatch_alloc(const void *vtable, size_t size);
192 void _dispatch_xref_dispose(dispatch_object_t dou);
193 void _dispatch_dispose(dispatch_object_t dou);
194 #if DISPATCH_COCOA_COMPAT
195 void *_dispatch_autorelease_pool_push(void);
196 void _dispatch_autorelease_pool_pop(void *context);
197 #endif
198
199 #if USE_OBJC
200 #include <objc/runtime.h>
201
202 #define OS_OBJC_CLASS_SYMBOL(name) \
203 DISPATCH_CONCAT(OBJC_CLASS_$_,name)
204 #define OS_OBJC_CLASS_DECL(name) \
205 extern void *OS_OBJC_CLASS_SYMBOL(name)
206 #define OS_OBJC_CLASS(name) \
207 ((Class)&OS_OBJC_CLASS_SYMBOL(name))
208 #define OS_OBJECT_OBJC_CLASS_DECL(name) \
209 OS_OBJC_CLASS_DECL(OS_OBJECT_CLASS(name))
210 #define OS_OBJECT_OBJC_CLASS(name) \
211 OS_OBJC_CLASS(OS_OBJECT_CLASS(name))
212 #define DISPATCH_OBJC_CLASS_DECL(name) \
213 OS_OBJC_CLASS_DECL(DISPATCH_CLASS(name))
214 #define DISPATCH_OBJC_CLASS(name) \
215 OS_OBJC_CLASS(DISPATCH_CLASS(name))
216
217 OS_OBJECT_OBJC_CLASS_DECL(object);
218 DISPATCH_OBJC_CLASS_DECL(object);
219
220 // ObjC toll-free bridging, keep in sync with libdispatch.order file
221 #define DISPATCH_OBJECT_TFB(f, o, ...) \
222 if (slowpath((uintptr_t)((o)._os_obj->os_obj_isa) & 1) || \
223 slowpath((Class)((o)._os_obj->os_obj_isa) < \
224 DISPATCH_OBJC_CLASS(object)) || \
225 slowpath((Class)((o)._os_obj->os_obj_isa) >= \
226 OS_OBJECT_OBJC_CLASS(object))) { \
227 return f((o), ##__VA_ARGS__); \
228 }
229
230 id _dispatch_objc_alloc(Class cls, size_t size);
231 void _dispatch_objc_retain(dispatch_object_t dou);
232 void _dispatch_objc_release(dispatch_object_t dou);
233 void _dispatch_objc_set_context(dispatch_object_t dou, void *context);
234 void *_dispatch_objc_get_context(dispatch_object_t dou);
235 void _dispatch_objc_set_finalizer_f(dispatch_object_t dou,
236 dispatch_function_t finalizer);
237 void _dispatch_objc_set_target_queue(dispatch_object_t dou,
238 dispatch_queue_t queue);
239 void _dispatch_objc_suspend(dispatch_object_t dou);
240 void _dispatch_objc_resume(dispatch_object_t dou);
241 size_t _dispatch_objc_debug(dispatch_object_t dou, char* buf, size_t bufsiz);
242
243 #if __OBJC2__
244 @interface NSObject (DISPATCH_CONCAT(_,DISPATCH_CLASS(object)))
245 - (void)_setContext:(void*)context;
246 - (void*)_getContext;
247 - (void)_setFinalizer:(dispatch_function_t)finalizer;
248 - (void)_setTargetQueue:(dispatch_queue_t)queue;
249 - (void)_suspend;
250 - (void)_resume;
251 @end
252 #endif // __OBJC2__
253 #else // USE_OBJC
254 #define DISPATCH_OBJECT_TFB(f, o, ...)
255 #endif // USE_OBJC
256
257 #pragma mark -
258 #pragma mark _os_object_s
259
260 /*
261 * Low level _os_atomic_refcnt_* actions
262 *
263 * _os_atomic_refcnt_inc2o(o, f):
264 * performs a refcount increment and returns the new refcount value
265 *
266 * _os_atomic_refcnt_dec2o(o, f):
267 * performs a refcount decrement and returns the new refcount value
268 *
269 * _os_atomic_refcnt_dispose_barrier2o(o, f):
270 * a barrier to perform prior to tearing down an object when the refcount
271 * reached -1.
272 */
273 #define _os_atomic_refcnt_perform2o(o, f, op, m) ({ \
274 typeof(o) _o = (o); \
275 int _ref_cnt = _o->f; \
276 if (fastpath(_ref_cnt != _OS_OBJECT_GLOBAL_REFCNT)) { \
277 _ref_cnt = dispatch_atomic_##op##2o(_o, f, m); \
278 } \
279 _ref_cnt; \
280 })
281
282 #define _os_atomic_refcnt_inc2o(o, m) \
283 _os_atomic_refcnt_perform2o(o, m, inc, relaxed)
284
285 #define _os_atomic_refcnt_dec2o(o, m) \
286 _os_atomic_refcnt_perform2o(o, m, dec, release)
287
288 #define _os_atomic_refcnt_dispose_barrier2o(o, m) \
289 (void)dispatch_atomic_load2o(o, m, acquire)
290
291
292 /*
293 * Higher level _os_object_{x,}refcnt_* actions
294 *
295 * _os_atomic_{x,}refcnt_inc(o):
296 * increment the external (resp. internal) refcount and
297 * returns the new refcount value
298 *
299 * _os_atomic_{x,}refcnt_dec(o):
300 * decrement the external (resp. internal) refcount and
301 * returns the new refcount value
302 *
303 * _os_atomic_{x,}refcnt_dispose_barrier(o):
304 * performs the pre-teardown barrier for the external
305 * (resp. internal) refcount
306 *
307 */
308 #define _os_object_xrefcnt_inc(o) \
309 _os_atomic_refcnt_inc2o(o, os_obj_xref_cnt)
310
311 #define _os_object_xrefcnt_dec(o) \
312 _os_atomic_refcnt_dec2o(o, os_obj_xref_cnt)
313
314 #define _os_object_xrefcnt_dispose_barrier(o) \
315 _os_atomic_refcnt_dispose_barrier2o(o, os_obj_xref_cnt)
316
317 #define _os_object_refcnt_inc(o) \
318 _os_atomic_refcnt_inc2o(o, os_obj_ref_cnt)
319
320 #define _os_object_refcnt_dec(o) \
321 _os_atomic_refcnt_dec2o(o, os_obj_ref_cnt)
322
323 #define _os_object_refcnt_dispose_barrier(o) \
324 _os_atomic_refcnt_dispose_barrier2o(o, os_obj_ref_cnt)
325
326 typedef struct _os_object_class_s {
327 _OS_OBJECT_CLASS_HEADER();
328 } _os_object_class_s;
329
330 typedef struct _os_object_s {
331 _OS_OBJECT_HEADER(
332 const _os_object_class_s *os_obj_isa,
333 os_obj_ref_cnt,
334 os_obj_xref_cnt);
335 } _os_object_s;
336
337 void _os_object_init(void);
338 unsigned long _os_object_retain_count(_os_object_t obj);
339 bool _os_object_retain_weak(_os_object_t obj);
340 bool _os_object_allows_weak_reference(_os_object_t obj);
341 void _os_object_dispose(_os_object_t obj);
342 void _os_object_xref_dispose(_os_object_t obj);
343
344 #endif // __DISPATCH_OBJECT_INTERNAL__