]> git.saurik.com Git - apple/libdispatch.git/blob - src/object.m
ea696228cdf6b7bbe3b8bea072aed2942f99e20f
[apple/libdispatch.git] / src / object.m
1 /*
2 * Copyright (c) 2011 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 #include "internal.h"
22
23 #if USE_OBJC
24
25 #if !__OBJC2__
26 #error "Cannot build with legacy ObjC runtime"
27 #endif
28 #if _OS_OBJECT_OBJC_ARC
29 #error "Cannot build with ARC"
30 #endif
31
32 #include <objc/runtime.h>
33 #include <objc/objc-internal.h>
34 #include <objc/objc-exception.h>
35
36 #pragma mark -
37 #pragma mark _os_object_gc
38
39 #if __OBJC_GC__
40 #include <objc/objc-auto.h>
41 #include <auto_zone.h>
42
43 static dispatch_once_t _os_object_gc_pred;
44 static bool _os_object_have_gc;
45 static malloc_zone_t *_os_object_gc_zone;
46
47 static void
48 _os_object_gc_init(void *ctxt DISPATCH_UNUSED)
49 {
50 _os_object_have_gc = objc_collectingEnabled();
51 if (slowpath(_os_object_have_gc)) {
52 _os_object_gc_zone = objc_collectableZone();
53 }
54 }
55
56 static _os_object_t
57 _os_object_make_uncollectable(_os_object_t obj)
58 {
59 dispatch_once_f(&_os_object_gc_pred, NULL, _os_object_gc_init);
60 if (slowpath(_os_object_have_gc)) {
61 auto_zone_retain(_os_object_gc_zone, obj);
62 }
63 return obj;
64 }
65
66 static _os_object_t
67 _os_object_make_collectable(_os_object_t obj)
68 {
69 dispatch_once_f(&_os_object_gc_pred, NULL, _os_object_gc_init);
70 if (slowpath(_os_object_have_gc)) {
71 auto_zone_release(_os_object_gc_zone, obj);
72 }
73 return obj;
74 }
75 #else
76 #define _os_object_make_uncollectable(obj) (obj)
77 #define _os_object_make_collectable(obj) (obj)
78 #endif // __OBJC_GC__
79
80 #pragma mark -
81 #pragma mark _os_object_t
82
83 void
84 _os_object_init(void)
85 {
86 return _objc_init();
87 }
88
89 _os_object_t
90 _os_object_alloc(const void *_cls, size_t size)
91 {
92 Class cls = _cls;
93 _os_object_t obj;
94 dispatch_assert(size >= sizeof(struct _os_object_s));
95 size -= sizeof(((struct _os_object_s *)NULL)->os_obj_isa);
96 if (!cls) cls = [OS_OBJECT_CLASS(object) class];
97 while (!fastpath(obj = class_createInstance(cls, size))) {
98 sleep(1); // Temporary resource shortage
99 }
100 return _os_object_make_uncollectable(obj);
101 }
102
103 void
104 _os_object_dealloc(_os_object_t obj)
105 {
106 [_os_object_make_collectable(obj) dealloc];
107 }
108
109 void
110 _os_object_xref_dispose(_os_object_t obj)
111 {
112 [obj _xref_dispose];
113 }
114
115 void
116 _os_object_dispose(_os_object_t obj)
117 {
118 [obj _dispose];
119 }
120
121 #pragma mark -
122 #pragma mark _os_object
123
124 @implementation OS_OBJECT_CLASS(object)
125
126 -(id)retain {
127 return _os_object_retain(self);
128 }
129
130 -(oneway void)release {
131 return _os_object_release(self);
132 }
133
134 -(NSUInteger)retainCount {
135 return _os_object_retain_count(self);
136 }
137
138 -(BOOL)retainWeakReference {
139 return _os_object_retain_weak(self);
140 }
141
142 -(BOOL)allowsWeakReference {
143 return _os_object_allows_weak_reference(self);
144 }
145
146 - (void)_xref_dispose {
147 return _os_object_release_internal(self);
148 }
149
150 - (void)_dispose {
151 return _os_object_dealloc(self);
152 }
153
154 @end
155
156 #pragma mark -
157 #pragma mark _dispatch_object
158
159 #include <Foundation/NSString.h>
160
161 // Force non-lazy class realization rdar://10640168
162 #define DISPATCH_OBJC_LOAD() + (void)load {}
163
164 @implementation DISPATCH_CLASS(object)
165
166 - (id)init {
167 self = [super init];
168 [self release];
169 self = nil;
170 return self;
171 }
172
173 - (void)_xref_dispose {
174 _dispatch_xref_dispose(self);
175 [super _xref_dispose];
176 }
177
178 - (void)_dispose {
179 return _dispatch_dispose(self); // calls _os_object_dealloc()
180 }
181
182 - (NSString *)debugDescription {
183 Class nsstring = objc_lookUpClass("NSString");
184 if (!nsstring) return nil;
185 char buf[4096];
186 dx_debug((struct dispatch_object_s *)self, buf, sizeof(buf));
187 return [nsstring stringWithFormat:
188 [nsstring stringWithUTF8String:"<%s: %s>"],
189 class_getName([self class]), buf];
190 }
191
192 @end
193
194 @implementation DISPATCH_CLASS(queue)
195 DISPATCH_OBJC_LOAD()
196
197 - (NSString *)description {
198 Class nsstring = objc_lookUpClass("NSString");
199 if (!nsstring) return nil;
200 return [nsstring stringWithFormat:
201 [nsstring stringWithUTF8String:"<%s: %s[%p]>"],
202 class_getName([self class]), dispatch_queue_get_label(self), self];
203 }
204
205 @end
206
207 @implementation DISPATCH_CLASS(source)
208 DISPATCH_OBJC_LOAD()
209
210 - (void)_xref_dispose {
211 _dispatch_source_xref_dispose(self);
212 [super _xref_dispose];
213 }
214
215 @end
216
217 #define DISPATCH_CLASS_IMPL(name) \
218 @implementation DISPATCH_CLASS(name) \
219 DISPATCH_OBJC_LOAD() \
220 @end
221
222 DISPATCH_CLASS_IMPL(semaphore)
223 DISPATCH_CLASS_IMPL(group)
224 DISPATCH_CLASS_IMPL(queue_root)
225 DISPATCH_CLASS_IMPL(queue_mgr)
226 DISPATCH_CLASS_IMPL(queue_specific_queue)
227 DISPATCH_CLASS_IMPL(queue_attr)
228 DISPATCH_CLASS_IMPL(io)
229 DISPATCH_CLASS_IMPL(operation)
230 DISPATCH_CLASS_IMPL(disk)
231 DISPATCH_CLASS_IMPL(data)
232
233 #pragma mark -
234 #pragma mark dispatch_autorelease_pool
235
236 #if DISPATCH_COCOA_COMPAT
237
238 void *
239 _dispatch_autorelease_pool_push(void) {
240 return objc_autoreleasePoolPush();
241 }
242
243 void
244 _dispatch_autorelease_pool_pop(void *context) {
245 return objc_autoreleasePoolPop(context);
246 }
247
248 #endif // DISPATCH_COCOA_COMPAT
249
250 #pragma mark -
251 #pragma mark dispatch_client_callout
252
253 // Abort on uncaught exceptions thrown from client callouts rdar://8577499
254 #if DISPATCH_USE_CLIENT_CALLOUT && !__arm__
255 // On platforms with zero-cost exceptions, use a compiler-generated catch-all
256 // exception handler.
257
258 DISPATCH_NORETURN extern void objc_terminate(void);
259
260 #undef _dispatch_client_callout
261 void
262 _dispatch_client_callout(void *ctxt, dispatch_function_t f)
263 {
264 @try {
265 return f(ctxt);
266 }
267 @catch (...) {
268 objc_terminate();
269 }
270 }
271
272 #undef _dispatch_client_callout2
273 void
274 _dispatch_client_callout2(void *ctxt, size_t i, void (*f)(void *, size_t))
275 {
276 @try {
277 return f(ctxt, i);
278 }
279 @catch (...) {
280 objc_terminate();
281 }
282 }
283
284 #endif // DISPATCH_USE_CLIENT_CALLOUT
285
286 #endif // USE_OBJC