2 * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
24 #include <security_utilities/cfclass.h>
25 #include <security_utilities/seccfobject.h>
26 #include <security_utilities/threading.h>
27 #include <CoreFoundation/CFString.h>
29 #include <auto_zone.h>
30 #include <objc/objc-auto.h>
35 CFClass::CFClass(const char *name
)
37 // initialize the CFRuntimeClass structure
42 finalize
= finalizeType
;
45 copyFormattingDesc
= copyFormattingDescType
;
46 copyDebugDesc
= copyDebugDescType
;
48 // update because we are now doing our own reference counting
49 version
|= _kCFRuntimeCustomRefCount
; // see ma, no hands!
50 refcount
= refCountForType
;
53 typeID
= _CFRuntimeRegisterClass(this);
54 assert(typeID
!= _kCFRuntimeNotATypeID
);
58 CFClass::cleanupObject(intptr_t op
, CFTypeRef cf
, bool &zap
)
60 // the default is to not throw away the object
63 bool isGC
= CF_IS_COLLECTABLE(cf
);
65 uint32_t currentCount
;
66 SecCFObject
*obj
= SecCFObject::optional(cf
);
69 currentCount
= obj
->updateRetainCount(op
, &oldCount
);
73 auto_zone_t
* zone
= objc_collectableZone();
75 if (op
== -1 && oldCount
== 0)
77 auto_zone_release(zone
, (void*) cf
);
79 else if (op
== 1 && oldCount
== 0 && currentCount
== 1)
81 auto_zone_retain(zone
, (void*) cf
);
83 else if (op
== -1 && oldCount
== 1 && currentCount
== 0)
86 To prevent accidental resurrection, just pull it out of the
89 obj
->aboutToDestruct();
90 auto_zone_release(zone
, (void*) cf
);
104 else if (currentCount
== 0)
107 zap
= true; // the the caller to release the mutex and zap the object
117 CFClass::refCountForType(intptr_t op
, CFTypeRef cf
) throw()
124 SecCFObject
*obj
= SecCFObject::optional(cf
);
125 Mutex
* mutex
= obj
->getMutexForObject();
128 // if the object didn't have a mutex, it wasn't cached.
129 // Just clean it up and get out.
130 result
= cleanupObject(op
, cf
, zap
);
134 // we have a mutex, so we need to do our cleanup operation under its control
135 StLock
<Mutex
> _(*mutex
);
136 result
= cleanupObject(op
, cf
, zap
);
139 if (zap
) // did we release the object?
141 delete obj
; // should call the overloaded delete for the object
148 // keep the compiler happy
155 CFClass::finalizeType(CFTypeRef cf
) throw()
158 Why are we asserting the mutex here as well as in refCountForType?
159 Because the way we control the objects and the queues are different
160 under GC than they are under non-GC operations.
162 In non-GC, we need to control the lifetime of the object. This means
163 that the cache lock has to be asserted while we are determining if the
164 object should live or die. The mutex is recursive, which means that
165 we won't end up with mutex inversion.
167 In GC, GC figures out the lifetime of the object. We probably don't need
168 to assert the mutex here, but it doesn't hurt.
171 SecCFObject
*obj
= SecCFObject::optional(cf
);
173 bool isCollectable
= CF_IS_COLLECTABLE(cf
);
177 Mutex
* mutex
= obj
->getMutexForObject();
180 // if the object didn't have a mutex, it wasn't cached.
181 // Just clean it up and get out.
182 obj
->aboutToDestruct(); // removes the object from its associated cache.
186 StLock
<Mutex
> _(*mutex
);
190 // New objects aren't in the cache.
191 // Just clean it up and get out.
192 obj
->aboutToDestruct(); // removes the object from its associated cache.
196 obj
->aboutToDestruct(); // removes the object from its associated cache.
210 CFClass::equalType(CFTypeRef cf1
, CFTypeRef cf2
) throw()
212 // CF checks for pointer equality and ensures type equality already
214 return SecCFObject::optional(cf1
)->equal(*SecCFObject::optional(cf2
));
221 CFClass::hashType(CFTypeRef cf
) throw()
224 return SecCFObject::optional(cf
)->hash();
226 return 666; /* Beasty return for error */
231 CFClass::copyFormattingDescType(CFTypeRef cf
, CFDictionaryRef dict
) throw()
234 return SecCFObject::optional(cf
)->copyFormattingDesc(dict
);
236 return CFSTR("Exception thrown trying to format object");
241 CFClass::copyDebugDescType(CFTypeRef cf
) throw()
244 return SecCFObject::optional(cf
)->copyDebugDesc();
246 return CFSTR("Exception thrown trying to format object");