Index: src/OFAutoreleasePool.h ================================================================== --- src/OFAutoreleasePool.h +++ src/OFAutoreleasePool.h @@ -9,12 +9,10 @@ * the packaging of this file. */ #import "OFObject.h" -@class OFMutableArray; - /** * \brief A pool that keeps track of objects to release. * * The OFAutoreleasePool class is a class that keeps track of objects that will * be released when the autorelease pool is released. @@ -21,12 +19,13 @@ * * Every thread has its own stack of autorelease pools. */ @interface OFAutoreleasePool: OFObject { - OFMutableArray *objects; OFAutoreleasePool *next, *prev; + id *objects; + size_t count, size; } /** * Adds an object to the autorelease pool at the top of the thread-specific * stack. @@ -44,10 +43,17 @@ */ - (void)addObject: (OFObject*)obj; /** * Releases all objects in the autorelease pool. + * + * This does not free the memory allocated to store pointers to the objects in + * the pool, so reusing the pool does not allocate any memory until the previous + * number of objects is exceeded. It behaves this way to optimize loops that + * always work with the same or similar number of objects and call relaseObjects + * at the end of the loop, which is propably the most common case for + * releaseObjects. * * If a garbage collector is added in the future, it will tell the GC that now * is a good time to clean up, as this is often used after a lot of objects * have been added to the pool that should be released before the next iteration * of a loop, which adds objects again. Thus, it is usually a clean up call. Index: src/OFAutoreleasePool.m ================================================================== --- src/OFAutoreleasePool.m +++ src/OFAutoreleasePool.m @@ -17,10 +17,12 @@ #import "OFArray.h" #import "OFExceptions.h" #ifdef OF_THREADS # import "threading.h" + +#define GROW_SIZE 16 static of_tlskey_t first_key, last_key; #else static OFAutoreleasePool *first = nil, *last = nil; #endif @@ -116,28 +118,46 @@ #endif } if (prev != nil) prev->next = self; + + size = GROW_SIZE; + @try { + objects = [self allocMemoryForNItems: GROW_SIZE + withSize: sizeof(id)]; + } @catch (OFException *e) { + [self dealloc]; + @throw e; + } return self; } - (void)addObject: (OFObject*)obj { - if (objects == nil) - objects = [[OFMutableArray alloc] init]; + if (count + 1 > size) { + objects = [self resizeMemory: objects + toNItems: size + GROW_SIZE + withSize: sizeof(id)]; + size += GROW_SIZE; + } - [objects addObject: obj]; - [obj release]; + objects[count] = obj; + count++; } - (void)releaseObjects { + size_t i; + [next releaseObjects]; - [objects release]; - objects = nil; + + for (i = 0; i < count; i++) + [objects[i] release]; + + count = 0; } - (void)release { [self dealloc]; @@ -148,12 +168,16 @@ [self dealloc]; } - (void)dealloc { + size_t i; + [next dealloc]; - [objects release]; + + for (i = 0; i < count; i++) + [objects[i] release]; /* * If of_tlskey_set fails, this is a real problem. The best we can do * is to not change the pool below the current pool and stop * deallocation. This way, new objects will be added to the current