参考GNU的代码实现
+ (void) detachNewThreadSelector: (SEL)aSelector
toTarget: (id)aTarget
withObject: (id)anArgument
{
NSThread *thread;
/*
* Create the new thread.
*/
thread = [[NSThread alloc] initWithTarget: aTarget
selector: aSelector
object: anArgument];
[thread start];
RELEASE(thread);
}
- (id) initWithTarget: (id)aTarget
selector: (SEL)aSelector
object: (id)anArgument
{
/* initialize our ivars. */
_selector = aSelector;
_target = RETAIN(aTarget);
_arg = RETAIN(anArgument);
init_autorelease_thread_vars(&_autorelease_vars);
return self;
}
- (void) start
{
pthread_attr_t attr;
pthread_t thr;
if (_active == YES)
{
[NSException raise: NSInternalInconsistencyException
format: @"[%@-%@] called on active thread",
NSStringFromClass([self class]),
NSStringFromSelector(_cmd)];
}
if (_cancelled == YES)
{
[NSException raise: NSInternalInconsistencyException
format: @"[%@-%@] called on cancelled thread",
NSStringFromClass([self class]),
NSStringFromSelector(_cmd)];
}
if (_finished == YES)
{
[NSException raise: NSInternalInconsistencyException
format: @"[%@-%@] called on finished thread",
NSStringFromClass([self class]),
NSStringFromSelector(_cmd)];
}
/* Make sure the notification is posted BEFORE the new thread starts.
*/
gnustep_base_thread_callback();
/* The thread must persist until it finishes executing.
*/
RETAIN(self);
/* Mark the thread as active whiul it's running.
*/
_active = YES;
errno = 0;
pthread_attr_init(&attr);
/* Create this thread detached, because we never use the return state from
* threads.
*/
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
/* Set the stack size when the thread is created. Unlike the old setrlimit
* code, this actually works.
*/
if (_stackSize > 0)
{
pthread_attr_setstacksize(&attr, _stackSize);
}
if (pthread_create(&thr, &attr, nsthreadLauncher, self))
{
DESTROY(self);
[NSException raise: NSInternalInconsistencyException
format: @"Unable to detach thread (last error %@)",
[NSError _last]];
}
}
- (void) main
{
if (_active == NO)
{
[NSException raise: NSInternalInconsistencyException
format: @"[%@-%@] called on inactive thread",
NSStringFromClass([self class]),
NSStringFromSelector(_cmd)];
}
[_target performSelector: _selector withObject: _arg];
}
+ (void) exit
{
NSThread *t;
t = GSCurrentThread();
if (t->_active == YES)
{
unregisterActiveThread(t);
if (t == defaultThread || defaultThread == nil)
{
/* For the default thread, we exit the process.
*/
exit(0);
}
else
{
pthread_exit(NULL);
}
}
}