Implement part of MacOS 10.5 additions for NSThread.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@25607 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
rfm 2007-11-25 14:25:26 +00:00
parent 8d867b011f
commit ef82327d8e
4 changed files with 203 additions and 25 deletions

View file

@ -1,3 +1,10 @@
2007-11-25 Richard Frith-Macdonald <rfm@gnu.org>
* Headers/Foundation/NSThread.h: Add new methods from MacOS 10.5
* Source/NSThread.m: Implement some new MacOS-5 stuff and add stubs
for stack size and thread cancellation.
* Source/NSException.m Implement ([NSThread+callStackReturnAddresses])
2007-11-09 Adam Fedor <fedor@gnu.org> 2007-11-09 Adam Fedor <fedor@gnu.org>
* Version 1.15.1 * Version 1.15.1

View file

@ -32,6 +32,8 @@
#import <Foundation/NSException.h> #import <Foundation/NSException.h>
#import <Foundation/NSAutoreleasePool.h> // for struct autorelease_thread_vars #import <Foundation/NSAutoreleasePool.h> // for struct autorelease_thread_vars
@class NSArray;
#if defined(__cplusplus) #if defined(__cplusplus)
extern "C" { extern "C" {
#endif #endif
@ -41,7 +43,10 @@ extern "C" {
id _target; id _target;
id _arg; id _arg;
SEL _selector; SEL _selector;
NSString *_name;
unsigned _stackSize;
@public @public
BOOL _cancelled;
BOOL _active; BOOL _active;
NSHandler *_exception_handler; NSHandler *_exception_handler;
NSMutableDictionary *_thread_dictionary; NSMutableDictionary *_thread_dictionary;
@ -55,12 +60,82 @@ extern "C" {
withObject: (id)anArgument; withObject: (id)anArgument;
+ (void) exit; + (void) exit;
+ (BOOL) isMultiThreaded; + (BOOL) isMultiThreaded;
+ (void) setThreadPriority: (double)pri;
+ (void) sleepUntilDate: (NSDate*)date; + (void) sleepUntilDate: (NSDate*)date;
+ (double) threadPriority;
- (NSMutableDictionary*) threadDictionary; - (NSMutableDictionary*) threadDictionary;
#if OS_API_VERSION(100200,GS_API_LATEST) && GS_API_VERSION(010200,GS_API_LATEST)
+ (void) setThreadPriority: (double)pri;
+ (double) threadPriority;
#endif
#if OS_API_VERSION(100500,GS_API_LATEST) && GS_API_VERSION(011501,GS_API_LATEST)
/** Returns an array of the call stack return addresses.
*/
+ (NSArray*) callStackReturnAddresses;
/** Returns the main thread of the process.
*/
+ (NSThread*) mainThread;
/** Suspends execution of the process for the specified period.
*/
+ (void) sleepForTimeInterval: (NSTimeInterval)ti;
/** Cancels the receiving thread.
*/
- (void) cancel;
/** </init>
*/
- (id) init;
/** Initialises the receiver to send the message aSelector to the object aTarget
* with the argument anArgument (which may be nil).<br />
* The arguments aTarget and aSelector are retained while the thread is
* running.
*/
- (id) initWithTarget: (id)aTarget
selector: (SEL)aSelector
object: (id)anArgument;
/** Returns a boolean indicating whether the receiving
* thread has been cancelled.
*/
- (BOOL) isCancelled;
/** Returns a boolean indicating whether the receiving
* thread has been started (and has not yet finished or been cancelled).
*/
- (BOOL) isExecuting;
/** Returns a boolean indicating whether this thread is the main thread of
* the process.
*/
- (BOOL) isMainThread;
/** Returns the name of the receiver.
*/
- (NSString*) name;
/** Sets the name of the receiver.
*/
- (void) setName: (NSString*)aName;
/** Sets the size of the receiver's stack.
*/
- (void) setStackSize: (unsigned)stackSize;
/** Returns the size of the receiver's stack.
*/
- (unsigned) stackSize;
/** Starts the receiver executing.
*/
- (void) start;
#endif
@end @end
#if GS_API_VERSION(GS_API_MACOSX, GS_API_LATEST) #if GS_API_VERSION(GS_API_MACOSX, GS_API_LATEST)

View file

@ -36,6 +36,7 @@
#include "Foundation/NSThread.h" #include "Foundation/NSThread.h"
#include "Foundation/NSLock.h" #include "Foundation/NSLock.h"
#include "Foundation/NSDictionary.h" #include "Foundation/NSDictionary.h"
#include "Foundation/NSValue.h"
#include <stdio.h> #include <stdio.h>
#if defined(__MINGW32__) #if defined(__MINGW32__)
@ -83,6 +84,7 @@ GSPrivateBaseAddress(void *addr, void **base)
- (NSString*) description; - (NSString*) description;
- (NSEnumerator*) enumerator; - (NSEnumerator*) enumerator;
- (NSMutableArray*) frames;
- (id) frameAt: (unsigned)index; - (id) frameAt: (unsigned)index;
- (unsigned) frameCount; - (unsigned) frameCount;
- (NSEnumerator*) reverseEnumerator; - (NSEnumerator*) reverseEnumerator;
@ -513,9 +515,7 @@ GSListModules()
- (oneway void) dealloc - (oneway void) dealloc
{ {
[frames release]; DESTROY(frames);
frames = nil;
[super dealloc]; [super dealloc];
} }
@ -550,6 +550,11 @@ GSListModules()
return [frames count]; return [frames count];
} }
- (NSMutableArray*) frames
{
return frames;
}
// grab the current stack // grab the current stack
- (id) init - (id) init
{ {
@ -644,6 +649,30 @@ GSListModules()
@end @end
/**
* Get a stack trace and convert it to an array of return addresses.
*/
@interface NSThread (Frames)
+ (NSArray*) callStackReturnAddresses;
@end
@implementation NSThread (Frames)
+ (NSArray*) callStackReturnAddresses
{
NSMutableArray *frames = [[GSStackTrace currentStack] frames];
unsigned count = [frames count];
while (count-- > 0)
{
GSFunctionInfo *info = [frames objectAtIndex: count];
NSValue *address;
address = [NSValue valueWithPointer: [info address]];
[frames replaceObjectAtIndex: count
withObject: address];
}
return frames;
}
@end

View file

@ -247,11 +247,6 @@ inline static void objc_thread_remove (void)
} }
#endif /* not HAVE_OBJC_THREAD_ADD */ #endif /* not HAVE_OBJC_THREAD_ADD */
@interface NSThread (Private)
- (id) _initWithSelector: (SEL)s toTarget: (id)t withObject: (id)o;
- (void) _sendThreadMethod;
@end
/* /*
* Flag indicating whether the objc runtime ever went multi-threaded. * Flag indicating whether the objc runtime ever went multi-threaded.
*/ */
@ -485,6 +480,16 @@ gnustep_base_thread_callback(void)
*/ */
@implementation NSThread @implementation NSThread
+ (NSArray*) callStackReturnAddresses
{
/* NB. This method is actually implemented in a category in
* The NSException.m file as the stack trace code there is
* able to set up an array of stack addresses and we don't
* want to duplicate the code.
*/
return [self notImplemented: _cmd];
}
/** /**
* <p> * <p>
* Returns the NSThread object corresponding to the current thread. * Returns the NSThread object corresponding to the current thread.
@ -543,14 +548,14 @@ gnustep_base_thread_callback(void)
* Create the new thread. * Create the new thread.
*/ */
thread = (NSThread*)NSAllocateObject(self, 0, NSDefaultMallocZone()); thread = (NSThread*)NSAllocateObject(self, 0, NSDefaultMallocZone());
thread = [thread _initWithSelector: aSelector thread = [thread initWithTarget: aTarget
toTarget: aTarget selector: aSelector
withObject: anArgument]; object: anArgument];
/* /*
* Have the runtime detach the thread * Have the runtime detach the thread
*/ */
if (objc_thread_detach(@selector(_sendThreadMethod), thread, nil) == NULL) if (objc_thread_detach(@selector(start), thread, nil) == NULL)
{ {
[NSException raise: NSInternalInconsistencyException [NSException raise: NSInternalInconsistencyException
format: @"Unable to detach thread (unknown error)"]; format: @"Unable to detach thread (unknown error)"];
@ -621,9 +626,7 @@ gnustep_base_thread_callback(void)
*/ */
defaultThread defaultThread
= (NSThread*)NSAllocateObject(self, 0, NSDefaultMallocZone()); = (NSThread*)NSAllocateObject(self, 0, NSDefaultMallocZone());
defaultThread = [defaultThread _initWithSelector: (SEL)0 defaultThread = [defaultThread init];
toTarget: nil
withObject: nil];
defaultThread->_active = YES; defaultThread->_active = YES;
objc_thread_set_data(defaultThread); objc_thread_set_data(defaultThread);
threadClass = self; threadClass = self;
@ -643,6 +646,11 @@ gnustep_base_thread_callback(void)
return entered_multi_threaded_state; return entered_multi_threaded_state;
} }
+ (NSThread*) mainThread
{
return defaultThread;
}
/** /**
* Set the priority of the current thread. This is a value in the * Set the priority of the current thread. This is a value in the
* range 0.0 (lowest) to 1.0 (highest) which is mapped to the underlying * range 0.0 (lowest) to 1.0 (highest) which is mapped to the underlying
@ -663,6 +671,15 @@ gnustep_base_thread_callback(void)
objc_thread_set_priority(p); objc_thread_set_priority(p);
} }
+ (void) sleepForTimeInterval: (NSTimeInterval)ti
{
if (ti > 0.0)
{
GSSleepUntilIntervalSinceReferenceDate(
[NSDate timeIntervalSinceReferenceDate] + ti);
}
}
/** /**
* Delaying a thread ... pause until the specified date. * Delaying a thread ... pause until the specified date.
*/ */
@ -695,6 +712,16 @@ gnustep_base_thread_callback(void)
* Thread instance methods. * Thread instance methods.
*/ */
- (void) cancel
{
_cancelled = YES;
if (_active == YES)
{
[self notImplemented: _cmd];
// FIXME
}
}
- (void) dealloc - (void) dealloc
{ {
if (_active == YES) if (_active == YES)
@ -705,6 +732,7 @@ gnustep_base_thread_callback(void)
DESTROY(_thread_dictionary); DESTROY(_thread_dictionary);
DESTROY(_target); DESTROY(_target);
DESTROY(_arg); DESTROY(_arg);
DESTROY(_name);
if (_autorelease_vars.pool_cache != 0) if (_autorelease_vars.pool_cache != 0)
{ {
[NSAutoreleasePool _endThread: self]; [NSAutoreleasePool _endThread: self];
@ -739,24 +767,63 @@ gnustep_base_thread_callback(void)
- (id) init - (id) init
{ {
RELEASE(self); return self;
return [NSThread currentThread];
} }
- (id) _initWithSelector: (SEL)s toTarget: (id)t withObject: (id)o - (id) initWithTarget: (id)aTarget
selector: (SEL)aSelector
object: (id)anArgument
{ {
/* initialize our ivars. */ /* initialize our ivars. */
_selector = s; _selector = aSelector;
_target = RETAIN(t); _target = RETAIN(aTarget);
_arg = RETAIN(o); _arg = RETAIN(anArgument);
_thread_dictionary = nil; // Initialize this later only when needed _thread_dictionary = nil; // Initialize this later only when needed
_exception_handler = NULL; _exception_handler = NULL;
_cancelled = NO;
_active = NO; _active = NO;
_name = nil;
init_autorelease_thread_vars(&_autorelease_vars); init_autorelease_thread_vars(&_autorelease_vars);
return self; return self;
} }
- (void) _sendThreadMethod - (BOOL) isCancelled
{
return _cancelled;
}
- (BOOL) isExecuting
{
return _active;
}
- (BOOL) isMainThread
{
return (self == defaultThread ? YES : NO);
}
- (NSString*) name
{
return _name;
}
- (void) setName: (NSString*)aName
{
ASSIGN(_name, aName);
}
- (void) setStackSize: (unsigned)stackSize
{
[self notImplemented: _cmd];
_stackSize = stackSize; // FIXME
}
- (unsigned) stackSize
{
return _stackSize;
}
- (void) start
{ {
/* /*
* We are running in the new thread - so we store ourself in the thread * We are running in the new thread - so we store ourself in the thread
@ -1149,7 +1216,7 @@ GSRegisterCurrentThread (void)
*/ */
thread = (NSThread*)NSAllocateObject (threadClass, 0, thread = (NSThread*)NSAllocateObject (threadClass, 0,
NSDefaultMallocZone ()); NSDefaultMallocZone ());
thread = [thread _initWithSelector: NULL toTarget: nil withObject: nil]; thread = [thread init];
objc_thread_set_data (thread); objc_thread_set_data (thread);
((NSThread_ivars *)thread)->_active = YES; ((NSThread_ivars *)thread)->_active = YES;
} }