mirror of
https://github.com/gnustep/libs-base.git
synced 2025-05-31 16:50:58 +00:00
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:
parent
8d867b011f
commit
ef82327d8e
4 changed files with 203 additions and 25 deletions
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue