Macos-X implementation compatibility changes.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@14242 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
CaS 2002-08-07 13:29:31 +00:00
parent 0422591a90
commit 393abdf85c
5 changed files with 279 additions and 150 deletions

View file

@ -1,6 +1,13 @@
2002-08-07 Richard Frith-Macdonald <rfm@gnu.org> 2002-08-07 Richard Frith-Macdonald <rfm@gnu.org>
* Source/NSString.m: ([-boolValue]) Accept 'true' as well as 'YES' * Source/NSString.m: ([-boolValue]) Accept 'true' as well as 'YES'
* Source/NSThread.m: Modified to avoid using non-standard notification
initialisation.
* Source/NSNotification.m: Rewritten as abstract/cluster class for
implementation compatibility with MacOS-X
* Source/NSNotificationCenter.m: Modified posting to behave like the
MacOS-X implementation. Implement concrete subclass of
NSNotification.
2002-07-29 Adam Fedor <fedor@gnu.org> 2002-07-29 Adam Fedor <fedor@gnu.org>

View file

@ -37,9 +37,6 @@
@interface NSNotification : NSObject <NSCopying, NSCoding> @interface NSNotification : NSObject <NSCopying, NSCoding>
{ {
NSString *_name;
id _object;
NSDictionary *_info;
} }
/* Creating a Notification Object */ /* Creating a Notification Object */
@ -87,11 +84,6 @@
@end @end
#ifndef NO_GNUSTEP #ifndef NO_GNUSTEP
@interface NSNotification (GNUstep)
- (id) initWithName: (NSString*)name
object: (id)object
userInfo: (NSDictionary*)info;
@end
@interface NSNotificationCenter (GNUstep) @interface NSNotificationCenter (GNUstep)
/* /*

View file

@ -29,78 +29,110 @@
#include <Foundation/NSCoder.h> #include <Foundation/NSCoder.h>
#include <Foundation/NSString.h> #include <Foundation/NSString.h>
@implementation NSNotification (GNUstep)
/* <init />
* Initialise a newly created notification.
*/
- (id) initWithName: (NSString*)name
object: (id)object
userInfo: (NSDictionary*)info
{
_name = [name copyWithZone: GSObjCZone(self)];
_object = TEST_RETAIN(object);
_info = TEST_RETAIN(info);
return self;
}
@end
@implementation NSNotification @implementation NSNotification
static Class concreteClass = 0;
@class GSNotification;
+ (NSNotification*) allocWithZone: (NSZone*)z
{
return (id)NSAllocateObject(concreteClass, 0, z);
}
+ (void) initialize
{
if (concreteClass == 0)
{
concreteClass = [GSNotification class];
}
}
/**
* Create a new autoreleased notification. Concrete subclasses override
* this method to create actual notification objects.
*/
+ (NSNotification*) notificationWithName: (NSString*)name + (NSNotification*) notificationWithName: (NSString*)name
object: (id)object object: (id)object
userInfo: (NSDictionary*)info userInfo: (NSDictionary*)info
{ {
return AUTORELEASE([[self allocWithZone: NSDefaultMallocZone()] return [concreteClass notificationWithName: name
initWithName: name object: object userInfo: info]); object: object
userInfo: info];
} }
/**
* Create a new autoreleased notification by calling
* +notificationWithName:object:userInfo: with a nil user info argument.
*/
+ (NSNotification*) notificationWithName: (NSString*)name + (NSNotification*) notificationWithName: (NSString*)name
object: (id)object object: (id)object
{ {
return [self notificationWithName: name object: object userInfo: nil]; return [concreteClass notificationWithName: name
object: object
userInfo: nil];
} }
/**
* The abstract class implements a copy as a simple retain ...
* subclasses should override this to perform more intelligent
* copy operations.
*/
- (id) copyWithZone: (NSZone*)zone - (id) copyWithZone: (NSZone*)zone
{ {
if (NSShouldRetainWithZone (self, zone)) return [self retain];
{
return [self retain];
}
return [[[self class] allocWithZone: zone] initWithName: _name
object: _object
userInfo: _info];
}
- (void) dealloc
{
RELEASE(_name);
TEST_RELEASE(_object);
TEST_RELEASE(_info);
[super dealloc];
} }
/**
* Return a description of the parts of the notification.
*/
- (NSString*) description - (NSString*) description
{ {
return [[super description] stringByAppendingFormat: return [[super description] stringByAppendingFormat:
@" Name: %@ Object: %@ Info: %@", _name, _object, _info]; @" Name: %@ Object: %@ Info: %@",
[self name], [self object], [self userInfo]];
} }
- (id) init
{
if ([self class] == [NSNotification class])
{
NSZone *z = [self zone];
RELEASE(self);
self = (id)NSAllocateObject (concreteClass, 0, z);
}
return self;
}
/**
* Concrete subclasses of NSNotification are responsible for
* implementing this method to return the notification name.
*/
- (NSString*) name - (NSString*) name
{ {
return _name; [self subclassResponsibility: _cmd];
return nil;
} }
/**
* Concrete subclasses of NSNotification are responsible for
* implementing this method to return the notification object.
*/
- (id) object - (id) object
{ {
return _object; [self subclassResponsibility: _cmd];
return nil;
} }
/**
* Concrete subclasses of NSNotification are responsible for
* implementing this method to return the notification user information.
*/
- (NSDictionary*) userInfo - (NSDictionary*) userInfo
{ {
return _info; [self subclassResponsibility: _cmd];
return nil;
} }
/* /*
@ -110,17 +142,32 @@
*/ */
- (void) encodeWithCoder: (NSCoder*)aCoder - (void) encodeWithCoder: (NSCoder*)aCoder
{ {
[aCoder encodeValueOfObjCType: @encode(id) at: &_name]; id o;
[aCoder encodeValueOfObjCType: @encode(id) at: &_object];
[aCoder encodeValueOfObjCType: @encode(id) at: &_info]; o = [self name];
[aCoder encodeValueOfObjCType: @encode(id) at: &o];
o = [self object];
[aCoder encodeValueOfObjCType: @encode(id) at: &o];
o = [self userInfo];
[aCoder encodeValueOfObjCType: @encode(id) at: &o];
} }
- (id) initWithCoder: (NSCoder*)aCoder - (id) initWithCoder: (NSCoder*)aCoder
{ {
[aCoder decodeValueOfObjCType: @encode(id) at: &_name]; NSString *name;
[aCoder decodeValueOfObjCType: @encode(id) at: &_object]; id object;
[aCoder decodeValueOfObjCType: @encode(id) at: &_info]; NSDictionary *info;
return self; id n;
[aCoder decodeValueOfObjCType: @encode(id) at: &name];
[aCoder decodeValueOfObjCType: @encode(id) at: &object];
[aCoder decodeValueOfObjCType: @encode(id) at: &info];
n = [NSNotification notificationWithName: name object: object userInfo: info];
RELEASE(name);
RELEASE(object);
RELEASE(info);
RELEASE(self);
return RETAIN(n);
} }
@end @end

View file

@ -34,9 +34,84 @@
#include <Foundation/NSLock.h> #include <Foundation/NSLock.h>
#include <Foundation/NSThread.h> #include <Foundation/NSThread.h>
typedef struct {
@defs(NSNotification) /**
} NotificationStruct; * Concrete class implementing NSNotification
*/
@interface GSNotification : NSNotification
{
@public
NSString *_name;
id _object;
NSDictionary *_info;
}
@end
@implementation GSNotification
static Class concrete = 0;
+ (void) initialize
{
if (concrete == 0)
{
concrete = [GSNotification class];
}
}
+ (NSNotification*) notificationWithName: (NSString*)name
object: (id)object
userInfo: (NSDictionary*)info
{
GSNotification *n;
n = (GSNotification*)NSAllocateObject(self, 0, NSDefaultMallocZone());
n->_name = [name copyWithZone: GSObjCZone(self)];
n->_object = TEST_RETAIN(object);
n->_info = TEST_RETAIN(info);
return AUTORELEASE(n);
}
- (id) copyWithZone: (NSZone*)zone
{
GSNotification *n;
if (NSShouldRetainWithZone (self, zone))
{
return [self retain];
}
n = (GSNotification*)NSAllocateObject(concrete, 0, NSDefaultMallocZone());
n->_name = [_name copyWithZone: GSObjCZone(self)];
n->_object = TEST_RETAIN(_object);
n->_info = TEST_RETAIN(_info);
return n;
}
- (void) dealloc
{
RELEASE(_name);
TEST_RELEASE(_object);
TEST_RELEASE(_info);
[super dealloc];
}
- (NSString*) name
{
return _name;
}
- (id) object
{
return _object;
}
- (NSDictionary*) userInfo
{
return _info;
}
@end
/* /*
* Garbage collection considerations - * Garbage collection considerations -
@ -485,6 +560,10 @@ static NSNotificationCenter *default_center = nil;
{ {
if (self == [NSNotificationCenter class]) if (self == [NSNotificationCenter class])
{ {
if (concrete == 0)
{
concrete = [GSNotification class];
}
/* /*
* Do alloc and init separately so the default center can refer to * Do alloc and init separately so the default center can refer to
* the 'default_center' variable during initialisation. * the 'default_center' variable during initialisation.
@ -854,35 +933,58 @@ static NSNotificationCenter *default_center = nil;
} }
/* /**
* Post NOTIFICATION to all the observers that match its NAME and OBJECT. * Posts notification to all the observers that match its NAME and OBJECT.<br />
* * The GNUstep implementation calls -postNotificationName:object:userInfo: to
* perform the actual posting.
*/
- (void) postNotification: (NSNotification*)notification
{
[self postNotificationName: [notification name]
object: [notification object]
userInfo: [notification userInfo]];
}
/**
* Creates and posts a notification using the
* -postNotificationName:object:userInfo: passing a nil user info argument.
*/
- (void) postNotificationName: (NSString*)name
object: (id)object
{
[self postNotificationName: name object: object userInfo: nil];
}
/**
* The preferred method for posting a notification.
* <br />
* For performance reasons, we don't wrap an exception handler round every * For performance reasons, we don't wrap an exception handler round every
* message sent to an observer. This means that, if one observer raises * message sent to an observer. This means that, if one observer raises
* an exception, later observers in the lists will not get the notification. * an exception, later observers in the lists will not get the notification.
*/ */
- (void) postNotification: (NSNotification*)notification - (void) postNotificationName: (NSString*)name
object: (id)object
userInfo: (NSDictionary*)info
{ {
NSString *n_name;
id n_object;
Observation *o; Observation *o;
unsigned count; unsigned count;
volatile GSIArray a; volatile GSIArray a;
unsigned arrayBase; unsigned arrayBase;
GSNotification *notification;
if (notification == nil) if (name == nil)
[NSException raise: NSInvalidArgumentException {
format: @"Tried to post a nil notification."]; [NSException raise: NSInvalidArgumentException
format: @"Tried to post a notification with no name."];
n_name = ((NotificationStruct*)notification)->_name; }
n_object = ((NotificationStruct*)notification)->_object; notification = (id)NSAllocateObject(concrete, 0, NSDefaultMallocZone());
if (n_object != nil) name = notification->_name = [name copyWithZone: GSObjCZone(self)];
n_object = CHEATGC(n_object); object = notification->_object = TEST_RETAIN(object);
notification->_info = TEST_RETAIN(info);
if (n_name == nil) if (object != nil)
[NSException raise: NSInvalidArgumentException {
format: @"Tried to post a notification with no name."]; object = CHEATGC(object);
}
lockNCTable(TABLE); lockNCTable(TABLE);
a = ARRAY; a = ARRAY;
@ -922,9 +1024,9 @@ static NSNotificationCenter *default_center = nil;
* Post the notification to all the observers that specified OBJECT, * Post the notification to all the observers that specified OBJECT,
* but didn't specify NAME. * but didn't specify NAME.
*/ */
if (n_object) if (object)
{ {
n = GSIMapNodeForSimpleKey(NAMELESS, (GSIMapKey)n_object); n = GSIMapNodeForSimpleKey(NAMELESS, (GSIMapKey)object);
if (n != 0) if (n != 0)
{ {
o = n->value.ext; o = n->value.ext;
@ -941,19 +1043,23 @@ static NSNotificationCenter *default_center = nil;
* observers with a non-nil OBJECT that doesn't match the * observers with a non-nil OBJECT that doesn't match the
* notification's OBJECT). * notification's OBJECT).
*/ */
if (n_name) if (name)
{ {
n = GSIMapNodeForKey(NAMED, (GSIMapKey)n_name); n = GSIMapNodeForKey(NAMED, (GSIMapKey)name);
if (n) if (n)
m = (GSIMapTable)n->value.ptr; {
m = (GSIMapTable)n->value.ptr;
}
else else
m = 0; {
m = 0;
}
if (m != 0) if (m != 0)
{ {
/* /*
* First, observers with a matching object. * First, observers with a matching object.
*/ */
n = GSIMapNodeForSimpleKey(m, (GSIMapKey)n_object); n = GSIMapNodeForSimpleKey(m, (GSIMapKey)object);
if (n != 0) if (n != 0)
{ {
o = n->value.ext; o = n->value.ext;
@ -965,7 +1071,7 @@ static NSNotificationCenter *default_center = nil;
} }
} }
if (n_object != nil) if (object != nil)
{ {
/* /*
* Now observers with a nil object. * Now observers with a nil object.
@ -1008,9 +1114,9 @@ static NSNotificationCenter *default_center = nil;
* Post the notification to all the observers that specified OBJECT, * Post the notification to all the observers that specified OBJECT,
* but didn't specify NAME. * but didn't specify NAME.
*/ */
if (n_object) if (object)
{ {
n = GSIMapNodeForSimpleKey(NAMELESS, (GSIMapKey)n_object); n = GSIMapNodeForSimpleKey(NAMELESS, (GSIMapKey)object);
if (n != 0) if (n != 0)
{ {
o = n->value.ext; o = n->value.ext;
@ -1035,19 +1141,23 @@ static NSNotificationCenter *default_center = nil;
* observers with a non-nil OBJECT that doesn't match the * observers with a non-nil OBJECT that doesn't match the
* notification's OBJECT). * notification's OBJECT).
*/ */
if (n_name) if (name)
{ {
n = GSIMapNodeForKey(NAMED, (GSIMapKey)n_name); n = GSIMapNodeForKey(NAMED, (GSIMapKey)name);
if (n) if (n)
m = (GSIMapTable)n->value.ptr; {
m = (GSIMapTable)n->value.ptr;
}
else else
m = 0; {
m = 0;
}
if (m != 0) if (m != 0)
{ {
/* /*
* First, observers with a matching object. * First, observers with a matching object.
*/ */
n = GSIMapNodeForSimpleKey(m, (GSIMapKey)n_object); n = GSIMapNodeForSimpleKey(m, (GSIMapKey)object);
if (n != 0) if (n != 0)
{ {
o = n->value.ext; o = n->value.ext;
@ -1058,7 +1168,7 @@ static NSNotificationCenter *default_center = nil;
} }
} }
if (n_object != nil) if (object != nil)
{ {
/* /*
* Now observers with a nil object. * Now observers with a nil object.
@ -1097,28 +1207,14 @@ static NSNotificationCenter *default_center = nil;
GSIArrayRemoveItemsFromIndex(ARRAY, arrayBase); GSIArrayRemoveItemsFromIndex(ARRAY, arrayBase);
unlockNCTable(TABLE); unlockNCTable(TABLE);
DESTROY(notification); // Get rid of notification we created.
[localException raise]; [localException raise];
} }
NS_ENDHANDLER NS_ENDHANDLER
#endif #endif
unlockNCTable(TABLE); unlockNCTable(TABLE);
} RELEASE(notification);
- (void) postNotificationName: (NSString*)name
object: (id)object
{
[self postNotification: [NSNotification notificationWithName: name
object: object]];
}
- (void) postNotificationName: (NSString*)name
object: (id)object
userInfo: (NSDictionary*)info
{
[self postNotification: [NSNotification notificationWithName: name
object: object
userInfo: info]];
} }
@end @end

View file

@ -41,6 +41,7 @@
#include <Foundation/NSNotificationQueue.h> #include <Foundation/NSNotificationQueue.h>
static Class threadClass = Nil; static Class threadClass = Nil;
static NSNotificationCenter *nc = nil;
#ifndef NO_GNUSTEP #ifndef NO_GNUSTEP
#if !defined(HAVE_OBJC_THREAD_ADD) && !defined(NeXT_RUNTIME) #if !defined(HAVE_OBJC_THREAD_ADD) && !defined(NeXT_RUNTIME)
@ -156,15 +157,14 @@ gnustep_base_thread_callback()
*/ */
if (entered_multi_threaded_state == NO) if (entered_multi_threaded_state == NO)
{ {
NSNotification *n;
entered_multi_threaded_state = YES; entered_multi_threaded_state = YES;
n = [NSNotification alloc]; if (nc == nil)
n = [n initWithName: NSWillBecomeMultiThreadedNotification {
object: nil nc = [NSNotificationCenter defaultCenter];
userInfo: nil]; }
[[NSNotificationCenter defaultCenter] postNotification: n]; [nc postNotificationName: NSWillBecomeMultiThreadedNotification
RELEASE(n); object: nil
userInfo: nil];
} }
} }
@ -248,8 +248,6 @@ gnustep_base_thread_callback()
t = GSCurrentThread(); t = GSCurrentThread();
if (t->_active == YES) if (t->_active == YES)
{ {
NSNotification *n;
/* /*
* Set the thread to be inactive to avoid any possibility of recursion. * Set the thread to be inactive to avoid any possibility of recursion.
*/ */
@ -258,12 +256,13 @@ gnustep_base_thread_callback()
/* /*
* Let observers know this thread is exiting. * Let observers know this thread is exiting.
*/ */
n = [NSNotification alloc]; if (nc == nil)
n = [n initWithName: NSThreadWillExitNotification {
object: t nc = [NSNotificationCenter defaultCenter];
userInfo: nil]; }
[[NSNotificationCenter defaultCenter] postNotification: n]; [nc postNotificationName: NSThreadWillExitNotification
RELEASE(n); object: t
userInfo: nil];
/* /*
* destroy the thread object. * destroy the thread object.
@ -413,10 +412,6 @@ gnustep_base_thread_callback()
- (void) _sendThreadMethod - (void) _sendThreadMethod
{ {
#ifndef NO_GNUSTEP
NSNotification *n;
#endif
/* /*
* 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
* dictionary and release ourself - thus, when the thread exits, we will * dictionary and release ourself - thus, when the thread exits, we will
@ -429,12 +424,13 @@ gnustep_base_thread_callback()
/* /*
* Let observers know a new thread is starting. * Let observers know a new thread is starting.
*/ */
n = [NSNotification alloc]; if (nc == nil)
n = [n initWithName: NSThreadDidStartNotification {
object: self nc = [NSNotificationCenter defaultCenter];
userInfo: nil]; }
[[NSNotificationCenter defaultCenter] postNotification: n]; [nc postNotificationName: NSThreadDidStartNotification
RELEASE(n); object: self
userInfo: nil];
#endif #endif
[_target performSelector: _selector withObject: _arg]; [_target performSelector: _selector withObject: _arg];
@ -517,21 +513,11 @@ void
GSUnregisterCurrentThread (void) GSUnregisterCurrentThread (void)
{ {
NSThread *thread; NSThread *thread;
static NSNotificationCenter *nc = nil;
static Class notificationClass = Nil;
if (nc == nil)
{
nc = [NSNotificationCenter defaultCenter];
notificationClass = [NSNotification class];
}
thread = GSCurrentThread(); thread = GSCurrentThread();
if (((NSThread_ivars *)thread)->_active == YES) if (((NSThread_ivars *)thread)->_active == YES)
{ {
NSNotification *n;
/* /*
* Set the thread to be inactive to avoid any possibility of recursion. * Set the thread to be inactive to avoid any possibility of recursion.
*/ */
@ -540,12 +526,13 @@ GSUnregisterCurrentThread (void)
/* /*
* Let observers know this thread is exiting. * Let observers know this thread is exiting.
*/ */
n = [notificationClass alloc]; if (nc == nil)
n = [n initWithName: NSThreadWillExitNotification {
object: thread nc = [NSNotificationCenter defaultCenter];
userInfo: nil]; }
[nc postNotification: n]; [nc postNotificationName: NSThreadWillExitNotification
RELEASE(n); object: thread
userInfo: nil];
/* /*
* destroy the thread object. * destroy the thread object.