Correctly call C++ constructors / destructors for C++ 'objects' in ObjC++ ivars.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@32632 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
theraven 2011-03-17 15:02:52 +00:00
parent 58e3acf804
commit 644bda0ad8

View file

@ -648,6 +648,39 @@ GSObjCZone(NSObject *object)
return ((obj)object)[-1].zone;
}
static SEL cxx_construct, cxx_destruct;
/**
* Calls the C++ constructors for this object, starting with the ones declared
* in aClass. The compiler generates two methods on Objective-C++ classes that
* static instances of C++ classes as ivars. These are -.cxx_construct and
* -.cxx_destruct. The -.cxx_construct methods must be called in order from
* the root class to all subclasses, to ensure that subclass ivars are
* initialised after superclass ones. This must be done in reverse for
* destruction.
*
* This function first calls itself recursively on the superclass, to get the
* IMP for the constructor function in the superclass. It then compares the
* construct method for this class with the one that's already been called,
* and calls it if it's new.
*/
static IMP callCXXConstructors(Class aClass, id anObject)
{
IMP constructor = 0;
if (class_respondsToSelector(aClass, cxx_construct))
{
IMP calledConstructor =
callCXXConstructors(class_getSuperclass(aClass), anObject);
constructor = class_getMethodImplementation(aClass, cxx_construct);
if (calledConstructor != constructor)
{
constructor(anObject, cxx_construct);
}
}
return constructor;
}
inline id
NSAllocateObject (Class aClass, NSUInteger extraBytes, NSZone *zone)
{
@ -669,16 +702,48 @@ NSAllocateObject (Class aClass, NSUInteger extraBytes, NSZone *zone)
object_setClass(new, aClass);
AADD(aClass, new);
}
// Don't bother doing this in a thread-safe way, because the cost of locking
// will be a lot more than the cost of doing the same call in two threads.
// The returned selector will persist and the runtime will ensure that both
// calls return the same selector, so we don't need to bother doing it
// ourselves.
if (0 == cxx_construct)
{
cxx_construct = sel_registerName(".cxx_construct");
cxx_destruct = sel_registerName(".cxx_destruct");
}
callCXXConstructors(aClass, new);
return new;
}
inline void
NSDeallocateObject(id anObject)
{
if ((anObject!=nil) && !class_isMetaClass(object_getClass((id)anObject)))
Class aClass = object_getClass(anObject);
if ((anObject!=nil) && !class_isMetaClass(aClass))
{
obj o = &((obj)anObject)[-1];
NSZone *z = o->zone;
Class destructorClass = aClass;
IMP destructor = 0;
// C++ destructors must be called in the opposite order to their
// creators, so start at the leaf class and then go up the tree until we
// get to the root class. As a small optimisation, we don't bother
// visiting any classes that don't have an implementation of this method
// (including one inherited from a superclass).
//
// Care must be taken not to call inherited .cxx_destruct methods.
while (class_respondsToSelector(destructorClass, cxx_destruct))
{
IMP newDestructor = class_getMethodImplementation(destructorClass, cxx_destruct);
if (newDestructor != destructor)
{
newDestructor(anObject, cxx_destruct);
destructor = newDestructor;
}
destructorClass = class_getSuperclass(destructorClass);
}
AREM(object_getClass((id)anObject), (id)anObject);
if (NSZombieEnabled == YES)