diff options
Diffstat (limited to 'src/core/basetypes/MCAutoreleasePool.cpp')
-rw-r--r-- | src/core/basetypes/MCAutoreleasePool.cpp | 123 |
1 files changed, 123 insertions, 0 deletions
diff --git a/src/core/basetypes/MCAutoreleasePool.cpp b/src/core/basetypes/MCAutoreleasePool.cpp new file mode 100644 index 00000000..67e58a78 --- /dev/null +++ b/src/core/basetypes/MCAutoreleasePool.cpp @@ -0,0 +1,123 @@ +#include "MCAutoreleasePool.h" + +#include <libetpan/libetpan.h> + +#include "MCString.h" +#include "MCLog.h" +#include "MCUtils.h" + +using namespace mailcore; + +pthread_key_t AutoreleasePool::autoreleasePoolStackKey; + +void AutoreleasePool::init() +{ + static pthread_once_t once = PTHREAD_ONCE_INIT; + pthread_once(&once, initAutoreleasePoolStackKey); +} + +AutoreleasePool::AutoreleasePool() +{ + mPoolObjects = carray_new(4); + +#if __APPLE__ + mAppleAutoreleasePool = createAppleAutoreleasePool(); +#endif + + unsigned int idx; + carray * stack = createAutoreleasePoolStackIfNeeded(); + carray_add(stack, this, &idx); +} + +AutoreleasePool::~AutoreleasePool() +{ +#if __APPLE__ + releaseAppleAutoreleasePool(mAppleAutoreleasePool); +#endif + + carray * stack = createAutoreleasePoolStackIfNeeded(); + carray_delete_slow(stack, carray_count(stack) - 1); + + unsigned int count = carray_count(mPoolObjects); + for(unsigned int i = 0 ; i < count ; i ++) { + Object * obj = (Object *) carray_get(mPoolObjects, i); + obj->release(); + } + carray_free(mPoolObjects); +} + +carray * AutoreleasePool::createAutoreleasePoolStackIfNeeded() +{ + init(); + carray * stack = (carray *) pthread_getspecific(autoreleasePoolStackKey); + if (stack != NULL) { + return stack; + } + + stack = carray_new(4); + pthread_setspecific(autoreleasePoolStackKey, stack); + + return stack; +} + +void AutoreleasePool::destroyAutoreleasePoolStack(void * value) +{ + carray * stack = (carray *) value; + if (carray_count(stack) != 0) { + MCLog("some autoreleasepool have not been released\n"); + } + carray_free(stack); +} + +void AutoreleasePool::initAutoreleasePoolStackKey() +{ + pthread_key_create(&autoreleasePoolStackKey, destroyAutoreleasePoolStack); +} + +AutoreleasePool * AutoreleasePool::currentAutoreleasePool() +{ + init(); + carray * stack; + stack = createAutoreleasePoolStackIfNeeded(); + if (carray_count(stack) == 0) { + //fprintf(stderr, "no current autoreleasepool\n"); + return NULL; + } + + AutoreleasePool * pool; + pool = (AutoreleasePool *) carray_get(stack, carray_count(stack) - 1); + return pool; +} + +void AutoreleasePool::add(Object * obj) +{ + unsigned int idx; + carray_add(mPoolObjects, obj, &idx); +} + +void AutoreleasePool::autorelease(Object * obj) +{ + AutoreleasePool * pool = AutoreleasePool::currentAutoreleasePool(); + if (pool == NULL) { + MCLog("-autorelease called with no current autoreleasepool\n"); + return; + } + pool->add(obj); +} + +String * AutoreleasePool::description() +{ + String * result = String::string(); + result->appendUTF8Format("<%p:%p ", className(), this); + unsigned int count = carray_count(mPoolObjects); + for(unsigned int i = 0 ; i < count ; i ++) { + Object * obj = (Object *) carray_get(mPoolObjects, i); + if (i != 0) { + result->appendUTF8Characters(" "); + } + result->appendString(obj->description()); + } + result->appendUTF8Characters(">"); + + return result; +} |