Index: src/OFNotificationCenter.m ================================================================== --- src/OFNotificationCenter.m +++ src/OFNotificationCenter.m @@ -14,10 +14,11 @@ */ #include "config.h" #import "OFNotificationCenter.h" +#import "OFArray.h" #import "OFDictionary.h" #ifdef OF_HAVE_THREADS # import "OFMutex.h" #endif #import "OFSet.h" @@ -24,11 +25,11 @@ #import "OFString.h" @interface OFDefaultNotificationCenter: OFNotificationCenter @end -@interface OFNotificationRegistration: OFObject +@interface OFNotificationHandler: OFObject { @public id _observer; SEL _selector; unsigned long _selectorHash; @@ -40,11 +41,11 @@ object: (id)object; @end static OFNotificationCenter *defaultCenter; -@implementation OFNotificationRegistration +@implementation OFNotificationHandler - (instancetype)initWithObserver: (id)observer selector: (SEL)selector object: (id)object { self = [super init]; @@ -74,23 +75,22 @@ [_object release]; [super dealloc]; } -- (bool)isEqual: (OFNotificationRegistration *)registration +- (bool)isEqual: (OFNotificationHandler *)handler { - if (![registration isKindOfClass: [OFNotificationRegistration class]]) + if (![handler isKindOfClass: [OFNotificationHandler class]]) + return false; + + if (![handler->_observer isEqual: _observer]) return false; - if (![registration->_observer isEqual: _observer]) + if (!sel_isEqual(handler->_selector, _selector)) return false; - if (!sel_isEqual(registration->_selector, _selector)) - return false; - - if (registration->_object != _object && - ![registration->_object isEqual: _object]) + if (handler->_object != _object && ![handler->_object isEqual: _object]) return false; return true; } @@ -155,30 +155,29 @@ selector: (SEL)selector name: (OFNotificationName)name object: (id)object { void *pool = objc_autoreleasePoolPush(); - OFNotificationRegistration *registration = - [[[OFNotificationRegistration alloc] + OFNotificationHandler *handler = [[[OFNotificationHandler alloc] initWithObserver: observer selector: selector object: object] autorelease]; #ifdef OF_HAVE_THREADS [_mutex lock]; @try { +#endif OFMutableSet *notificationsForName = [_notifications objectForKey: name]; if (notificationsForName == nil) { notificationsForName = [OFMutableSet set]; [_notifications setObject: notificationsForName forKey: name]; } - [notificationsForName addObject: registration]; -#endif + [notificationsForName addObject: handler]; #ifdef OF_HAVE_THREADS } @finally { [_mutex unlock]; } #endif @@ -190,22 +189,20 @@ selector: (SEL)selector name: (OFNotificationName)name object: (id)object { void *pool = objc_autoreleasePoolPush(); - OFNotificationRegistration *registration = - [[[OFNotificationRegistration alloc] + OFNotificationHandler *handler = [[[OFNotificationHandler alloc] initWithObserver: observer selector: selector object: object] autorelease]; #ifdef OF_HAVE_THREADS [_mutex lock]; @try { - [[_notifications objectForKey: name] - removeObject: registration]; #endif + [[_notifications objectForKey: name] removeObject: handler]; #ifdef OF_HAVE_THREADS } @finally { [_mutex unlock]; } #endif @@ -213,33 +210,37 @@ objc_autoreleasePoolPop(pool); } - (void)postNotification: (OFNotification *)notification { + void *pool = objc_autoreleasePoolPush(); + OFMutableArray *matchedHandlers = [OFMutableArray array]; + #ifdef OF_HAVE_THREADS [_mutex lock]; @try { - for (OFNotificationRegistration *registration in - [_notifications objectForKey: notification.name]) { - void (*callback)(id, SEL, OFNotification *); - - if (registration->_object != nil && - registration->_object != notification.object) - continue; - - callback = (void (*)(id, SEL, OFNotification *)) - [registration->_observer methodForSelector: - registration->_selector]; - callback(registration->_observer, - registration->_selector, notification); - } #endif + for (OFNotificationHandler *handler in + [_notifications objectForKey: notification.name]) + if (handler->_object == nil || + handler->_object == notification.object) + [matchedHandlers addObject: handler]; #ifdef OF_HAVE_THREADS } @finally { [_mutex unlock]; } #endif + + for (OFNotificationHandler *handler in matchedHandlers) { + void (*callback)(id, SEL, OFNotification *) = + (void (*)(id, SEL, OFNotification *)) + [handler->_observer methodForSelector: handler->_selector]; + + callback(handler->_observer, handler->_selector, notification); + } + + objc_autoreleasePoolPop(pool); } @end @implementation OFDefaultNotificationCenter - (instancetype)autorelease