fix error removing collected observers

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@27844 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Richard Frith-MacDonald 2009-02-11 09:31:30 +00:00
parent 7df8c0e140
commit d3da55f975
2 changed files with 36 additions and 14 deletions

View file

@ -1,4 +1,9 @@
2009-02-09 Richard Frith-Macdonald <rfm@gnu.org>
2009-02-11 Richard Frith-Macdonald <rfm@gnu.org>
* Source/NSNotificationCenter.m: Fix bug removing observations for
collected observers.
2009-02-10 Richard Frith-Macdonald <rfm@gnu.org>
* Source/NSConcretePointerFunctions.h:
* Source/NSConcretePointerFunctions.m:

View file

@ -37,15 +37,6 @@
#import "Foundation/NSDebug.h"
#import "GNUstepBase/GSLock.h"
/* purgeCollected() returns a list of observations with any observations for
* a collected observer removed.
*/
#if GS_WITH_GC
#define purgeCollected(X) (X = listPurge(X, nil))
#else
#define purgeCollected(X) (X)
#endif
static NSZone *_zone = 0;
/**
@ -482,6 +473,8 @@ static void listFree(Observation *list)
* we remove to be zero so that, if it currently exists in an array
* of observations being posted, the posting code can notice that it
* has been removed from its linked list.
*
* Also,
*/
static Observation *listPurge(Observation *list, id observer)
{
@ -561,6 +554,30 @@ purgeMapNode(GSIMapTable map, GSIMapNode node, id observer)
}
}
/* purgeCollected() returns a list of observations with any observations for
* a collected observer removed.
* purgeCollectedFromMapNode() does the same thing but also handles cleanup
* of the map node containing the list if necessary.
*/
#if GS_WITH_GC
#define purgeCollected(X) listPurge(X, nil)
static Observation*
purgeCollectedFromMapNode(GSIMapTable map, GSIMapNode node)
{
Observation *o;
o = node->value.ext = purgeCollected((Observation*)(node->value.ext));
if (o == ENDOBS)
{
GSIMapRemoveKey(map, node->key);
}
return o;
}
#else
#define purgeCollected(X) (X)
#define purgeCollectedFromMapNode(X, Y) ((Observation*)Y->value.ext)
#endif
/*
* In order to hide pointers from garbage collection, we OR in an
* extra bit. This should be ok for the objects we deal with
@ -1037,7 +1054,7 @@ static NSNotificationCenter *default_center = nil;
/*
* Find all the observers that specified neither NAME nor OBJECT.
*/
for (o = purgeCollected(WILDCARD); o != ENDOBS; o = o->next)
for (o = WILDCARD = purgeCollected(WILDCARD); o != ENDOBS; o = o->next)
{
GSIArrayAddItem(a, (GSIArrayItem)o);
}
@ -1050,7 +1067,7 @@ static NSNotificationCenter *default_center = nil;
n = GSIMapNodeForSimpleKey(NAMELESS, (GSIMapKey)object);
if (n != 0)
{
o = purgeCollected(n->value.ext);
o = purgeCollectedFromMapNode(NAMELESS, n);
while (o != ENDOBS)
{
GSIArrayAddItem(a, (GSIArrayItem)o);
@ -1082,7 +1099,7 @@ static NSNotificationCenter *default_center = nil;
n = GSIMapNodeForSimpleKey(m, (GSIMapKey)object);
if (n != 0)
{
o = purgeCollected(n->value.ext);
o = purgeCollectedFromMapNode(m, n);
while (o != ENDOBS)
{
GSIArrayAddItem(a, (GSIArrayItem)o);
@ -1098,7 +1115,7 @@ static NSNotificationCenter *default_center = nil;
n = GSIMapNodeForSimpleKey(m, (GSIMapKey)nil);
if (n != 0)
{
o = purgeCollected(n->value.ext);
o = purgeCollectedFromMapNode(m, n);
while (o != ENDOBS)
{
GSIArrayAddItem(a, (GSIArrayItem)o);