User-space threads and NSAutoreleasePool
User-space threads and NSAutoreleasePool
- Subject: User-space threads and NSAutoreleasePool
- From: BJ Homer <email@hidden>
- Date: Wed, 17 Mar 2010 22:11:34 -0600
Hi everyone,
Some setup, first. If you just want to jump to the question, jump to the
last paragraph.
OS X includes (as part of its UNIX heritage) functions for implementing
user-space threading. (See, for example, the man page on
swapcontext<http://developer.apple.com/Mac/library/documentation/Darwin/Reference/ManPages/man3/swapcontext.3.html>.)
This allows developers to swap out the current stack for another, in effect
allowing two threads of execution on a single thread. Using kernel-level
threads is, naturally, simpler, but due to the cost of kernel-level context
switches, they don't scale well. (You just can't run 500 threads at once
very well.) User-space threads require more programmer attention, certainly,
but also allow certain programming models that can't be done otherwise. For
example, they can be used for coroutines, cooperative threading, or all
sorts of esoteric-yet-sometimes-useful effects.
I say all that in an effort to avoid the frequent "you're fighting the
frameworks" responses. I'm well familiar with the frameworks, GCD, etc., and
in this particular case, user-space threads is what I need.
The problem is that when you call swapcontext() to switch the user-thread
running on a kernel-thread, the NSAutoreleasePool stack is not swapped out.
It remains rooted in thread-local storage. As a result, serious problems
result. Let me give an example.
- (void)doStuff {
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
// do some stuff that calls swapcontext()
[pool drain];
}
-doStuff calls swapcontext(), trusting that the other user-thread will
eventually call swapcontext() and restore the flow to this user-thread.
Further, assume that the second user-thread also allocates an autorelease
pool before returning. Despite being on separate user-threads, there is
still only one kernel-thread. Since the autorelease pool stack is in
(kernel-)thread-local storage, the second user-thread's pool goes on top of
the same stack:
Autorelease pool stack: pool_from_uthread1 -> pool_from_uthread2
Now, when we swap back to the first user-thread, it will release its
autorelease pool. This, naturally, releases the second pool as well. When we
swap back to the second user-thread, anything that was autoreleased is now
dead and gone.
Okay, so that's the setup. Obviously, the problem is that the two user-space
threads are sharing an autorelease pool stack that is intended to be
thread-local. My question, then, is whether there exists a way to get and
set the autorelease pool stack, so that before calling swapcontext(), I
could put it in a state appropriate for this user-level thread? I assume it
is being stored in thread-local storage, but it's not in the NSThread
threadDictionary, which means it's probably set using pthread_setspecific.
Accessing that value would require the key used to store it, but naturally I
don't have access to that. So is there some existing function call that
allows such access?
Thanks for listening,
-BJ Homer
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden