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:
Richard Frith-Macdonald 2002-08-07 13:29:31 +00:00
parent cb508560f8
commit a702331098
5 changed files with 279 additions and 150 deletions

View file

@ -1,6 +1,13 @@
2002-08-07 Richard Frith-Macdonald <rfm@gnu.org>
* 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>

View file

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

View file

@ -29,78 +29,110 @@
#include <Foundation/NSCoder.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
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
object: (id)object
userInfo: (NSDictionary*)info
{
return AUTORELEASE([[self allocWithZone: NSDefaultMallocZone()]
initWithName: name object: object userInfo: info]);
return [concreteClass notificationWithName: name
object: object
userInfo: info];
}
/**
* Create a new autoreleased notification by calling
* +notificationWithName:object:userInfo: with a nil user info argument.
*/
+ (NSNotification*) notificationWithName: (NSString*)name
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
{
if (NSShouldRetainWithZone (self, zone))
{
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 [self retain];
}
/**
* Return a description of the parts of the notification.
*/
- (NSString*) description
{
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
{
return _name;
[self subclassResponsibility: _cmd];
return nil;
}
/**
* Concrete subclasses of NSNotification are responsible for
* implementing this method to return the notification 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
{
return _info;
[self subclassResponsibility: _cmd];
return nil;
}
/*
@ -110,17 +142,32 @@
*/
- (void) encodeWithCoder: (NSCoder*)aCoder
{
[aCoder encodeValueOfObjCType: @encode(id) at: &_name];
[aCoder encodeValueOfObjCType: @encode(id) at: &_object];
[aCoder encodeValueOfObjCType: @encode(id) at: &_info];
id o;
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
{
[aCoder decodeValueOfObjCType: @encode(id) at: &_name];
[aCoder decodeValueOfObjCType: @encode(id) at: &_object];
[aCoder decodeValueOfObjCType: @encode(id) at: &_info];
return self;
NSString *name;
id object;
NSDictionary *info;
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

View file

@ -34,9 +34,84 @@
#include <Foundation/NSLock.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 -
@ -485,6 +560,10 @@ static NSNotificationCenter *default_center = nil;
{
if (self == [NSNotificationCenter class])
{
if (concrete == 0)
{
concrete = [GSNotification class];
}
/*
* Do alloc and init separately so the default center can refer to
* 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
* message sent to an observer. This means that, if one observer raises
* 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;
unsigned count;
volatile GSIArray a;
unsigned arrayBase;
GSNotification *notification;
if (notification == nil)
[NSException raise: NSInvalidArgumentException
format: @"Tried to post a nil notification."];
n_name = ((NotificationStruct*)notification)->_name;
n_object = ((NotificationStruct*)notification)->_object;
if (n_object != nil)
n_object = CHEATGC(n_object);
if (n_name == nil)
[NSException raise: NSInvalidArgumentException
format: @"Tried to post a notification with no name."];
if (name == nil)
{
[NSException raise: NSInvalidArgumentException
format: @"Tried to post a notification with no name."];
}
notification = (id)NSAllocateObject(concrete, 0, NSDefaultMallocZone());
name = notification->_name = [name copyWithZone: GSObjCZone(self)];
object = notification->_object = TEST_RETAIN(object);
notification->_info = TEST_RETAIN(info);
if (object != nil)
{
object = CHEATGC(object);
}
lockNCTable(TABLE);
a = ARRAY;
@ -922,9 +1024,9 @@ static NSNotificationCenter *default_center = nil;
* Post the notification to all the observers that specified OBJECT,
* but didn't specify NAME.
*/
if (n_object)
if (object)
{
n = GSIMapNodeForSimpleKey(NAMELESS, (GSIMapKey)n_object);
n = GSIMapNodeForSimpleKey(NAMELESS, (GSIMapKey)object);
if (n != 0)
{
o = n->value.ext;
@ -941,19 +1043,23 @@ static NSNotificationCenter *default_center = nil;
* observers with a non-nil OBJECT that doesn't match the
* notification's OBJECT).
*/
if (n_name)
if (name)
{
n = GSIMapNodeForKey(NAMED, (GSIMapKey)n_name);
n = GSIMapNodeForKey(NAMED, (GSIMapKey)name);
if (n)
m = (GSIMapTable)n->value.ptr;
{
m = (GSIMapTable)n->value.ptr;
}
else
m = 0;
{
m = 0;
}
if (m != 0)
{
/*
* First, observers with a matching object.
*/
n = GSIMapNodeForSimpleKey(m, (GSIMapKey)n_object);
n = GSIMapNodeForSimpleKey(m, (GSIMapKey)object);
if (n != 0)
{
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.
@ -1008,9 +1114,9 @@ static NSNotificationCenter *default_center = nil;
* Post the notification to all the observers that specified OBJECT,
* but didn't specify NAME.
*/
if (n_object)
if (object)
{
n = GSIMapNodeForSimpleKey(NAMELESS, (GSIMapKey)n_object);
n = GSIMapNodeForSimpleKey(NAMELESS, (GSIMapKey)object);
if (n != 0)
{
o = n->value.ext;
@ -1035,19 +1141,23 @@ static NSNotificationCenter *default_center = nil;
* observers with a non-nil OBJECT that doesn't match the
* notification's OBJECT).
*/
if (n_name)
if (name)
{
n = GSIMapNodeForKey(NAMED, (GSIMapKey)n_name);
n = GSIMapNodeForKey(NAMED, (GSIMapKey)name);
if (n)
m = (GSIMapTable)n->value.ptr;
{
m = (GSIMapTable)n->value.ptr;
}
else
m = 0;
{
m = 0;
}
if (m != 0)
{
/*
* First, observers with a matching object.
*/
n = GSIMapNodeForSimpleKey(m, (GSIMapKey)n_object);
n = GSIMapNodeForSimpleKey(m, (GSIMapKey)object);
if (n != 0)
{
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.
@ -1097,28 +1207,14 @@ static NSNotificationCenter *default_center = nil;
GSIArrayRemoveItemsFromIndex(ARRAY, arrayBase);
unlockNCTable(TABLE);
DESTROY(notification); // Get rid of notification we created.
[localException raise];
}
NS_ENDHANDLER
#endif
unlockNCTable(TABLE);
}
- (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]];
RELEASE(notification);
}
@end

View file

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