Re: [Pyobjc-dev] threads + autoreleasepools
Brought to you by:
ronaldoussoren
From: <bb...@ma...> - 2003-02-15 22:56:15
|
On Saturday, Feb 15, 2003, at 17:52 US/Eastern, Just van Rossum wrote: > Hm, this crashes when I use it from a different thread (shortly after > calling pyobjcPopPool()). I wonder whether this has anything to do with > autoGIL :-/ You are popping in the same thread that you pushed the release pool, correct? Release pools are thread specific. On Saturday, Feb 15, 2003, at 17:37 US/Eastern, Just van Rossum wrote: >> But I agree with you, I think alloc/init for NSAutoreleasePool should >> work as we're all used to. > > Well, not me, as I'm still pretty much a Cocoa newbie ;-) I have always thought that the autorelease pool implementation in the Foundation was broken. Autorelease pools are stack based and are context dependent upon the thread. Therefore, the NSAutoreleasePool API should have a push/pop that does the right thing on a thread aware basis. Which is exactly what the aforementioned category does (see below, it is short) -- does now, anyway, I just fixed a stupid memory leak in it. Ooops. The category isn't exactly fast, but the developer should never push/pop that many release pools anyway. static NSString *_threadPoolIdentifier = @"PyObjC: NSThread AutoreleasePool Identifier."; @interface NSAutoreleasePool(PyObjCPushPopSupport) @end @implementation NSAutoreleasePool (PyObjCPushPopSupport) + (NSMutableArray *) pyobjcPoolStackForCurrentThread { NSMutableDictionary *threadDictionary = [[NSThread currentThread] threadDictionary]; NSMutableArray *poolStack; poolStack = [threadDictionary objectForKey: _threadPoolIdentifier]; if (!poolStack) { poolStack = [NSMutableArray array]; [threadDictionary setObject: poolStack forKey: _threadPoolIdentifier]; } return poolStack; } + (void) pyobjcPushPool { NSAutoreleasePool *p = [[NSAutoreleasePool alloc] init]; [[self pyobjcPoolStackForCurrentThread] addObject: [NSValue valueWithNonretainedObject: p]]; } + (void) pyobjcPopPool { NSMutableArray *poolStack = [self pyobjcPoolStackForCurrentThread]; NSValue *pValue = [poolStack lastObject]; [[pValue objectValue] release]; [poolStack removeLastObject]; } @end |