]> git.saurik.com Git - apple/cf.git/blob - CFRuntime.h
CF-476.13.tar.gz
[apple/cf.git] / CFRuntime.h
1 /*
2 * Copyright (c) 2008 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23 /* CFRuntime.h
24 Copyright (c) 1999-2007, Apple Inc. All rights reserved.
25 */
26
27 #if !defined(__COREFOUNDATION_CFRUNTIME__)
28 #define __COREFOUNDATION_CFRUNTIME__ 1
29
30 #include <CoreFoundation/CFBase.h>
31 #include <CoreFoundation/CFDictionary.h>
32 #include <stddef.h>
33
34 CF_EXTERN_C_BEGIN
35
36 // GC: until we link against ObjC must use indirect functions. Overridden in CFSetupFoundationBridging
37 extern bool kCFUseCollectableAllocator;
38 extern bool (*__CFObjCIsCollectable)(void *);
39 extern const void* (*__CFObjCAssignIvar)(const void *value, const void *base, const void **slot);
40 extern const void* (*__CFObjCStrongAssign)(const void *value, const void **slot);
41 extern void* (*__CFObjCMemmoveCollectable)(void *dest, const void *src, size_t);
42 extern void (*__CFObjCWriteBarrierRange)(void *, size_t);
43
44 // GC: primitives.
45 // is GC on?
46 #define CF_USING_COLLECTABLE_MEMORY (kCFUseCollectableAllocator)
47 // is GC on and is this the GC allocator?
48 #define CF_IS_COLLECTABLE_ALLOCATOR(allocator) (CF_USING_COLLECTABLE_MEMORY && (NULL == (allocator) || kCFAllocatorSystemDefault == (allocator)))
49 // is this allocated by the collector?
50 #define CF_IS_COLLECTABLE(obj) (__CFObjCIsCollectable ? __CFObjCIsCollectable((void*)obj) : false)
51
52 // XXX_PCB for generational GC support.
53
54 CF_INLINE const void* __CFAssignIvar(CFAllocatorRef allocator, const void *rvalue, const void *base, const void **lvalue) {
55 if (rvalue && CF_IS_COLLECTABLE_ALLOCATOR(allocator))
56 return __CFObjCAssignIvar(rvalue, base, lvalue);
57 else
58 return (*lvalue = rvalue);
59 }
60
61 CF_INLINE const void* __CFStrongAssign(CFAllocatorRef allocator, const void *rvalue, const void **lvalue) {
62 if (rvalue && CF_IS_COLLECTABLE_ALLOCATOR(allocator))
63 return __CFObjCStrongAssign(rvalue, lvalue);
64 else
65 return (*lvalue = rvalue);
66 }
67
68 // Use this form when the base pointer to the object is known.
69 #define CF_WRITE_BARRIER_BASE_ASSIGN(allocator, base, lvalue, rvalue) __CFAssignIvar(allocator, (const void*)rvalue, (const void*)base, (const void**)&(lvalue))
70
71 // Use this form when the base pointer to the object isn't known.
72 #define CF_WRITE_BARRIER_ASSIGN(allocator, lvalue, rvalue) __CFStrongAssign(allocator, (const void*)rvalue, (const void**)&(lvalue))
73
74 // Write-barrier memory move.
75 #define CF_WRITE_BARRIER_MEMMOVE(dst, src, size) __CFObjCMemmoveCollectable(dst, src, size)
76
77 // Used by frameworks to assert they "KNOW WHAT THEY'RE DOING under GC."
78 CF_EXPORT CFAllocatorRef _CFAllocatorCreateGC(CFAllocatorRef allocator, CFAllocatorContext *context);
79
80 // Zero-retain count CFAllocator functions, i.e. memory that will be collected, no dealloc necessary
81 CF_EXPORT void *_CFAllocatorAllocateGC(CFAllocatorRef allocator, CFIndex size, CFOptionFlags hint);
82 CF_EXPORT void *_CFAllocatorReallocateGC(CFAllocatorRef allocator, void *ptr, CFIndex newsize, CFOptionFlags hint);
83 CF_EXPORT void _CFAllocatorDeallocateGC(CFAllocatorRef allocator, void *ptr);
84
85 enum {
86 _kCFRuntimeNotATypeID = 0,
87 _kCFRuntimeScannedObject = (1 << 0),
88 /* _kCFRuntimeUncollectableObject = (1 << 1), No longer used; obsolete. */
89 _kCFRuntimeResourcefulObject = (1 << 2)
90 };
91
92 typedef struct __CFRuntimeClass { // Version 0 struct
93 CFIndex version;
94 const char *className;
95 void (*init)(CFTypeRef cf);
96 CFTypeRef (*copy)(CFAllocatorRef allocator, CFTypeRef cf);
97 #if MAC_OS_X_VERSION_10_2 <= MAC_OS_X_VERSION_MAX_ALLOWED
98 void (*finalize)(CFTypeRef cf);
99 #else
100 void (*dealloc)(CFTypeRef cf);
101 #endif
102 Boolean (*equal)(CFTypeRef cf1, CFTypeRef cf2);
103 CFHashCode (*hash)(CFTypeRef cf);
104 CFStringRef (*copyFormattingDesc)(CFTypeRef cf, CFDictionaryRef formatOptions); // str with retain
105 CFStringRef (*copyDebugDesc)(CFTypeRef cf); // str with retain
106 #if MAC_OS_X_VERSION_10_5 <= MAC_OS_X_VERSION_MAX_ALLOWED
107 #define CF_RECLAIM_AVAILABLE 1
108 void (*reclaim)(CFTypeRef cf);
109 #endif
110 } CFRuntimeClass;
111
112 #define RADAR_5115468_FIXED 1
113
114 /* Note that CF runtime class registration and unregistration is not currently
115 * thread-safe, which should not currently be a problem, as long as unregistration
116 * is done only when valid to do so.
117 */
118
119 CF_EXPORT CFTypeID _CFRuntimeRegisterClass(const CFRuntimeClass * const cls);
120 /* Registers a new class with the CF runtime. Pass in a
121 * pointer to a CFRuntimeClass structure. The pointer is
122 * remembered by the CF runtime -- the structure is NOT
123 * copied.
124 *
125 * - version field must be zero currently.
126 * - className field points to a null-terminated C string
127 * containing only ASCII (0 - 127) characters; this field
128 * may NOT be NULL.
129 * - init field points to a function which classes can use to
130 * apply some generic initialization to instances as they
131 * are created; this function is called by both
132 * _CFRuntimeCreateInstance and _CFRuntimeInitInstance; if
133 * this field is NULL, no function is called; the instance
134 * has been initialized enough that the polymorphic funcs
135 * CFGetTypeID(), CFRetain(), CFRelease(), CFGetRetainCount(),
136 * and CFGetAllocator() are valid on it when the init
137 * function if any is called.
138 * - finalize field points to a function which destroys an
139 * instance when the retain count has fallen to zero; if
140 * this is NULL, finalization does nothing. Note that if
141 * the class-specific functions which create or initialize
142 * instances more fully decide that a half-initialized
143 * instance must be destroyed, the finalize function for
144 * that class has to be able to deal with half-initialized
145 * instances. The finalize function should NOT destroy the
146 * memory for the instance itself; that is done by the
147 * CF runtime after this finalize callout returns.
148 * - equal field points to an equality-testing function; this
149 * field may be NULL, in which case only pointer/reference
150 * equality is performed on instances of this class.
151 * Pointer equality is tested, and the type IDs are checked
152 * for equality, before this function is called (so, the
153 * two instances are not pointer-equal but are of the same
154 * class before this function is called).
155 * NOTE: the equal function must implement an immutable
156 * equality relation, satisfying the reflexive, symmetric,
157 * and transitive properties, and remains the same across
158 * time and immutable operations (that is, if equal(A,B) at
159 * some point, then later equal(A,B) provided neither
160 * A or B has been mutated).
161 * - hash field points to a hash-code-computing function for
162 * instances of this class; this field may be NULL in which
163 * case the pointer value of an instance is converted into
164 * a hash.
165 * NOTE: the hash function and equal function must satisfy
166 * the relationship "equal(A,B) implies hash(A) == hash(B)";
167 * that is, if two instances are equal, their hash codes must
168 * be equal too. (However, the converse is not true!)
169 * - copyFormattingDesc field points to a function returning a
170 * CFStringRef with a human-readable description of the
171 * instance; if this is NULL, the type does not have special
172 * human-readable string-formats.
173 * - copyDebugDesc field points to a function returning a
174 * CFStringRef with a debugging description of the instance;
175 * if this is NULL, a simple description is generated.
176 *
177 * This function returns _kCFRuntimeNotATypeID on failure, or
178 * on success, returns the CFTypeID for the new class. This
179 * CFTypeID is what the class uses to allocate or initialize
180 * instances of the class. It is also returned from the
181 * conventional *GetTypeID() function, which returns the
182 * class's CFTypeID so that clients can compare the
183 * CFTypeID of instances with that of a class.
184 *
185 * The function to compute a human-readable string is very
186 * optional, and is really only interesting for classes,
187 * like strings or numbers, where it makes sense to format
188 * the instance using just its contents.
189 */
190
191 CF_EXPORT const CFRuntimeClass * _CFRuntimeGetClassWithTypeID(CFTypeID typeID);
192 /* Returns the pointer to the CFRuntimeClass which was
193 * assigned the specified CFTypeID.
194 */
195
196 CF_EXPORT void _CFRuntimeUnregisterClassWithTypeID(CFTypeID typeID);
197 /* Unregisters the class with the given type ID. It is
198 * undefined whether type IDs are reused or not (expect
199 * that they will be).
200 *
201 * Whether or not unregistering the class is a good idea or
202 * not is not CF's responsibility. In particular you must
203 * be quite sure all instances are gone, and there are no
204 * valid weak refs to such in other threads.
205 */
206
207 /* All CF "instances" start with this structure. Never refer to
208 * these fields directly -- they are for CF's use and may be added
209 * to or removed or change format without warning. Binary
210 * compatibility for uses of this struct is not guaranteed from
211 * release to release.
212 */
213 typedef struct __CFRuntimeBase {
214 uintptr_t _cfisa;
215 uint8_t _cfinfo[4];
216 #if __LP64__
217 uint32_t _rc;
218 #endif
219 } CFRuntimeBase;
220
221 #if __BIG_ENDIAN__
222 #define INIT_CFRUNTIME_BASE(...) {0, {0, 0, 0, 0x80}}
223 #else
224 #define INIT_CFRUNTIME_BASE(...) {0, {0x80, 0, 0, 0}}
225 #endif
226
227 CF_EXPORT CFTypeRef _CFRuntimeCreateInstance(CFAllocatorRef allocator, CFTypeID typeID, CFIndex extraBytes, unsigned char *category);
228 /* Creates a new CF instance of the class specified by the
229 * given CFTypeID, using the given allocator, and returns it.
230 * If the allocator returns NULL, this function returns NULL.
231 * A CFRuntimeBase structure is initialized at the beginning
232 * of the returned instance. extraBytes is the additional
233 * number of bytes to allocate for the instance (BEYOND that
234 * needed for the CFRuntimeBase). If the specified CFTypeID
235 * is unknown to the CF runtime, this function returns NULL.
236 * No part of the new memory other than base header is
237 * initialized (the extra bytes are not zeroed, for example).
238 * All instances created with this function must be destroyed
239 * only through use of the CFRelease() function -- instances
240 * must not be destroyed by using CFAllocatorDeallocate()
241 * directly, even in the initialization or creation functions
242 * of a class. Pass NULL for the category parameter.
243 */
244
245 CF_EXPORT void _CFRuntimeSetInstanceTypeID(CFTypeRef cf, CFTypeID typeID);
246 /* This function changes the typeID of the given instance.
247 * If the specified CFTypeID is unknown to the CF runtime,
248 * this function does nothing. This function CANNOT be used
249 * to initialize an instance. It is for advanced usages such
250 * as faulting.
251 */
252
253 CF_EXPORT void _CFRuntimeInitStaticInstance(void *memory, CFTypeID typeID);
254 /* This function initializes a memory block to be a constant
255 * (unreleaseable) CF object of the given typeID.
256 * If the specified CFTypeID is unknown to the CF runtime,
257 * this function does nothing. The memory block should
258 * be a chunk of in-binary writeable static memory, and at
259 * least as large as sizeof(CFRuntimeBase) on the platform
260 * the code is being compiled for. The init function of the
261 * CFRuntimeClass is invoked on the memory as well, if the
262 * class has one.
263 */
264 #define CF_HAS_INIT_STATIC_INSTANCE 1
265
266 #if 0
267 // ========================= EXAMPLE =========================
268
269 // Example: EXRange -- a "range" object, which keeps the starting
270 // location and length of the range. ("EX" as in "EXample").
271
272 // ---- API ----
273
274 typedef const struct __EXRange * EXRangeRef;
275
276 CFTypeID EXRangeGetTypeID(void);
277
278 EXRangeRef EXRangeCreate(CFAllocatorRef allocator, uint32_t location, uint32_t length);
279
280 uint32_t EXRangeGetLocation(EXRangeRef rangeref);
281 uint32_t EXRangeGetLength(EXRangeRef rangeref);
282
283
284 // ---- implementation ----
285
286 #include <CoreFoundation/CFBase.h>
287 #include <CoreFoundation/CFString.h>
288
289 struct __EXRange {
290 CFRuntimeBase _base;
291 uint32_t _location;
292 uint32_t _length;
293 };
294
295 static Boolean __EXRangeEqual(CFTypeRef cf1, CFTypeRef cf2) {
296 EXRangeRef rangeref1 = (EXRangeRef)cf1;
297 EXRangeRef rangeref2 = (EXRangeRef)cf2;
298 if (rangeref1->_location != rangeref2->_location) return false;
299 if (rangeref1->_length != rangeref2->_length) return false;
300 return true;
301 }
302
303 static CFHashCode __EXRangeHash(CFTypeRef cf) {
304 EXRangeRef rangeref = (EXRangeRef)cf;
305 return (CFHashCode)(rangeref->_location + rangeref->_length);
306 }
307
308 static CFStringRef __EXRangeCopyFormattingDesc(CFTypeRef cf, CFDictionaryRef formatOpts) {
309 EXRangeRef rangeref = (EXRangeRef)cf;
310 return CFStringCreateWithFormat(CFGetAllocator(rangeref), formatOpts,
311 CFSTR("[%u, %u)"),
312 rangeref->_location,
313 rangeref->_location + rangeref->_length);
314 }
315
316 static CFStringRef __EXRangeCopyDebugDesc(CFTypeRef cf) {
317 EXRangeRef rangeref = (EXRangeRef)cf;
318 return CFStringCreateWithFormat(CFGetAllocator(rangeref), NULL,
319 CFSTR("<EXRange %p [%p]>{loc = %u, len = %u}"),
320 rangeref,
321 CFGetAllocator(rangeref),
322 rangeref->_location,
323 rangeref->_length);
324 }
325
326 static void __EXRangeEXRangeFinalize(CFTypeRef cf) {
327 EXRangeRef rangeref = (EXRangeRef)cf;
328 // nothing to finalize
329 }
330
331 static CFTypeID _kEXRangeID = _kCFRuntimeNotATypeID;
332
333 static CFRuntimeClass _kEXRangeClass = {0};
334
335 /* Something external to this file is assumed to call this
336 * before the EXRange class is used.
337 */
338 void __EXRangeClassInitialize(void) {
339 _kEXRangeClass.version = 0;
340 _kEXRangeClass.className = "EXRange";
341 _kEXRangeClass.init = NULL;
342 _kEXRangeClass.copy = NULL;
343 _kEXRangeClass.finalize = __EXRangeEXRangeFinalize;
344 _kEXRangeClass.equal = __EXRangeEqual;
345 _kEXRangeClass.hash = __EXRangeHash;
346 _kEXRangeClass.copyFormattingDesc = __EXRangeCopyFormattingDesc;
347 _kEXRangeClass.copyDebugDesc = __EXRangeCopyDebugDesc;
348 _kEXRangeID = _CFRuntimeRegisterClass((const CFRuntimeClass * const)&_kEXRangeClass);
349 }
350
351 CFTypeID EXRangeGetTypeID(void) {
352 return _kEXRangeID;
353 }
354
355 EXRangeRef EXRangeCreate(CFAllocatorRef allocator, uint32_t location, uint32_t length) {
356 struct __EXRange *newrange;
357 uint32_t extra = sizeof(struct __EXRange) - sizeof(CFRuntimeBase);
358 newrange = (struct __EXRange *)_CFRuntimeCreateInstance(allocator, _kEXRangeID, extra, NULL);
359 if (NULL == newrange) {
360 return NULL;
361 }
362 newrange->_location = location;
363 newrange->_length = length;
364 return (EXRangeRef)newrange;
365 }
366
367 uint32_t EXRangeGetLocation(EXRangeRef rangeref) {
368 return rangeref->_location;
369 }
370
371 uint32_t EXRangeGetLength(EXRangeRef rangeref) {
372 return rangeref->_length;
373 }
374
375 #endif
376
377 CF_EXTERN_C_END
378
379 #endif /* ! __COREFOUNDATION_CFRUNTIME__ */