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.