Index: src/OFAutoreleasePool.h ================================================================== --- src/OFAutoreleasePool.h +++ src/OFAutoreleasePool.h @@ -18,12 +18,12 @@ * that will be released when the autorelease pool is released. * Every thread has its own stack of autorelease pools. */ @interface OFAutoreleasePool: OFObject { - OFArray *objects; - of_list_object_t *listobj; + OFArray *objects; + OFAutoreleasePool *next, *prev; } /** * Adds an object to the autorelease pool at the top of the thread-specific * stack. Index: src/OFAutoreleasePool.m ================================================================== --- src/OFAutoreleasePool.m +++ src/OFAutoreleasePool.m @@ -10,119 +10,166 @@ */ #include "config.h" #include + +#ifndef _WIN32 +#include +#else +#include +#endif #import "OFAutoreleasePool.h" #import "OFList.h" #import "OFThread.h" #import "OFExceptions.h" -static OFTLSKey *pool_list_key; +/* + * Pay special attention to NULL and nil in this file, they might be different! + * Use NULL for TLS values and nil for instance variables. + */ + +#ifndef _WIN32 +static pthread_key_t first_key, last_key; +#else +static DWORD first_key, last_key; +#endif static void -release_list(void *list) -{ - of_list_object_t *first, *iter; - IMP release; - - if ((first = [(OFList*)list first]) != NULL) - release = [first->object methodForSelector: @selector(release)]; - - for (iter = first; iter != NULL; iter = iter->next) - release(iter->object, @selector(release)); - - [(OFList*)list release]; +release_all(void *list) +{ +#ifndef _WIN32 + void *first = pthread_getspecific(first_key); +#else + void *first = TlsGetValue(first_key); +#endif + + if (first != NULL) + [(OFAutoreleasePool*)first release]; } @implementation OFAutoreleasePool + (void)initialize { if (self != [OFAutoreleasePool class]) return; - pool_list_key = [[OFTLSKey alloc] initWithDestructor: release_list]; +#ifndef _WIN32 + if (pthread_key_create(&first_key, release_all) || + pthread_key_create(&last_key, NULL)) +#else + /* FIXME: Call destructor */ + if ((first_key = TlsAlloc()) == TLS_OUT_OF_INDEXES || + (last_key = TlsAlloc()) == TLS_OUT_OF_INDEXES) +#endif + @throw [OFInitializationFailedException newWithClass: self]; } + (void)addObjectToTopmostPool: (OFObject*)obj { - OFList *pool_list = [OFThread objectForTLSKey: pool_list_key]; +#ifndef _WIN32 + void *last = pthread_getspecific(last_key); +#else + void *last = TlsGetValue(last_key); +#endif - if (pool_list == nil || [pool_list last] == NULL) { + if (last == NULL) { @try { [[self alloc] init]; - pool_list = [OFThread objectForTLSKey: pool_list_key]; } @catch (OFException *e) { [obj release]; @throw e; } + +#ifndef _WIN32 + last = pthread_getspecific(last_key); +#else + last = TlsGetValue(last_key); +#endif } - if (pool_list == nil || [pool_list last] == NULL) { + if (last == NULL) { [obj release]; @throw [OFInitializationFailedException newWithClass: self]; } @try { - [[pool_list last]->object addObject: obj]; + [(OFAutoreleasePool*)last addObject: obj]; } @catch (OFException *e) { [obj release]; @throw e; } } - init { - OFList *pool_list; - - self = [super init]; - - if ((pool_list = [OFThread objectForTLSKey: pool_list_key]) == nil) { - @try { - pool_list = [[OFList alloc] - initWithoutRetainAndRelease]; - } @catch (OFException *e) { - [self dealloc]; - @throw e; - } - - @try { - [OFThread setObject: pool_list - forTLSKey: pool_list_key]; - } @catch (OFException *e) { - [self dealloc]; - @throw e; - } @finally { - [pool_list release]; - } - } - - @try { - listobj = [pool_list append: self]; - } @catch (OFException *e) { - [self dealloc]; - @throw e; + self = [super init]; + +#ifndef _WIN32 + void *first = pthread_getspecific(first_key); + void *last = pthread_getspecific(last_key); +#else + void *first = TlsGetValue(first_key); + void *last = TlsGetValue(last_key); +#endif + +#ifndef _WIN32 + if (pthread_setspecific(last_key, self)) { +#else + if (!TlsSetValue(last_key, self)) { +#endif + Class c = isa; + [super dealloc]; + @throw [OFInitializationFailedException newWithClass: c]; + } + + if (first == NULL) { +#ifndef _WIN32 + if (pthread_setspecific(first_key, self)) { +#else + if (!TlsSetValue(first_key, self)) { +#endif + Class c = isa; + +#ifndef _WIN32 + pthread_setspecific(last_key, last); +#else + TlsSetValue(last_key, last); +#endif + + [super dealloc]; + @throw [OFInitializationFailedException + newWithClass: c]; + } + } + + if (last != NULL) { + prev = (OFAutoreleasePool*)last; + prev->next = self; } return self; } - (void)dealloc { - /* - * FIXME: - * Maybe we should get the objects ourself, release them and then - * release the pool without calling its release method? This way, - * there wouldn't be a recursion. - */ - if (listobj->next != NULL) - [listobj->next->object release]; - - [self releaseObjects]; - - [[OFThread objectForTLSKey: pool_list_key] remove: listobj]; + [next dealloc]; + + if (prev != nil) + prev->next = nil; +#ifndef _WIN32 + pthread_setspecific(last_key, (prev != nil ? prev : NULL)); + if (pthread_getspecific(first_key) == self) + pthread_setspecific(first_key, NULL); +#else + TlsSetValue(last_key, (prev != nil ? prev : NULL)); + if (TlsGetValue(first_key) == self) + TlsSetValue(first_key, NULL); +#endif + + [objects release]; [super dealloc]; } - addObject: (OFObject*)obj @@ -136,12 +183,11 @@ return self; } - releaseObjects { - if (listobj->next != NULL) - [listobj->next->object releaseObjects]; + [next releaseObjects]; if (objects == nil) return self; [objects release]; Index: src/OFList.h ================================================================== --- src/OFList.h +++ src/OFList.h @@ -31,26 +31,17 @@ @interface OFList: OFObject { of_list_object_t *first; of_list_object_t *last; size_t count; - BOOL retain_and_release; } /** * \return A new autoreleased OFList */ + list; -/** - * Initializes an already allocated OFList that does not retain/release objects - * added to it. - * - * \return An initialized OFList - */ -- initWithoutRetainAndRelease; - /** * \return The first list object in the list */ - (of_list_object_t*)first; Index: src/OFList.m ================================================================== --- src/OFList.m +++ src/OFList.m @@ -24,21 +24,10 @@ - init { self = [super init]; - first = NULL; - last = NULL; - retain_and_release = YES; - - return self; -} - -- initWithoutRetainAndRelease -{ - self = [super init]; - first = NULL; last = NULL; return self; } @@ -79,12 +68,11 @@ if (first == NULL) first = o; count++; - if (retain_and_release) - [obj retain]; + [obj retain]; return o; } - (of_list_object_t*)prepend: (id)obj @@ -103,12 +91,11 @@ if (last == NULL) last = o; count++; - if (retain_and_release) - [obj retain]; + [obj retain]; return o; } - (of_list_object_t*)insert: (id)obj @@ -129,12 +116,11 @@ if (listobj == first) first = o; count++; - if (retain_and_release) - [obj retain]; + [obj retain]; return o; } - (of_list_object_t*)insert: (id)obj @@ -155,12 +141,11 @@ if (listobj == last) last = o; count++; - if (retain_and_release) - [obj retain]; + [obj retain]; return o; } - remove: (of_list_object_t*)listobj @@ -175,12 +160,11 @@ if (last == listobj) last = listobj->prev; count--; - if (retain_and_release) - [listobj->object release]; + [listobj->object release]; [self freeMemory: listobj]; return self; } @@ -211,18 +195,13 @@ return YES; } - (id)copy { - OFList *new; + OFList *new = [[OFList alloc] init]; of_list_object_t *iter, *o, *prev; - if (retain_and_release) - new = [[OFList alloc] init]; - else - new = [[OFList alloc] initWithoutRetainAndRelease]; - o = NULL; prev = NULL; @try { for (iter = first; iter != NULL; iter = iter->next) { @@ -236,12 +215,11 @@ if (prev != NULL) prev->next = o; new->count++; - if (retain_and_release) - [o->object retain]; + [o->object retain]; prev = o; } } @catch (OFException *e) { [new release]; Index: tests/Makefile ================================================================== --- tests/Makefile +++ tests/Makefile @@ -1,9 +1,8 @@ include ../extra.mk -SUBDIRS = OFAutoreleasePool \ - OFDataArray \ +SUBDIRS = OFDataArray \ OFArray \ OFDictionary \ OFHashes \ ${OFPLUGIN} \ OFTCPSocket \ Index: tests_new/main.m ================================================================== --- tests_new/main.m +++ tests_new/main.m @@ -14,12 +14,12 @@ #ifdef STDOUT #include #endif #include -#import -#import +#import "OFString.h" +#import "OFAutoreleasePool.h" extern void object_tests(); extern void string_tests(); static int fails = 0;