diff --git a/Headers/GNUstepBase/NSObject+GNUstepBase.h b/Headers/GNUstepBase/NSObject+GNUstepBase.h index 649b48b2e..166c13a10 100644 --- a/Headers/GNUstepBase/NSObject+GNUstepBase.h +++ b/Headers/GNUstepBase/NSObject+GNUstepBase.h @@ -219,16 +219,17 @@ extern "C" { * set to YES).
* Your class then has two options for performing clean-up when the process * ends: - *

1. Use the +leak: at: method to register addresses whose contents are - * to be either ignored or released depending on the clean-up setting in - * force when the program exits. + *

1. Use the +keep:at: method to register static/global variables whose + * contents are to be retained for the lifetime of the program (up to exit) + * and either ignored or released depending on the clean-up setting in force + * when the program exits.
* This mechanism is simple and should be sufficient for many classes. *

- *

2. Implement a +atExit method to be run when the process ends and, - * within your +initialize implementation, call +shouldCleanUp to determine - * whether clean-up should be done, and if it returns YES then call - * +registerAtExit to have your +atExit method called when the process - * terminates. + *

2. Implement an +atExit method to be run when the process ends and, + * within your +initialize implementation, +registerAtExit to have your + * +atExit method called when the process exits. Within the +atExit method + * you may call +shouldCleanUp to determine whether celan up has been + * requested. *

*

The order in which 'leaked' objects are released and +atExit methods * are called on process exist is the reverse of the order in which they @@ -241,23 +242,23 @@ extern "C" { */ + (BOOL) isExiting; -/** This method stored anObject at anAddress (retaining it) and notes - * that the object should persist until the process exits. If clean-up - * is enabled the object should be released (and the address content - * zeroed out) upon process exit. +/** This method stores anObject at anAddress (which should be a static or + * global variable) and retains it. The code notes that the object should + * persist until the process exits. If clean-up is enabled the object will + * be released (and the address content zeroed out) upon process exit. * If this method is called while the process is already exiting it * simply zeros out the memory location then returns nil, otherwise * it returns the object stored at the memory location. - * Raises an exception if anObject is nil or anAddress is NULL (unless - * the process is already exiting). + * Raises an exception if anObject is nil or anAddress is NULL or the old + * value at anAddresss is not nil (unless the process is already exiting). */ -+ (id) leak: (id)anObject at: (id*)anAddress; ++ (id) NS_RETURNS_RETAINED keep: (id)anObject at: (id*)anAddress; -/** DEPRECATED ... use +leak: at: instead. +/** DEPRECATED ... use +keep:at: instead. */ + (id) NS_RETURNS_RETAINED leak: (id)anObject; -/** DEPRECATED ... use +leak: at: instead. +/** DEPRECATED ... use +keep:at: instead. */ + (id) NS_RETURNS_RETAINED leakAt: (id*)anAddress; diff --git a/Source/Additions/NSObject+GNUstepBase.m b/Source/Additions/NSObject+GNUstepBase.m index b58aa3666..316b6edbc 100644 --- a/Source/Additions/NSObject+GNUstepBase.m +++ b/Source/Additions/NSObject+GNUstepBase.m @@ -197,7 +197,11 @@ handleExit() Method method; IMP msg; -fprintf(stderr, "*** +[%s %s]\n", class_getName(tmp->obj), sel_getName(tmp->sel)); + if (shouldCleanUp) + { + fprintf(stderr, "*** clean-up +[%s %s]\n", + class_getName(tmp->obj), sel_getName(tmp->sel)); + } method = class_getClassMethod(tmp->obj, tmp->sel); msg = method_getImplementation(method); if (0 != msg) @@ -211,12 +215,16 @@ fprintf(stderr, "*** +[%s %s]\n", class_getName(tmp->obj), sel_getName(tmp->sel) { if (tmp->obj != *(tmp->at)) { -fprintf(stderr, "*** leaked value %p at %p changed to %p\n", tmp->obj, (const void*)tmp->at, *(tmp->at)); + fprintf(stderr, + "*** clean-up kept value %p at %p changed to %p\n", + tmp->obj, (const void*)tmp->at, *(tmp->at)); tmp->obj = *(tmp->at); } *(tmp->at) = nil; } -fprintf(stderr, "*** -[%s release] %p %p\n", class_getName(object_getClass(tmp->obj)), tmp->obj, (const void*)tmp->at); + fprintf(stderr, "*** clean-up -[%s release] %p %p\n", + class_getName(object_getClass(tmp->obj)), + tmp->obj, (const void*)tmp->at); [tmp->obj release]; } free(tmp); @@ -237,7 +245,7 @@ fprintf(stderr, "*** -[%s release] %p %p\n", class_getName(object_getClass(tmp-> return isExiting; } -+ (id) leak: (id)anObject at: (id*)anAddress ++ (id) keep: (id)anObject at: (id*)anAddress { struct exitLink *l; @@ -253,6 +261,7 @@ fprintf(stderr, "*** -[%s release] %p %p\n", class_getName(object_getClass(tmp-> NSAssert([anObject isKindOfClass: [NSObject class]], NSInvalidArgumentException); NSAssert(anAddress != NULL, NSInvalidArgumentException); + NSAssert(*anAddress == nil, NSInvalidArgumentException); setup(); [exitLock lock]; for (l = exited; l != NULL; l = l->next) @@ -520,9 +529,9 @@ fprintf(stderr, "*** -[%s release] %p %p\n", class_getName(object_getClass(tmp-> /* Dummy implementation */ -@implementation NSObject(GSCleanup) +@implementation NSObject(GSCleanUp) -+ (id) leak: (id)anObject at: (id*)anAddress ++ (id) keep: (id)anObject at: (id*)anAddress { ASSIGN(*anAddress, anObject); return *anAddress; diff --git a/Source/GSLocale.m b/Source/GSLocale.m index 0868e6f1c..00be5e93f 100644 --- a/Source/GSLocale.m +++ b/Source/GSLocale.m @@ -223,7 +223,7 @@ GSDomainFromDefaultLocale(void) */ if (saved == nil) { - [NSObject leak: AUTORELEASE([dict copy]) at: &saved]; + [NSObject keep: AUTORELEASE([dict copy]) at: &saved]; } /**