This is Autorelease.m in view mode; [Download] [Up]
#import "Autorelease.h" #import <appkit/appkit.h> static id autoreleasePool = nil; static void gc_handler(DPSTimedEntry tag, double now, void *userData); @implementation AutoreleaseObject - init { [super init]; retainCount = 1; return self; } - incrementRetainCount { retainCount++; return self; } - decrementRetainCount { retainCount--; return self; } - (unsigned int) retainCount { return retainCount; } - free { if([self retainCount] > 1) { NXLogError("Free called for instance 0x%X of class %s with retainCount of %d!", self, [self name], retainCount); return nil; } // NXLogError("Free called for instance 0x%X of class %s.", self, [self name]); return [super free]; } @end @implementation Object (AutoreleaseCategory) - autorelease { if(!autoreleasePool) { autoreleasePool = [[List alloc] init]; /* * Kick off a "garbage collector" for the list. Make the period, every 0.0 seconds * so it does it the first chance it gets (I remove the handler in the handler) and * set the threshold to NX_BASETHRESHOLD so that it isn't called during modal sessions * since this would mean that a alert panal might cause garbage collection which we don't * want to happen. */ DPSAddTimedEntry(0.0, gc_handler, (void *)0, NX_BASETHRESHOLD); } [autoreleasePool addObject: self]; return self; } - (void) release { unsigned int cnt = [(AutoreleaseObject *)self retainCount]; if(!cnt) NXLogError("Release called for instance 0x%X of class %s with retainCount of 0!", self, [self name]); else { if(cnt == 1) [self free]; else [(AutoreleaseObject *)self decrementRetainCount]; } } - retain { [(AutoreleaseObject *)self incrementRetainCount]; return self; } - dealloc { return [self free]; } @end static void gc_handler(DPSTimedEntry tag, double now, void *userData) { int x, cnt; id (*objectAt)(id,SEL,int); DPSRemoveTimedEntry(tag); /* only call this once */ if(!autoreleasePool) return; /* * Can't use List's makeObjectsPerform: since it traveres the list * in reverse order. The objects may have been autoreleased in a specific order... */ cnt = [autoreleasePool count]; if(cnt) { objectAt = (id (*)(id,SEL,int))[autoreleasePool methodFor: @selector(objectAt:)]; for(x = 0; x < cnt; x++) [objectAt(autoreleasePool,@selector(objectAt:),x) release]; } [autoreleasePool free]; autoreleasePool = nil; }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.