2 * Copyright (c) 2011 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/runtime.h>
33 #include <objc/objc-internal.h>
34 #include <objc/objc-exception.h>
37 #pragma mark _os_object_gc
40 #include <objc/objc-auto.h>
41 #include <auto_zone.h>
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;
48 _os_object_gc_init(void *ctxt DISPATCH_UNUSED)
50 _os_object_have_gc = objc_collectingEnabled();
51 if (slowpath(_os_object_have_gc)) {
52 _os_object_gc_zone = objc_collectableZone();
57 _os_object_make_uncollectable(_os_object_t obj)
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);
67 _os_object_make_collectable(_os_object_t obj)
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);
76 #define _os_object_make_uncollectable(obj) (obj)
77 #define _os_object_make_collectable(obj) (obj)
81 #pragma mark _os_object_t
90 _os_object_alloc(const void *_cls, size_t size)
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
100 return _os_object_make_uncollectable(obj);
104 _os_object_dealloc(_os_object_t obj)
106 [_os_object_make_collectable(obj) dealloc];
110 _os_object_xref_dispose(_os_object_t obj)
116 _os_object_dispose(_os_object_t obj)
122 #pragma mark _os_object
124 @implementation OS_OBJECT_CLASS(object)
127 return _os_object_retain(self);
130 -(oneway void)release {
131 return _os_object_release(self);
134 -(NSUInteger)retainCount {
135 return _os_object_retain_count(self);
138 -(BOOL)retainWeakReference {
139 return _os_object_retain_weak(self);
142 -(BOOL)allowsWeakReference {
143 return _os_object_allows_weak_reference(self);
146 - (void)_xref_dispose {
147 return _os_object_release_internal(self);
151 return _os_object_dealloc(self);
157 #pragma mark _dispatch_object
159 #include <Foundation/NSString.h>
161 // Force non-lazy class realization rdar://10640168
162 #define DISPATCH_OBJC_LOAD() + (void)load {}
164 @implementation DISPATCH_CLASS(object)
173 - (void)_xref_dispose {
174 _dispatch_xref_dispose(self);
175 [super _xref_dispose];
179 return _dispatch_dispose(self); // calls _os_object_dealloc()
182 - (NSString *)debugDescription {
183 Class nsstring = objc_lookUpClass("NSString");
184 if (!nsstring) return nil;
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];
194 @implementation DISPATCH_CLASS(queue)
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];
207 @implementation DISPATCH_CLASS(source)
210 - (void)_xref_dispose {
211 _dispatch_source_xref_dispose(self);
212 [super _xref_dispose];
217 #define DISPATCH_CLASS_IMPL(name) \
218 @implementation DISPATCH_CLASS(name) \
219 DISPATCH_OBJC_LOAD() \
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)
234 #pragma mark dispatch_autorelease_pool
236 #if DISPATCH_COCOA_COMPAT
239 _dispatch_autorelease_pool_push(void) {
240 return objc_autoreleasePoolPush();
244 _dispatch_autorelease_pool_pop(void *context) {
245 return objc_autoreleasePoolPop(context);
248 #endif // DISPATCH_COCOA_COMPAT
251 #pragma mark dispatch_client_callout
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.
258 DISPATCH_NORETURN extern void objc_terminate(void);
260 #undef _dispatch_client_callout
262 _dispatch_client_callout(void *ctxt, dispatch_function_t f)
272 #undef _dispatch_client_callout2
274 _dispatch_client_callout2(void *ctxt, size_t i, void (*f)(void *, size_t))
284 #endif // DISPATCH_USE_CLIENT_CALLOUT