]> git.saurik.com Git - apple/libdispatch.git/blob - src/object_internal.h
libdispatch-339.1.9.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 #if USE_OBJC
44 #define DISPATCH_CLASS(name) OS_OBJECT_CLASS(dispatch_##name)
45 // ObjC classes and dispatch vtables are co-located via linker order and alias
46 // files rdar://10640168
47 #define DISPATCH_VTABLE_SUBCLASS_INSTANCE(name, super, ...) \
48 __attribute__((section("__DATA,__objc_data"), used)) \
49 static const struct { \
50 DISPATCH_VTABLE_HEADER(super); \
51 } DISPATCH_CONCAT(_,DISPATCH_CLASS(name##_vtable)) = { \
52 __VA_ARGS__ \
53 }
54 #else
55 #define DISPATCH_VTABLE_SUBCLASS_INSTANCE(name, super, ...) \
56 DISPATCH_CONST_STRUCT_INSTANCE(dispatch_##super##_vtable_s, \
57 _dispatch_##name##_vtable, \
58 ._os_obj_xref_dispose = _dispatch_xref_dispose, \
59 ._os_obj_dispose = _dispatch_dispose, \
60 __VA_ARGS__)
61 #endif // USE_OBJC
62
63 #define DISPATCH_SUBCLASS_DECL(name, super) \
64 DISPATCH_DECL_SUBCLASS_INTERFACE(dispatch_##name, super) \
65 struct dispatch_##name##_s; \
66 extern DISPATCH_CONST_STRUCT_DECL(dispatch_##name##_vtable_s, \
67 _dispatch_##name##_vtable, \
68 { \
69 _OS_OBJECT_CLASS_HEADER(); \
70 DISPATCH_VTABLE_HEADER(name); \
71 })
72 #define DISPATCH_CLASS_DECL(name) DISPATCH_SUBCLASS_DECL(name, dispatch_object)
73 #define DISPATCH_INTERNAL_SUBCLASS_DECL(name, super) \
74 DISPATCH_DECL_INTERNAL_SUBCLASS(dispatch_##name, dispatch_##super); \
75 DISPATCH_DECL_SUBCLASS_INTERFACE(dispatch_##name, dispatch_##super) \
76 extern DISPATCH_CONST_STRUCT_DECL(dispatch_##super##_vtable_s, \
77 _dispatch_##name##_vtable)
78 #define DISPATCH_VTABLE_INSTANCE(name, ...) \
79 DISPATCH_VTABLE_SUBCLASS_INSTANCE(name, name, __VA_ARGS__)
80 #define DISPATCH_VTABLE(name) &_dispatch_##name##_vtable
81
82 #if !TARGET_OS_WIN32
83 #define DISPATCH_VTABLE_HEADER(x) \
84 unsigned long const do_type; \
85 const char *const do_kind; \
86 size_t (*const do_debug)(struct dispatch_##x##_s *, char *, size_t); \
87 void (*const do_invoke)(struct dispatch_##x##_s *); \
88 unsigned long (*const do_probe)(struct dispatch_##x##_s *); \
89 void (*const do_dispose)(struct dispatch_##x##_s *);
90 #else
91 // Cannot be const on Win32 because we initialize at runtime.
92 #define DISPATCH_VTABLE_HEADER(x) \
93 unsigned long do_type; \
94 const char *do_kind; \
95 size_t (*do_debug)(struct dispatch_##x##_s *, char *, size_t); \
96 void (*do_invoke)(struct dispatch_##x##_s *); \
97 unsigned long (*do_probe)(struct dispatch_##x##_s *); \
98 void (*do_dispose)(struct dispatch_##x##_s *);
99 #endif
100
101 #define dx_type(x) (x)->do_vtable->do_type
102 #define dx_metatype(x) ((x)->do_vtable->do_type & _DISPATCH_META_TYPE_MASK)
103 #define dx_kind(x) (x)->do_vtable->do_kind
104 #define dx_debug(x, y, z) (x)->do_vtable->do_debug((x), (y), (z))
105 #define dx_dispose(x) (x)->do_vtable->do_dispose(x)
106 #define dx_invoke(x) (x)->do_vtable->do_invoke(x)
107 #define dx_probe(x) (x)->do_vtable->do_probe(x)
108
109 #define DISPATCH_STRUCT_HEADER(x) \
110 _OS_OBJECT_HEADER( \
111 const struct dispatch_##x##_vtable_s *do_vtable, \
112 do_ref_cnt, \
113 do_xref_cnt); \
114 struct dispatch_##x##_s *volatile do_next; \
115 struct dispatch_queue_s *do_targetq; \
116 void *do_ctxt; \
117 void *do_finalizer; \
118 unsigned int do_suspend_cnt;
119
120 #define DISPATCH_OBJECT_GLOBAL_REFCNT _OS_OBJECT_GLOBAL_REFCNT
121 // "word and bit" must be a power of two to be safely subtracted
122 #define DISPATCH_OBJECT_SUSPEND_LOCK 1u
123 #define DISPATCH_OBJECT_SUSPEND_INTERVAL 2u
124 #define DISPATCH_OBJECT_SUSPENDED(x) \
125 ((x)->do_suspend_cnt >= DISPATCH_OBJECT_SUSPEND_INTERVAL)
126 #ifdef __LP64__
127 // the bottom nibble must not be zero, the rest of the bits should be random
128 // we sign extend the 64-bit version so that a better instruction encoding is
129 // generated on Intel
130 #define DISPATCH_OBJECT_LISTLESS ((void *)0xffffffff89abcdef)
131 #else
132 #define DISPATCH_OBJECT_LISTLESS ((void *)0x89abcdef)
133 #endif
134
135 enum {
136 _DISPATCH_CONTINUATION_TYPE = 0x00000, // meta-type for continuations
137 _DISPATCH_QUEUE_TYPE = 0x10000, // meta-type for queues
138 _DISPATCH_SOURCE_TYPE = 0x20000, // meta-type for sources
139 _DISPATCH_SEMAPHORE_TYPE = 0x30000, // meta-type for semaphores
140 _DISPATCH_NODE_TYPE = 0x40000, // meta-type for data node
141 _DISPATCH_IO_TYPE = 0x50000, // meta-type for io channels
142 _DISPATCH_OPERATION_TYPE = 0x60000, // meta-type for io operations
143 _DISPATCH_DISK_TYPE = 0x70000, // meta-type for io disks
144 _DISPATCH_META_TYPE_MASK = 0xfff0000, // mask for object meta-types
145 _DISPATCH_ATTR_TYPE = 0x10000000, // meta-type for attributes
146
147 DISPATCH_CONTINUATION_TYPE = _DISPATCH_CONTINUATION_TYPE,
148
149 DISPATCH_DATA_TYPE = 1 | _DISPATCH_NODE_TYPE,
150 DISPATCH_MACH_MSG_TYPE = 2 | _DISPATCH_NODE_TYPE,
151
152 DISPATCH_IO_TYPE = _DISPATCH_IO_TYPE,
153 DISPATCH_OPERATION_TYPE = _DISPATCH_OPERATION_TYPE,
154 DISPATCH_DISK_TYPE = _DISPATCH_DISK_TYPE,
155
156 DISPATCH_QUEUE_ATTR_TYPE = _DISPATCH_QUEUE_TYPE |_DISPATCH_ATTR_TYPE,
157
158 DISPATCH_QUEUE_TYPE = 1 | _DISPATCH_QUEUE_TYPE,
159 DISPATCH_QUEUE_ROOT_TYPE = 2 | _DISPATCH_QUEUE_TYPE,
160 DISPATCH_QUEUE_MGR_TYPE = 3 | _DISPATCH_QUEUE_TYPE,
161 DISPATCH_QUEUE_SPECIFIC_TYPE = 4 | _DISPATCH_QUEUE_TYPE,
162
163 DISPATCH_SEMAPHORE_TYPE = 1 | _DISPATCH_SEMAPHORE_TYPE,
164 DISPATCH_GROUP_TYPE = 2 | _DISPATCH_SEMAPHORE_TYPE,
165
166 DISPATCH_SOURCE_KEVENT_TYPE = 1 | _DISPATCH_SOURCE_TYPE,
167 DISPATCH_MACH_CHANNEL_TYPE = 2 | _DISPATCH_SOURCE_TYPE,
168 };
169
170 DISPATCH_SUBCLASS_DECL(object, object);
171 struct dispatch_object_s {
172 DISPATCH_STRUCT_HEADER(object);
173 };
174
175 size_t _dispatch_object_debug_attr(dispatch_object_t dou, char* buf,
176 size_t bufsiz);
177 void *_dispatch_alloc(const void *vtable, size_t size);
178 void _dispatch_retain(dispatch_object_t dou);
179 void _dispatch_release(dispatch_object_t dou);
180 void _dispatch_xref_dispose(dispatch_object_t dou);
181 void _dispatch_dispose(dispatch_object_t dou);
182 #if DISPATCH_COCOA_COMPAT
183 void *_dispatch_autorelease_pool_push(void);
184 void _dispatch_autorelease_pool_pop(void *context);
185 #endif
186
187 #if USE_OBJC
188 #include <objc/runtime.h>
189
190 #define OS_OBJC_CLASS_SYMBOL(name) \
191 DISPATCH_CONCAT(OBJC_CLASS_$_,name)
192 #define OS_OBJC_CLASS_DECL(name) \
193 extern void *OS_OBJC_CLASS_SYMBOL(name)
194 #define OS_OBJC_CLASS(name) \
195 ((Class)&OS_OBJC_CLASS_SYMBOL(name))
196 #define OS_OBJECT_OBJC_CLASS_DECL(name) \
197 OS_OBJC_CLASS_DECL(OS_OBJECT_CLASS(name))
198 #define OS_OBJECT_OBJC_CLASS(name) \
199 OS_OBJC_CLASS(OS_OBJECT_CLASS(name))
200 #define DISPATCH_OBJC_CLASS_DECL(name) \
201 OS_OBJC_CLASS_DECL(DISPATCH_CLASS(name))
202 #define DISPATCH_OBJC_CLASS(name) \
203 OS_OBJC_CLASS(DISPATCH_CLASS(name))
204
205 OS_OBJECT_OBJC_CLASS_DECL(object);
206 DISPATCH_OBJC_CLASS_DECL(object);
207
208 // ObjC toll-free bridging, keep in sync with libdispatch.order file
209 #define DISPATCH_OBJECT_TFB(f, o, ...) \
210 if (slowpath((uintptr_t)((o)._os_obj->os_obj_isa) & 1) || \
211 slowpath((Class)((o)._os_obj->os_obj_isa) < \
212 DISPATCH_OBJC_CLASS(object)) || \
213 slowpath((Class)((o)._os_obj->os_obj_isa) >= \
214 OS_OBJECT_OBJC_CLASS(object))) { \
215 return f((o), ##__VA_ARGS__); \
216 }
217
218 id _dispatch_objc_alloc(Class cls, size_t size);
219 void _dispatch_objc_retain(dispatch_object_t dou);
220 void _dispatch_objc_release(dispatch_object_t dou);
221 void _dispatch_objc_set_context(dispatch_object_t dou, void *context);
222 void *_dispatch_objc_get_context(dispatch_object_t dou);
223 void _dispatch_objc_set_finalizer_f(dispatch_object_t dou,
224 dispatch_function_t finalizer);
225 void _dispatch_objc_set_target_queue(dispatch_object_t dou,
226 dispatch_queue_t queue);
227 void _dispatch_objc_suspend(dispatch_object_t dou);
228 void _dispatch_objc_resume(dispatch_object_t dou);
229 size_t _dispatch_objc_debug(dispatch_object_t dou, char* buf, size_t bufsiz);
230
231 #if __OBJC2__
232 @interface NSObject (DISPATCH_CONCAT(_,DISPATCH_CLASS(object)))
233 - (void)_setContext:(void*)context;
234 - (void*)_getContext;
235 - (void)_setFinalizer:(dispatch_function_t)finalizer;
236 - (void)_setTargetQueue:(dispatch_queue_t)queue;
237 - (void)_suspend;
238 - (void)_resume;
239 @end
240 #endif // __OBJC2__
241 #else // USE_OBJC
242 #define DISPATCH_OBJECT_TFB(f, o, ...)
243 #endif // USE_OBJC
244
245 #pragma mark -
246 #pragma mark _os_object_s
247
248 typedef struct _os_object_class_s {
249 _OS_OBJECT_CLASS_HEADER();
250 } _os_object_class_s;
251
252 typedef struct _os_object_s {
253 _OS_OBJECT_HEADER(
254 const _os_object_class_s *os_obj_isa,
255 os_obj_ref_cnt,
256 os_obj_xref_cnt);
257 } _os_object_s;
258
259 void _os_object_init(void);
260 unsigned long _os_object_retain_count(_os_object_t obj);
261 bool _os_object_retain_weak(_os_object_t obj);
262 bool _os_object_allows_weak_reference(_os_object_t obj);
263 void _os_object_dispose(_os_object_t obj);
264 void _os_object_xref_dispose(_os_object_t obj);
265
266 #endif // __DISPATCH_OBJECT_INTERNAL__