keep observer retained until removed

This commit is contained in:
rfm 2024-01-09 08:25:28 +00:00
parent db90ab6bb9
commit a0ce4ab880
2 changed files with 30 additions and 2 deletions

View file

@ -1,3 +1,8 @@
2024-01-08 Richard Frith-Macdonald <rfm@gnu.org>
* Source/NSNotificationCenter.m: fix for memory leak should keep the
observer retained until removed.
2023-12-21 Richard Frith-Macdonald <rfm@gnu.org>
* Tools/AGSParser.m: Replace GS_GENERIC macros in method types etc
@ -16,7 +21,8 @@
2023-12-09: Hugo Melder <contact@hugomelder.com>
* Source/NSNull.m:
Implement valueForUndefinedKey: and always return the NSNull singleton object.
Implement valueForUndefinedKey: and always return the NSNull singleton
object.
* Tests/base/KVC/nsnull.m:
Test for various KVC interactions with NSNull.
* Tests/base/NSPredicate/nsnull.m:

View file

@ -578,6 +578,10 @@ purgeMapNode(GSIMapTable map, GSIMapNode node, id observer)
@end
/* Cached class for fast test when removing observer.
*/
static Class GSNotificationObserverClass = Nil;
@interface GSNotificationObserver : NSObject
{
NSOperationQueue *_queue;
@ -588,6 +592,14 @@ purgeMapNode(GSIMapTable map, GSIMapNode node, id observer)
@implementation GSNotificationObserver
+ (void) initialize
{
if ([GSNotificationObserver class] == self)
{
GSNotificationObserverClass = self;
}
}
- (id) initWithQueue: (NSOperationQueue *)queue
block: (GSNotificationBlock)block
{
@ -869,7 +881,7 @@ static NSNotificationCenter *default_center = nil;
name: name
object: object];
return AUTORELEASE(observer);
return observer; // Released when observer is removed.
}
/**
@ -885,7 +897,9 @@ static NSNotificationCenter *default_center = nil;
object: (id)object
{
if (name == nil && object == nil && observer == nil)
{
return;
}
/*
* NB. The removal algorithm depends on an implementation characteristic
@ -1029,6 +1043,14 @@ static NSNotificationCenter *default_center = nil;
}
}
unlockNCTable(TABLE);
/* As a special case GSNotificationObserver instances are owned by the
* notification center and are released when they are removed.
*/
if (object_getClass(observer) == GSNotificationObserverClass)
{
RELEASE(observer);
}
}
/**