2 * Copyright (c) 2011-2013 Apple Inc. All rights reserved.
4 * @APPLE_APACHE_LICENSE_HEADER_START@
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 * @APPLE_APACHE_LICENSE_HEADER_END@
26 #error "Cannot build with legacy ObjC runtime"
28 #if _OS_OBJECT_OBJC_ARC
29 #error "Cannot build with ARC"
32 #include <objc/objc-internal.h>
33 #include <objc/objc-exception.h>
36 #pragma mark _os_object_gc
39 #include <objc/objc-auto.h>
40 #include <auto_zone.h>
42 static bool _os_object_have_gc;
43 static malloc_zone_t *_os_object_gc_zone;
46 _os_object_gc_init(void)
48 _os_object_have_gc = objc_collectingEnabled();
49 if (slowpath(_os_object_have_gc)) {
50 _os_object_gc_zone = objc_collectableZone();
55 _os_object_make_uncollectable(_os_object_t obj)
57 if (slowpath(_os_object_have_gc)) {
58 auto_zone_retain(_os_object_gc_zone, obj);
64 _os_object_make_collectable(_os_object_t obj)
66 if (slowpath(_os_object_have_gc)) {
67 auto_zone_release(_os_object_gc_zone, obj);
72 #define _os_objc_gc_retain(obj) \
73 if (slowpath(_os_object_have_gc)) { \
74 return auto_zone_retain(_os_object_gc_zone, obj); \
77 #define _os_objc_gc_release(obj) \
78 if (slowpath(_os_object_have_gc)) { \
79 return (void)auto_zone_release(_os_object_gc_zone, obj); \
83 #define _os_object_gc_init()
84 #define _os_object_make_uncollectable(obj) (obj)
85 #define _os_object_make_collectable(obj) (obj)
86 #define _os_objc_gc_retain(obj)
87 #define _os_objc_gc_release(obj)
91 #pragma mark _os_object_t
94 _os_objc_alloc(Class cls, size_t size)
97 size -= sizeof(((struct _os_object_s *)NULL)->os_obj_isa);
98 while (!fastpath(obj = class_createInstance(cls, size))) {
99 _dispatch_temporary_resource_shortage();
105 _os_object_init(void)
108 _os_object_gc_init();
112 _os_object_alloc_realized(const void *cls, size_t size)
114 dispatch_assert(size >= sizeof(struct _os_object_s));
115 return _os_object_make_uncollectable(_os_objc_alloc(cls, size));
119 _os_object_alloc(const void *_cls, size_t size)
121 dispatch_assert(size >= sizeof(struct _os_object_s));
122 Class cls = _cls ? [(id)_cls class] : [OS_OBJECT_CLASS(object) class];
123 return _os_object_make_uncollectable(_os_objc_alloc(cls, size));
127 _os_object_dealloc(_os_object_t obj)
129 [_os_object_make_collectable(obj) dealloc];
133 _os_object_xref_dispose(_os_object_t obj)
139 _os_object_dispose(_os_object_t obj)
145 #pragma mark _os_object
147 @implementation OS_OBJECT_CLASS(object)
150 return _os_object_retain(self);
153 -(oneway void)release {
154 return _os_object_release(self);
157 -(NSUInteger)retainCount {
158 return _os_object_retain_count(self);
161 -(BOOL)retainWeakReference {
162 return _os_object_retain_weak(self);
165 -(BOOL)allowsWeakReference {
166 return _os_object_allows_weak_reference(self);
169 - (void)_xref_dispose {
170 return _os_object_release_internal(self);
174 return _os_object_dealloc(self);
180 #pragma mark _dispatch_objc
182 #include <Foundation/NSString.h>
185 _dispatch_objc_alloc(Class cls, size_t size)
187 return _os_objc_alloc(cls, size);
191 _dispatch_objc_retain(dispatch_object_t dou)
193 _os_objc_gc_retain(dou);
194 return (void)[dou retain];
198 _dispatch_objc_release(dispatch_object_t dou)
200 _os_objc_gc_release(dou);
201 return [dou release];
205 _dispatch_objc_set_context(dispatch_object_t dou, void *context)
207 return [dou _setContext:context];
211 _dispatch_objc_get_context(dispatch_object_t dou)
213 return [dou _getContext];
217 _dispatch_objc_set_finalizer_f(dispatch_object_t dou,
218 dispatch_function_t finalizer)
220 return [dou _setFinalizer:finalizer];
224 _dispatch_objc_set_target_queue(dispatch_object_t dou, dispatch_queue_t queue)
226 return [dou _setTargetQueue:queue];
230 _dispatch_objc_suspend(dispatch_object_t dou)
232 return [dou _suspend];
236 _dispatch_objc_resume(dispatch_object_t dou)
238 return [dou _resume];
242 _dispatch_objc_debug(dispatch_object_t dou, char* buf, size_t bufsiz)
244 NSUInteger offset = 0;
245 NSString *desc = [dou debugDescription];
246 [desc getBytes:buf maxLength:bufsiz-1 usedLength:&offset
247 encoding:NSUTF8StringEncoding options:0
248 range:NSMakeRange(0, [desc length]) remainingRange:NULL];
249 if (offset) buf[offset] = 0;
254 #pragma mark _dispatch_object
256 // Force non-lazy class realization rdar://10640168
257 #define DISPATCH_OBJC_LOAD() + (void)load {}
259 @implementation DISPATCH_CLASS(object)
268 - (void)_xref_dispose {
269 _dispatch_xref_dispose(self);
270 [super _xref_dispose];
274 return _dispatch_dispose(self); // calls _os_object_dealloc()
277 - (NSString *)debugDescription {
278 Class nsstring = objc_lookUpClass("NSString");
279 if (!nsstring) return nil;
281 struct dispatch_object_s *obj = (struct dispatch_object_s *)self;
282 if (obj->do_vtable->do_debug) {
283 dx_debug(obj, buf, sizeof(buf));
285 strlcpy(buf, dx_kind(obj), sizeof(buf));
287 return [nsstring stringWithFormat:
288 [nsstring stringWithUTF8String:"<%s: %s>"],
289 class_getName([self class]), buf];
294 @implementation DISPATCH_CLASS(queue)
297 - (NSString *)description {
298 Class nsstring = objc_lookUpClass("NSString");
299 if (!nsstring) return nil;
300 return [nsstring stringWithFormat:
301 [nsstring stringWithUTF8String:"<%s: %s[%p]>"],
302 class_getName([self class]), dispatch_queue_get_label(self), self];
307 @implementation DISPATCH_CLASS(source)
310 - (void)_xref_dispose {
311 _dispatch_source_xref_dispose(self);
312 [super _xref_dispose];
317 @implementation DISPATCH_CLASS(queue_runloop)
320 - (void)_xref_dispose {
321 _dispatch_runloop_queue_xref_dispose(self);
322 [super _xref_dispose];
327 #define DISPATCH_CLASS_IMPL(name) \
328 @implementation DISPATCH_CLASS(name) \
329 DISPATCH_OBJC_LOAD() \
332 DISPATCH_CLASS_IMPL(semaphore)
333 DISPATCH_CLASS_IMPL(group)
334 DISPATCH_CLASS_IMPL(queue_root)
335 DISPATCH_CLASS_IMPL(queue_mgr)
336 DISPATCH_CLASS_IMPL(queue_specific_queue)
337 DISPATCH_CLASS_IMPL(queue_attr)
338 DISPATCH_CLASS_IMPL(mach)
339 DISPATCH_CLASS_IMPL(mach_msg)
340 DISPATCH_CLASS_IMPL(io)
341 DISPATCH_CLASS_IMPL(operation)
342 DISPATCH_CLASS_IMPL(disk)
345 #pragma mark dispatch_autorelease_pool
347 #if DISPATCH_COCOA_COMPAT
350 _dispatch_autorelease_pool_push(void) {
351 return objc_autoreleasePoolPush();
355 _dispatch_autorelease_pool_pop(void *context) {
356 return objc_autoreleasePoolPop(context);
359 #endif // DISPATCH_COCOA_COMPAT
362 #pragma mark dispatch_client_callout
364 // Abort on uncaught exceptions thrown from client callouts rdar://8577499
365 #if DISPATCH_USE_CLIENT_CALLOUT && !__arm__
366 // On platforms with zero-cost exceptions, use a compiler-generated catch-all
367 // exception handler.
369 DISPATCH_NORETURN extern void objc_terminate(void);
371 #undef _dispatch_client_callout
373 _dispatch_client_callout(void *ctxt, dispatch_function_t f)
383 #undef _dispatch_client_callout2
385 _dispatch_client_callout2(void *ctxt, size_t i, void (*f)(void *, size_t))
395 #undef _dispatch_client_callout3
397 _dispatch_client_callout3(void *ctxt, dispatch_data_t region, size_t offset,
398 const void *buffer, size_t size, dispatch_data_applier_function_t f)
401 return f(ctxt, region, offset, buffer, size);
408 #undef _dispatch_client_callout4
410 _dispatch_client_callout4(void *ctxt, dispatch_mach_reason_t reason,
411 dispatch_mach_msg_t dmsg, mach_error_t error,
412 dispatch_mach_handler_function_t f)
415 return f(ctxt, reason, dmsg, error);
422 #endif // DISPATCH_USE_CLIENT_CALLOUT