@@ -10,13 +10,17 @@ */ #include "config.h" #import "OFThread.h" +#import "OFList.h" +#import "OFAutoreleasePool.h" #import "OFExceptions.h" #import "threading.h" + +static OFList *tlskeys; static id call_main(id obj) { /* @@ -23,10 +27,13 @@ * Nasty workaround for thread implementations which can't return a * value on join. */ ((OFThread*)obj)->retval = [obj main]; + [OFTLSKey callAllDestructors]; + [OFAutoreleasePool releaseAll]; + return 0; } @implementation OFThread + threadWithObject: (id)obj @@ -104,49 +111,80 @@ [super dealloc]; } @end @implementation OFTLSKey ++ (void)initialize +{ + if (self == [OFTLSKey class]) + tlskeys = [[OFList alloc] init]; +} + + tlsKey { return [[[self alloc] init] autorelease]; } + tlsKeyWithDestructor: (void(*)(id))destructor { return [[[self alloc] initWithDestructor: destructor] autorelease]; } + ++ (void)callAllDestructors +{ + of_list_object_t *iter; + + @synchronized (tlskeys) { + for (iter = [tlskeys first]; iter != NULL; iter = iter->next) + ((OFTLSKey*)iter->object)->destructor(iter->object); + } +} - init { self = [super init]; - if (!of_tlskey_new(&key, NULL)) { + if (!of_tlskey_new(&key)) { Class c = isa; [super dealloc]; @throw [OFInitializationFailedException newWithClass: c]; } + + destructor = NULL; + + @synchronized (tlskeys) { + @try { + listobj = [tlskeys append: self]; + } @catch (OFException *e) { + listobj = NULL; + [self dealloc]; + @throw e; + } + } return self; } -- initWithDestructor: (void(*)(id))destructor -{ - self = [super init]; - - if (!of_tlskey_new(&key, destructor)) { - Class c = isa; - [super dealloc]; - @throw [OFInitializationFailedException newWithClass: c]; - } +- initWithDestructor: (void(*)(id))destructor_ +{ + self = [self init]; + + destructor = destructor_; return self; } - (void)dealloc { + if (destructor != NULL) + destructor(self); + of_tlskey_free(key); + + @synchronized (tlskeys) { + [tlskeys remove: listobj]; + } [super dealloc]; } @end