@@ -15,190 +15,122 @@ #import #endif #import "OFAutoreleasePool.h" #import "OFExceptions.h" +#import "OFList.h" #ifdef _WIN32 #import #endif #ifndef _WIN32 -static pthread_key_t pool_stack_key; -static pthread_key_t pool_index_key; +#define get_tls(t) pthread_getspecific(pool_list_key) +#define set_tls(t, v) pthread_setspecific(t, v) +static pthread_key_t pool_list_key; #else -static DWORD pool_stack_key; -static DWORD pool_index_key; +#define get_tls(t) TlsGetValue(t) +#define set_tls(t, v) TlsSetValue(t, v) +static DWORD pool_list_key; #endif #ifndef _WIN32 static void -free_each(void *ptr) -{ - OFAutoreleasePool **p; - OFObject **o; - - for (p = (OFAutoreleasePool**)ptr; *p != nil; p++) { - for (o = [*p objects]; *o != nil; o++) - [*o release]; - [*p free]; - } +release_obj(void *obj) +{ + [(OFObject*)obj release]; } #endif @implementation OFAutoreleasePool + (void)initialize { #ifndef _WIN32 - if (pthread_key_create(&pool_stack_key, free_each)) + if (pthread_key_create(&pool_list_key, release_obj)) @throw [OFInitializationFailedException newWithClass: self]; - if (pthread_key_create(&pool_index_key, free)) { - pthread_key_delete(pool_stack_key); - @throw [OFInitializationFailedException newWithClass: self]; - } #else /* FIXME: Free stuff when thread is terminated! */ - if ((pool_stack_key = TlsAlloc()) == TLS_OUT_OF_INDEXES) + if ((pool_list_key = TlsAlloc()) == TLS_OUT_OF_INDEXES) @throw [OFInitializationFailedException newWithClass: self]; - if ((pool_index_key = TlsAlloc()) == TLS_OUT_OF_INDEXES) { - TlsFree(pool_stack_key); - @throw [OFInitializationFailedException newWithClass: self]; - } - #endif } + (void)addToPool: (OFObject*)obj { - OFAutoreleasePool **pool_stack; - int *pool_index; - -#ifndef _WIN32 - pool_stack = pthread_getspecific(pool_stack_key); - pool_index = pthread_getspecific(pool_index_key); -#else - pool_stack = TlsGetValue(pool_stack_key); - pool_index = TlsGetValue(pool_index_key); -#endif - - if (pool_stack == NULL || pool_index == NULL) { - [[self alloc] init]; - -#ifndef _WIN32 - pool_stack = pthread_getspecific(pool_stack_key); - pool_index = pthread_getspecific(pool_index_key); -#else - pool_stack = TlsGetValue(pool_stack_key); - pool_index = TlsGetValue(pool_index_key); -#endif - } - - if (*pool_stack == nil || *pool_index == -1) - @throw [OFInitializationFailedException newWithClass: self]; - - [pool_stack[*pool_index] addToPool: obj]; + OFList *pool_list = get_tls(pool_list_key); + + if (pool_list == nil) { + [[self alloc] init]; + pool_list = get_tls(pool_list_key); + } + + if (pool_list == nil || [pool_list last] == NULL) + @throw [OFInitializationFailedException newWithClass: self]; + + [[pool_list last]->object addToPool: obj]; } - init { - OFAutoreleasePool **pool_stack, **pool_stack2; - int *pool_index; - Class c; + OFList *pool_list; if ((self = [super init])) { - objects = NULL; - size = 0; - -#ifndef _WIN32 - pool_stack = pthread_getspecific(pool_stack_key); - pool_index = pthread_getspecific(pool_index_key); -#else - pool_stack = TlsGetValue(pool_stack_key); - pool_index = TlsGetValue(pool_index_key); -#endif - - if (pool_index == NULL) { - if ((pool_index = malloc(sizeof(int))) == NULL) { - c = [self class]; - [super free]; - @throw [OFNoMemException newWithClass: c]; - } - - *pool_index = -1; -#ifndef _WIN32 - pthread_setspecific(pool_index_key, pool_index); -#else - TlsSetValue(pool_index_key, pool_index); -#endif - } - - if ((pool_stack2 = realloc(pool_stack, - (*pool_index + 3) * sizeof(OFAutoreleasePool*))) == NULL) { - c = [self class]; - [super free]; - @throw [OFNoMemException newWithClass: c]; - } - pool_stack = pool_stack2; -#ifndef _WIN32 - pthread_setspecific(pool_stack_key, pool_stack); -#else - TlsSetValue(pool_stack_key, pool_stack); -#endif - (*pool_index)++; - - pool_stack[*pool_index] = self; - pool_stack[*pool_index + 1] = nil; + objects = nil; + + pool_list = get_tls(pool_list_key); + + if (pool_list == nil) { + pool_list = [[OFList alloc] + initWithRetainAndReleaseEnabled: NO]; + set_tls(pool_list_key, pool_list); + } + + listobj = [pool_list append: self]; } return self; } - free { - [self release]; + [(OFList*)get_tls(pool_list_key) remove: listobj]; return [super free]; } - addToPool: (OFObject*)obj { - OFObject **objects2; - size_t size2; - - size2 = size + 1; - - if (SIZE_MAX - size < 1 || size2 > SIZE_MAX / sizeof(OFObject*)) - @throw [OFOutOfRangeException newWithClass: [self class]]; - - if ((objects2 = realloc(objects, size2 * sizeof(OFObject*))) == NULL) - @throw [OFNoMemException newWithClass: [self class] - andSize: size2]; - - objects = objects2; - objects[size] = obj; - size = size2; + if (objects == nil) + objects = [OFArray newWithItemSize: sizeof(char*)]; + + [objects add: &obj]; return self; } - release { - size_t i; - - if (objects != NULL) { - for (i = 0; size < i; i++) - [objects[i] release]; - - free(objects); - } - - objects = NULL; - size = 0; + [self releaseObjects]; + + return [super release]; +} + +- releaseObjects +{ + size_t i, size; + IMP get_item; + + if (objects == nil) + return self; + + size = [objects items]; + get_item = [objects methodFor: @selector(item:)]; + + for (i = 0; i < size; i++) + [*((OFObject**)get_item(objects, @selector(item:), i)) release]; + + [objects release]; + objects = nil; return self; } - -- (OFObject**)objects -{ - return objects; -} @end