/* * Copyright (c) 2008 - 2009 * Jonathan Schleifer * * All rights reserved. * * This file is part of libobjfw. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE included in * the packaging of this file. */ #import "config.h" #include #import "OFAutoreleasePool.h" #import "OFList.h" #import "OFThread.h" #import "OFExceptions.h" static OFTLSKey *pool_list_key; static void release_list(void *list) { of_list_object_t *first, *iter; IMP release; if ((first = [(OFList*)list first]) != NULL) release = [first->object methodFor: @selector(release)]; for (iter = first; iter != NULL; iter = iter->next) release(iter->object, @selector(release)); [(OFList*)list release]; } @implementation OFAutoreleasePool + initialize { pool_list_key = [[OFTLSKey alloc] initWithDestructor: release_list]; return self; } + (void)addToPool: (OFObject*)obj { OFList *pool_list; @try { pool_list = [OFThread objectForTLSKey: pool_list_key]; } @catch (OFNotInSetException *e) { [e free]; [[self alloc] init]; pool_list = [OFThread objectForTLSKey: pool_list_key]; } if ([pool_list last] == NULL) [[self alloc] init]; if ([pool_list last] == NULL) @throw [OFInitializationFailedException newWithClass: self]; [[pool_list last]->object addToPool: obj]; } - init { OFList *pool_list; self = [super init]; objects = nil; @try { pool_list = [OFThread objectForTLSKey: pool_list_key]; } @catch (OFNotInSetException *e) { [e free]; pool_list = [[OFList alloc] initWithoutRetainAndRelease]; [OFThread setObject: pool_list forTLSKey: pool_list_key]; [pool_list release]; } listobj = [pool_list append: self]; return self; } - free { [[OFThread objectForTLSKey: pool_list_key] remove: listobj]; return [super free]; } - addToPool: (OFObject*)obj { if (objects == nil) objects = [[OFArray alloc] initWithItemSize: sizeof(char*)]; [objects add: &obj]; return self; } - release { [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; } @end