Index: src/OFFile.m ================================================================== --- src/OFFile.m +++ src/OFFile.m @@ -684,10 +684,18 @@ if (closable && fileDescriptor != -1) close(fileDescriptor); [super dealloc]; } + +- (void)finalize +{ + if (closable && fileDescriptor != -1) + close(fileDescriptor); + + [super finalize]; +} @end @implementation OFFileSingleton - initWithPath: (OFString*)path mode: (OFString*)mode Index: src/OFObject.h ================================================================== --- src/OFObject.h +++ src/OFObject.h @@ -409,10 +409,16 @@ * Deallocates the object and also frees all memory in its memory pool. * * It is also called when the retain count reaches zero. */ - (void)dealloc; + +/** + * If a garbage collector is added in the future, this method will be called + * before it disposes of the object, for example to close files. + */ +- (void)finalize; @end /** * \brief A protocol for the creation of copies. */ Index: src/OFObject.m ================================================================== --- src/OFObject.m +++ src/OFObject.m @@ -813,10 +813,37 @@ if (PRE_IVAR->memoryChunks != NULL) free(PRE_IVAR->memoryChunks); free((char*)self - PRE_IVAR_ALIGN); } + +- (void)finalize +{ + Class class; + void (*last)(id, SEL) = NULL; + void **iter; + + for (class = isa; class != Nil; class = class_getSuperclass(class)) { + void (*destruct)(id, SEL); + + if ([class instancesRespondToSelector: cxx_destruct]) { + if ((destruct = (void(*)(id, SEL))[class + instanceMethodForSelector: cxx_destruct]) != last) + destruct(self, cxx_destruct); + + last = destruct; + } else + break; + } + + iter = PRE_IVAR->memoryChunks + PRE_IVAR->memoryChunksSize; + while (iter-- > PRE_IVAR->memoryChunks) + free(*iter); + + if (PRE_IVAR->memoryChunks != NULL) + free(PRE_IVAR->memoryChunks); +} /* Required to use properties with the Apple runtime */ - copyWithZone: (void*)zone { if (zone != NULL) Index: src/OFPlugin.m ================================================================== --- src/OFPlugin.m +++ src/OFPlugin.m @@ -82,6 +82,13 @@ [super dealloc]; dlclose(h); } + +- (void)finalize +{ + dlclose(handle); + + [super finalize]; +} @end Index: src/OFStreamObserver.m ================================================================== --- src/OFStreamObserver.m +++ src/OFStreamObserver.m @@ -150,10 +150,18 @@ [FDs release]; #endif [super dealloc]; } + +- (void)finalize +{ + close(cancelFD[0]); + close(cancelFD[1]); + + [super finalize]; +} - (id )delegate { return [[(id)delegate retain] autorelease]; } Index: src/OFStreamSocket.m ================================================================== --- src/OFStreamSocket.m +++ src/OFStreamSocket.m @@ -166,6 +166,14 @@ if (sock != INVALID_SOCKET) [self close]; [super dealloc]; } + +- (void)finalize +{ + if (sock != INVALID_SOCKET) + [self close]; + + [super finalize]; +} @end Index: src/OFThread.m ================================================================== --- src/OFThread.m +++ src/OFThread.m @@ -303,10 +303,26 @@ [object release]; [returnValue release]; [super dealloc]; } + +- (void)finalize +{ + if (running == OF_THREAD_RUNNING) + @throw [OFThreadStillRunningException newWithClass: isa + thread: self]; + + /* + * We should not be running anymore, but call detach in order to free + * the resources. + */ + if (running == OF_THREAD_WAITING_FOR_JOIN) + of_thread_detach(thread); + + [super finalize]; +} @end @implementation OFTLSKey + (void)initialize { @@ -385,10 +401,28 @@ } } [super dealloc]; } + +- (void)finalize +{ + if (destructor != NULL) + destructor(self); + + if (initialized) + of_tlskey_free(key); + + /* In case we called [self release] in init */ + if (listObject != NULL) { + @synchronized (TLSKeys) { + [TLSKeys removeListObject: listObject]; + } + } + + [super finalize]; +} @end @implementation OFMutex + mutex { @@ -436,10 +470,20 @@ @throw [OFMutexStillLockedException newWithClass: isa mutex: self]; [super dealloc]; } + +- (void)finalize +{ + if (initialized) + if (!of_mutex_free(&mutex)) + @throw [OFMutexStillLockedException newWithClass: isa + mutex: self]; + + [super finalize]; +} @end @implementation OFCondition + condition { @@ -490,6 +534,17 @@ newWithClass: isa condition: self]; [super dealloc]; } + +- (void)finalize +{ + if (conditionInitialized) + if (!of_condition_free(&condition)) + @throw [OFConditionStillWaitingException + newWithClass: isa + condition: self]; + + [super finalize]; +} @end