Add thread priority and checking for selectors.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@14356 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
CaS 2002-08-27 17:02:05 +00:00
parent c958dfe45d
commit 8be710069a
4 changed files with 132 additions and 46 deletions

View file

@ -3,6 +3,8 @@
* Source/Additions/GSXML.m: Integrated GSXPath code by Nicola Pero * Source/Additions/GSXML.m: Integrated GSXPath code by Nicola Pero
provides an API to use the xpath support built into libxml from provides an API to use the xpath support built into libxml from
version 2.3 onwards. version 2.3 onwards.
* Source/NSThread.m: Implement new priority methods.
* Source/NSObject.m: Raise exception when passed null selector.
2002-08-27 Richard Frith-Macdonald <rfm@gnu.org> 2002-08-27 Richard Frith-Macdonald <rfm@gnu.org>

View file

@ -33,13 +33,6 @@
#include <Foundation/NSException.h> #include <Foundation/NSException.h>
#include <Foundation/NSAutoreleasePool.h> // for struct autorelease_thread_vars #include <Foundation/NSAutoreleasePool.h> // for struct autorelease_thread_vars
typedef enum
{
NSInteractiveThreadPriority,
NSBackgroundThreadPriority,
NSLowThreadPriority
} NSThreadPriority;
@interface NSThread : NSObject @interface NSThread : NSObject
{ {
id _target; id _target;
@ -57,12 +50,13 @@ typedef enum
+ (void) detachNewThreadSelector: (SEL)aSelector + (void) detachNewThreadSelector: (SEL)aSelector
toTarget: (id)aTarget toTarget: (id)aTarget
withObject: (id)anArgument; withObject: (id)anArgument;
+ (BOOL) isMultiThreaded;
- (NSMutableDictionary*) threadDictionary;
+ (void) sleepUntilDate: (NSDate*)date;
+ (void) exit; + (void) exit;
+ (BOOL) isMultiThreaded;
+ (void) setThreadPriority: (double)pri;
+ (void) sleepUntilDate: (NSDate*)date;
+ (double) threadPriority;
- (NSMutableDictionary*) threadDictionary;
@end @end

View file

@ -1119,9 +1119,13 @@ static BOOL double_release_check_enabled = NO;
* where a subclass implements -forwardInvocation: to respond to * where a subclass implements -forwardInvocation: to respond to
* selectors not normally handled ... in these cases the subclass * selectors not normally handled ... in these cases the subclass
* may override this method to handle it. * may override this method to handle it.
* <br />Raises NSInvalidArgumentException if given a null selector.
*/ */
+ (BOOL) instancesRespondToSelector: (SEL)aSelector + (BOOL) instancesRespondToSelector: (SEL)aSelector
{ {
if (aSelector == 0)
[NSException raise: NSInvalidArgumentException
format: @"%@ null selector given", NSStringFromSelector(_cmd)];
#if 0 #if 0
return (class_get_instance_method(self, aSelector) != METHOD_NULL); return (class_get_instance_method(self, aSelector) != METHOD_NULL);
#else #else
@ -1170,8 +1174,17 @@ static BOOL double_release_check_enabled = NO;
return [[self class] conformsToProtocol: aProtocol]; return [[self class] conformsToProtocol: aProtocol];
} }
/**
* Returns a pointer to the C function implementing the method used
* to respond to messages with aSelector by instances of the receiving
* class.
* <br />Raises NSInvalidArgumentException if given a null selector.
*/
+ (IMP) instanceMethodForSelector: (SEL)aSelector + (IMP) instanceMethodForSelector: (SEL)aSelector
{ {
if (aSelector == 0)
[NSException raise: NSInvalidArgumentException
format: @"%@ null selector given", NSStringFromSelector(_cmd)];
/* /*
* Since 'self' is an class, get_imp() will get the instance method. * Since 'self' is an class, get_imp() will get the instance method.
*/ */
@ -1181,9 +1194,13 @@ static BOOL double_release_check_enabled = NO;
/** /**
* Returns a pointer to the C function implementing the method used * Returns a pointer to the C function implementing the method used
* to respond to messages with aSelector. * to respond to messages with aSelector.
* <br />Raises NSInvalidArgumentException if given a null selector.
*/ */
- (IMP) methodForSelector: (SEL)aSelector - (IMP) methodForSelector: (SEL)aSelector
{ {
if (aSelector == 0)
[NSException raise: NSInvalidArgumentException
format: @"%@ null selector given", NSStringFromSelector(_cmd)];
/* /*
* If 'self' is an instance, GSObjCClass() will get the class, * If 'self' is an instance, GSObjCClass() will get the class,
* and get_imp() will get the instance method. * and get_imp() will get the instance method.
@ -1197,10 +1214,17 @@ static BOOL double_release_check_enabled = NO;
* Returns a pointer to the C function implementing the method used * Returns a pointer to the C function implementing the method used
* to respond to messages with aSelector whihc are sent to instances * to respond to messages with aSelector whihc are sent to instances
* of the receiving class. * of the receiving class.
* <br />Raises NSInvalidArgumentException if given a null selector.
*/ */
+ (NSMethodSignature*) instanceMethodSignatureForSelector: (SEL)aSelector + (NSMethodSignature*) instanceMethodSignatureForSelector: (SEL)aSelector
{ {
struct objc_method* mth = class_get_instance_method(self, aSelector); struct objc_method *mth;
if (aSelector == 0)
[NSException raise: NSInvalidArgumentException
format: @"%@ null selector given", NSStringFromSelector(_cmd)];
mth = class_get_instance_method(self, aSelector);
return mth ? [NSMethodSignature signatureWithObjCTypes:mth->method_types] return mth ? [NSMethodSignature signatureWithObjCTypes:mth->method_types]
: nil; : nil;
} }
@ -1208,6 +1232,7 @@ static BOOL double_release_check_enabled = NO;
/** /**
* Returns the method signature describing how the receiver would handle * Returns the method signature describing how the receiver would handle
* a message with aSelector. * a message with aSelector.
* <br />Raises NSInvalidArgumentException if given a null selector.
*/ */
- (NSMethodSignature*) methodSignatureForSelector: (SEL)aSelector - (NSMethodSignature*) methodSignatureForSelector: (SEL)aSelector
{ {
@ -1215,9 +1240,9 @@ static BOOL double_release_check_enabled = NO;
struct objc_method *mth; struct objc_method *mth;
if (aSelector == 0) if (aSelector == 0)
{ [NSException raise: NSInvalidArgumentException
return nil; format: @"%@ null selector given", NSStringFromSelector(_cmd)];
}
mth = (GSObjCIsInstance(self) mth = (GSObjCIsInstance(self)
? class_get_instance_method(GSObjCClass(self), aSelector) ? class_get_instance_method(GSObjCClass(self), aSelector)
: class_get_class_method(GSObjCClass(self), aSelector)); : class_get_class_method(GSObjCClass(self), aSelector));
@ -1282,13 +1307,17 @@ static BOOL double_release_check_enabled = NO;
format: @"%s(%s) does not recognize %s", format: @"%s(%s) does not recognize %s",
object_get_class_name(self), object_get_class_name(self),
GSObjCIsInstance(self) ? "instance" : "class", GSObjCIsInstance(self) ? "instance" : "class",
sel_get_name(aSelector)]; aSelector ? sel_get_name(aSelector) : "(null)"];
} }
- (retval_t) forward: (SEL)aSel : (arglist_t)argFrame - (retval_t) forward: (SEL)aSel : (arglist_t)argFrame
{ {
NSInvocation *inv; NSInvocation *inv;
if (aSel == 0)
[NSException raise: NSInvalidArgumentException
format: @"%@ null selector given", NSStringFromSelector(_cmd)];
inv = AUTORELEASE([[NSInvocation alloc] initWithArgframe: argFrame inv = AUTORELEASE([[NSInvocation alloc] initWithArgframe: argFrame
selector: aSel]); selector: aSel]);
[self forwardInvocation: inv]; [self forwardInvocation: inv];
@ -1506,17 +1535,15 @@ static BOOL double_release_check_enabled = NO;
* Causes the receiver to execute the method implementation corresponding * Causes the receiver to execute the method implementation corresponding
* to aSelector and returns the result.<br /> * to aSelector and returns the result.<br />
* The method must be one which takes no arguments and returns an object. * The method must be one which takes no arguments and returns an object.
* <br />Raises NSInvalidArgumentException if given a null selector.
*/ */
- (id) performSelector: (SEL)aSelector - (id) performSelector: (SEL)aSelector
{ {
IMP msg; IMP msg;
if (aSelector == 0) if (aSelector == 0)
{ [NSException raise: NSInvalidArgumentException
[NSException raise: NSInvalidArgumentException format: @"%@ null selector given", NSStringFromSelector(_cmd)];
format: @"null selector passed to %s", sel_get_name(_cmd)];
return nil;
}
msg = get_imp(GSObjCClass(self), aSelector); msg = get_imp(GSObjCClass(self), aSelector);
if (!msg) if (!msg)
@ -1532,17 +1559,15 @@ static BOOL double_release_check_enabled = NO;
* Causes the receiver to execute the method implementation corresponding * Causes the receiver to execute the method implementation corresponding
* to aSelector and returns the result.<br /> * to aSelector and returns the result.<br />
* The method must be one which takes one argument and returns an object. * The method must be one which takes one argument and returns an object.
* <br />Raises NSInvalidArgumentException if given a null selector.
*/ */
- (id) performSelector: (SEL)aSelector withObject: (id) anObject - (id) performSelector: (SEL)aSelector withObject: (id) anObject
{ {
IMP msg; IMP msg;
if (aSelector == 0) if (aSelector == 0)
{ [NSException raise: NSInvalidArgumentException
[NSException raise: NSInvalidArgumentException format: @"%@ null selector given", NSStringFromSelector(_cmd)];
format: @"null selector passed to %s", sel_get_name(_cmd)];
return nil;
}
msg = get_imp(GSObjCClass(self), aSelector); msg = get_imp(GSObjCClass(self), aSelector);
if (!msg) if (!msg)
@ -1559,6 +1584,7 @@ static BOOL double_release_check_enabled = NO;
* Causes the receiver to execute the method implementation corresponding * Causes the receiver to execute the method implementation corresponding
* to aSelector and returns the result.<br /> * to aSelector and returns the result.<br />
* The method must be one which takes two arguments and returns an object. * The method must be one which takes two arguments and returns an object.
* <br />Raises NSInvalidArgumentException if given a null selector.
*/ */
- (id) performSelector: (SEL)aSelector - (id) performSelector: (SEL)aSelector
withObject: (id) object1 withObject: (id) object1
@ -1567,11 +1593,8 @@ static BOOL double_release_check_enabled = NO;
IMP msg; IMP msg;
if (aSelector == 0) if (aSelector == 0)
{ [NSException raise: NSInvalidArgumentException
[NSException raise: NSInvalidArgumentException format: @"%@ null selector given", NSStringFromSelector(_cmd)];
format: @"null selector passed to %s", sel_get_name(_cmd)];
return nil;
}
msg = get_imp(GSObjCClass(self), aSelector); msg = get_imp(GSObjCClass(self), aSelector);
if (!msg) if (!msg)
@ -1631,13 +1654,14 @@ static BOOL double_release_check_enabled = NO;
* where a subclass implements -forwardInvocation: to respond to * where a subclass implements -forwardInvocation: to respond to
* selectors not normally handled ... in these cases the subclass * selectors not normally handled ... in these cases the subclass
* may override this method to handle it. * may override this method to handle it.
* <br />Raises NSInvalidArgumentException if given a null selector.
*/ */
- (BOOL) respondsToSelector: (SEL)aSelector - (BOOL) respondsToSelector: (SEL)aSelector
{ {
if (aSelector == 0) if (aSelector == 0)
{ [NSException raise: NSInvalidArgumentException
return NO; format: @"%@ null selector given", NSStringFromSelector(_cmd)];
}
return __objc_responds_to(self, aSelector); return __objc_responds_to(self, aSelector);
} }
@ -1812,6 +1836,10 @@ static BOOL double_release_check_enabled = NO;
- (retval_t) performv: (SEL)aSel :(arglist_t)argFrame - (retval_t) performv: (SEL)aSel :(arglist_t)argFrame
{ {
if (aSel == 0)
[NSException raise: NSInvalidArgumentException
format: @"%@ null selector given", NSStringFromSelector(_cmd)];
return objc_msg_sendv(self, aSel, argFrame); return objc_msg_sendv(self, aSel, argFrame);
} }
@ -1822,8 +1850,13 @@ static BOOL double_release_check_enabled = NO;
+ (NSMethodSignature*) instanceMethodSignatureForSelector: (SEL)aSelector + (NSMethodSignature*) instanceMethodSignatureForSelector: (SEL)aSelector
{ {
struct objc_method* mth = class_get_instance_method(self, aSelector); struct objc_method* mth;
if (aSelector == 0)
[NSException raise: NSInvalidArgumentException
format: @"%@ null selector given", NSStringFromSelector(_cmd)];
mth = class_get_instance_method(self, aSelector);
return mth ? [NSMethodSignature signatureWithObjCTypes:mth->method_types] return mth ? [NSMethodSignature signatureWithObjCTypes:mth->method_types]
: nil; : nil;
} }
@ -1843,7 +1876,8 @@ static BOOL double_release_check_enabled = NO;
{ {
[NSException [NSException
raise: NSGenericException raise: NSGenericException
format: @"method %s not implemented in %s(%s)", sel_get_name(aSel), format: @"method %s not implemented in %s(%s)",
aSel ? sel_get_name(aSel) : "(null)",
object_get_class_name(self), object_get_class_name(self),
GSObjCIsInstance(self) ? "instance" : "class"]; GSObjCIsInstance(self) ? "instance" : "class"];
return nil; return nil;
@ -1855,7 +1889,7 @@ static BOOL double_release_check_enabled = NO;
format: @"%s(%s) does not recognize %s", format: @"%s(%s) does not recognize %s",
object_get_class_name(self), object_get_class_name(self),
GSObjCIsInstance(self) ? "instance" : "class", GSObjCIsInstance(self) ? "instance" : "class",
sel_get_name(aSel)]; aSel ? sel_get_name(aSel) : "(null)"];
return nil; return nil;
} }
@ -2034,12 +2068,20 @@ static BOOL double_release_check_enabled = NO;
+ (struct objc_method_description *) descriptionForInstanceMethod: (SEL)aSel + (struct objc_method_description *) descriptionForInstanceMethod: (SEL)aSel
{ {
if (aSel == 0)
[NSException raise: NSInvalidArgumentException
format: @"%@ null selector given", NSStringFromSelector(_cmd)];
return ((struct objc_method_description *) return ((struct objc_method_description *)
class_get_instance_method(self, aSel)); class_get_instance_method(self, aSel));
} }
- (struct objc_method_description *) descriptionForMethod: (SEL)aSel - (struct objc_method_description *) descriptionForMethod: (SEL)aSel
{ {
if (aSel == 0)
[NSException raise: NSInvalidArgumentException
format: @"%@ null selector given", NSStringFromSelector(_cmd)];
return ((struct objc_method_description *) return ((struct objc_method_description *)
(GSObjCIsInstance(self) (GSObjCIsInstance(self)
?class_get_instance_method(GSObjCClass(self), aSel) ?class_get_instance_method(GSObjCClass(self), aSel)
@ -2066,7 +2108,7 @@ static BOOL double_release_check_enabled = NO;
format: @"subclass %s(%s) should override %s", format: @"subclass %s(%s) should override %s",
object_get_class_name(self), object_get_class_name(self),
GSObjCIsInstance(self) ? "instance" : "class", GSObjCIsInstance(self) ? "instance" : "class",
sel_get_name(aSel)]; aSel ? sel_get_name(aSel) : "(null)"];
return nil; return nil;
} }
@ -2077,7 +2119,7 @@ static BOOL double_release_check_enabled = NO;
format: @"%s(%s) should not implement %s", format: @"%s(%s) should not implement %s",
object_get_class_name(self), object_get_class_name(self),
GSObjCIsInstance(self) ? "instance" : "class", GSObjCIsInstance(self) ? "instance" : "class",
sel_get_name(aSel)]; aSel ? sel_get_name(aSel) : "(null)"];
return nil; return nil;
} }
@ -2213,6 +2255,10 @@ _fastMallocBuffer(unsigned size)
@implementation NSZombie @implementation NSZombie
- (retval_t) forward:(SEL)aSel :(arglist_t)argFrame - (retval_t) forward:(SEL)aSel :(arglist_t)argFrame
{ {
if (aSel == 0)
[NSException raise: NSInvalidArgumentException
format: @"%@ null selector given", NSStringFromSelector(_cmd)];
GSLogZombie(self, aSel); GSLogZombie(self, aSel);
return 0; return 0;
} }

View file

@ -224,7 +224,7 @@ gnustep_base_thread_callback()
return t; return t;
} }
/* /**
* Create a new thread - use this method rather than alloc-init * Create a new thread - use this method rather than alloc-init
*/ */
+ (void) detachNewThreadSelector: (SEL)aSelector + (void) detachNewThreadSelector: (SEL)aSelector
@ -256,7 +256,7 @@ gnustep_base_thread_callback()
} }
} }
/* /**
* Terminating a thread * Terminating a thread
* What happens if the thread doesn't call +exit - it doesn't terminate! * What happens if the thread doesn't call +exit - it doesn't terminate!
*/ */
@ -326,13 +326,39 @@ gnustep_base_thread_callback()
} }
} }
/**
* Returns a flag to say whether the application is multi-threaded or not.
* An application is considered to be multi-threaded if any thread other
* than the main thread has been started, irrespective of whether that
* thread has since terminated.
*/
+ (BOOL) isMultiThreaded + (BOOL) isMultiThreaded
{ {
return entered_multi_threaded_state; return entered_multi_threaded_state;
} }
/* /**
* Delaying a thread * 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
* system priorities. The current gnu objc runtime supports three
* priority levels which you can obtain using values of 0.0, 0.5, and 1.0
*/
+ (void) setThreadPriority: (double)pri
{
int p;
if (pri <= 0.3)
p = OBJC_THREAD_LOW_PRIORITY;
else if (pri <= 0.6)
p = OBJC_THREAD_BACKGROUND_PRIORITY;
else
p = OBJC_THREAD_INTERACTIVE_PRIORITY;
objc_thread_set_priority(p);
}
/**
* Delaying a thread ... pause until the specified date.
*/ */
+ (void) sleepUntilDate: (NSDate*)date + (void) sleepUntilDate: (NSDate*)date
{ {
@ -374,6 +400,23 @@ gnustep_base_thread_callback()
} }
} }
/**
* Return the priority of the current thread.
*/
+ (double) threadPriority
{
int p = objc_thread_get_priority();
if (p == OBJC_THREAD_LOW_PRIORITY)
return 0.0;
else if (p == OBJC_THREAD_BACKGROUND_PRIORITY)
return 0.5;
else if (p == OBJC_THREAD_INTERACTIVE_PRIORITY)
return 1.0;
else
return 0.0; // Unknown.
}
/* /*
@ -456,8 +499,9 @@ gnustep_base_thread_callback()
[NSThread exit]; [NSThread exit];
} }
/* /**
* Thread dictionary * Return the thread dictionary. This dictionary can be used to store
* arbitrary thread specific data.<br />
* NB. This cannot be autoreleased, since we cannot be sure that the * NB. This cannot be autoreleased, since we cannot be sure that the
* autorelease pool for the thread will continue to exist for the entire * autorelease pool for the thread will continue to exist for the entire
* life of the thread! * life of the thread!