mirror of
https://github.com/gnustep/libs-base.git
synced 2025-05-30 00:11:26 +00:00
garbage collecting fixes
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@27638 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
d8cf9c2d35
commit
e82bd33ab1
6 changed files with 275 additions and 156 deletions
|
@ -159,7 +159,11 @@ static SEL objSel;
|
|||
[aCoder decodeValueOfObjCType: @encode(unsigned)
|
||||
at: &count];
|
||||
|
||||
#if GS_WITH_GC
|
||||
GSIMapInitWithZoneAndCapacity(&map, GSScannedMallocZone(), count);
|
||||
#else
|
||||
GSIMapInitWithZoneAndCapacity(&map, GSObjCZone(self), count);
|
||||
#endif
|
||||
while (count-- > 0)
|
||||
{
|
||||
(*imp)(aCoder, sel, type, &key);
|
||||
|
@ -175,7 +179,12 @@ static SEL objSel;
|
|||
{
|
||||
unsigned int i;
|
||||
|
||||
#if GS_WITH_GC
|
||||
GSIMapInitWithZoneAndCapacity(&map, GSScannedMallocZone(), c);
|
||||
#else
|
||||
GSIMapInitWithZoneAndCapacity(&map, GSObjCZone(self), c);
|
||||
#endif
|
||||
|
||||
for (i = 0; i < c; i++)
|
||||
{
|
||||
GSIMapNode node;
|
||||
|
@ -214,9 +223,14 @@ static SEL objSel;
|
|||
- (id) initWithDictionary: (NSDictionary*)other
|
||||
copyItems: (BOOL)shouldCopy
|
||||
{
|
||||
NSZone *z = GSObjCZone(self);
|
||||
NSZone *z;
|
||||
unsigned c = [other count];
|
||||
|
||||
#if GS_WITH_GC
|
||||
z = GSScannedMallocZone();
|
||||
#else
|
||||
z = GSObjCZone(self);
|
||||
#endif
|
||||
GSIMapInitWithZoneAndCapacity(&map, z, c);
|
||||
|
||||
if (c > 0)
|
||||
|
@ -369,7 +383,11 @@ static SEL objSel;
|
|||
/* Designated initialiser */
|
||||
- (id) initWithCapacity: (unsigned)cap
|
||||
{
|
||||
#if GS_WITH_GC
|
||||
GSIMapInitWithZoneAndCapacity(&map, GSScannedMallocZone(), cap);
|
||||
#else
|
||||
GSIMapInitWithZoneAndCapacity(&map, GSObjCZone(self), cap);
|
||||
#endif
|
||||
return self;
|
||||
}
|
||||
|
||||
|
|
|
@ -138,7 +138,7 @@ static inline void setup()
|
|||
@interface GSKVOObservation : NSObject
|
||||
{
|
||||
@public
|
||||
NSObject *observer; // Not retained
|
||||
NSObject *observer; // Not retained (zeroing weak pointer)
|
||||
void *context;
|
||||
int options;
|
||||
}
|
||||
|
@ -586,7 +586,8 @@ replacementForClass(Class c)
|
|||
|
||||
if (!found)
|
||||
{
|
||||
NSDebugLLog(@"KVC", @"class %@ not KVC complient for %@", original, aKey);
|
||||
NSDebugLLog(@"KVC", @"class %@ not KVC complient for %@",
|
||||
original, aKey);
|
||||
/*
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"class not KVC complient for %@", aKey];
|
||||
|
@ -804,6 +805,12 @@ replacementForClass(Class c)
|
|||
|
||||
|
||||
@implementation GSKVOObservation
|
||||
#if GS_WITH_GC
|
||||
+ (void) initialize
|
||||
{
|
||||
GSMakeWeakPointer(self, "observer");
|
||||
}
|
||||
#endif
|
||||
@end
|
||||
|
||||
@implementation GSKVOPathInfo
|
||||
|
@ -956,17 +963,26 @@ replacementForClass(Class c)
|
|||
o = [pathInfo->observations objectAtIndex: count];
|
||||
if (o->observer == anObserver)
|
||||
{
|
||||
o->observer = anObserver;
|
||||
o->context = aContext;
|
||||
o->options = options;
|
||||
observation = o;
|
||||
}
|
||||
#if GS_WITH_GC
|
||||
else if (o->observer == nil)
|
||||
{
|
||||
/* The observer for thsi observation must have been collected.
|
||||
*/
|
||||
[pathInfo->observations removeObjectAtIndex: count];
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
pathInfo->allOptions |= o->options;
|
||||
}
|
||||
if (observation == nil)
|
||||
{
|
||||
observation = [GSKVOObservation new];
|
||||
observation->observer = anObserver;
|
||||
GSAssignZeroingWeakPointer((void**)&observation->observer,
|
||||
(void*)anObserver);
|
||||
observation->context = aContext;
|
||||
observation->options = options;
|
||||
[pathInfo->observations addObject: observation];
|
||||
|
@ -1050,7 +1066,7 @@ replacementForClass(Class c)
|
|||
GSKVOObservation *o;
|
||||
|
||||
o = [pathInfo->observations objectAtIndex: count];
|
||||
if (o->observer == anObserver)
|
||||
if (o->observer == anObserver || o->observer == nil)
|
||||
{
|
||||
[pathInfo->observations removeObjectAtIndex: count];
|
||||
if ([pathInfo->observations count] == 0)
|
||||
|
@ -1088,6 +1104,14 @@ replacementForClass(Class c)
|
|||
context = o->context;
|
||||
break;
|
||||
}
|
||||
#if GS_WITH_GC
|
||||
else if (o->observer == nil)
|
||||
{
|
||||
/* The observer for thsi observation must have been collected.
|
||||
*/
|
||||
[pathInfo->observations removeObjectAtIndex: count];
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
[iLock unlock];
|
||||
|
|
|
@ -41,7 +41,6 @@
|
|||
* a collected observer removed.
|
||||
*/
|
||||
#if GS_WITH_GC
|
||||
#include <gc.h>
|
||||
#define purgeCollected(X) (X = listPurge(X, nil))
|
||||
#else
|
||||
#define purgeCollected(X) (X)
|
||||
|
@ -437,7 +436,7 @@ static void obsFree(Observation *o)
|
|||
NCTable *t = o->link;
|
||||
|
||||
#if GS_WITH_GC
|
||||
GC_unregister_disappearing_link((GC_PTR*)&o->observer);
|
||||
GSAssignZeroingWeakPointer((void**)&o->observer, 0);
|
||||
#endif
|
||||
o->link = (NCTable*)t->freeList;
|
||||
t->freeList = o;
|
||||
|
@ -705,23 +704,14 @@ static NSNotificationCenter *default_center = nil;
|
|||
o = obsNew(TABLE);
|
||||
o->selector = selector;
|
||||
o->method = method;
|
||||
#if GS_WITH_GC
|
||||
GSAssignZeroingWeakPointer((void**)&o->observer, (void*)observer);
|
||||
#else
|
||||
o->observer = observer;
|
||||
#endif
|
||||
o->retained = 0;
|
||||
o->next = 0;
|
||||
|
||||
#if GS_WITH_GC
|
||||
/* Ensure that if the observer is garbage collected, we clear the
|
||||
* oservation so that we don't end up sending notifications to the
|
||||
* deallocated object.
|
||||
* The observer must be a real GC-allocated object or this mechanism
|
||||
* can't be used.
|
||||
*/
|
||||
if (GC_base(observer) != 0)
|
||||
{
|
||||
GC_general_register_disappearing_link((GC_PTR*)&o->observer, observer);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (object != nil)
|
||||
{
|
||||
object = CHEATGC(object);
|
||||
|
|
183
Source/NSZone.m
183
Source/NSZone.m
|
@ -1837,14 +1837,8 @@ NSReallocateCollectable(void *ptr, NSUInteger size, NSUInteger options)
|
|||
#define GS_ZONE_ATTR __attribute__((unused))
|
||||
#endif
|
||||
|
||||
#ifndef GS_WITH_GC
|
||||
#define GS_WITH_GC 0
|
||||
#endif
|
||||
#if GS_WITH_GC
|
||||
|
||||
#include <gc.h>
|
||||
|
||||
|
||||
NSZone*
|
||||
NSCreateZone (size_t start, size_t gran, BOOL canFree)
|
||||
{
|
||||
|
@ -1875,76 +1869,11 @@ NSZoneFromPointer (void *ptr)
|
|||
return &default_zone;
|
||||
}
|
||||
|
||||
void*
|
||||
NSZoneMalloc (NSZone *zone, size_t size)
|
||||
{
|
||||
void *ptr;
|
||||
|
||||
if (zone == GSAtomicMallocZone())
|
||||
ptr = (void*)GC_MALLOC_ATOMIC(size);
|
||||
else if (zone == GSScannedMallocZone())
|
||||
ptr = (void*)GC_MALLOC(size);
|
||||
else
|
||||
ptr = (void*)malloc(size);
|
||||
|
||||
if (ptr == 0)
|
||||
ptr = GSOutOfMemory(size, YES);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void*
|
||||
NSZoneCalloc (NSZone *zone, size_t elems, size_t bytes)
|
||||
{
|
||||
size_t size = elems * bytes;
|
||||
void *ptr;
|
||||
|
||||
if (zone == &atomic_zone)
|
||||
ptr = (void*)GC_MALLOC_ATOMIC(size);
|
||||
else if (zone == &scanned_zone)
|
||||
ptr = (void*)GC_MALLOC(size);
|
||||
else
|
||||
ptr = (void*)malloc(size);
|
||||
|
||||
if (ptr == 0)
|
||||
ptr = GSOutOfMemory(size, NO);
|
||||
memset(ptr, '\0', size);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void*
|
||||
NSZoneRealloc (NSZone *zone, void *ptr, size_t size)
|
||||
{
|
||||
if (GC_base(ptr) != 0)
|
||||
{
|
||||
ptr = GC_REALLOC(ptr, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
ptr = realloc(ptr, size);
|
||||
}
|
||||
if (ptr == 0)
|
||||
GSOutOfMemory(size, NO);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void
|
||||
NSRecycleZone (NSZone *zone)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
NSZoneFree (NSZone *zone, void *ptr)
|
||||
{
|
||||
if (GC_base(ptr) != 0)
|
||||
{
|
||||
GC_FREE(ptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
free(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
NSSetZoneName (NSZone *zone, NSString *name)
|
||||
{
|
||||
|
@ -1969,6 +1898,101 @@ NSZoneStats NSZoneStats (NSZone *zone)
|
|||
return stats;
|
||||
}
|
||||
|
||||
void
|
||||
GSMakeWeakPointer(Class class, const char *iVarName)
|
||||
{
|
||||
class_ivar_set_gcinvisible(class, iVarName, YES);
|
||||
}
|
||||
|
||||
|
||||
#include <gc.h>
|
||||
|
||||
BOOL
|
||||
GSAssignZeroingWeakPointer(void **destination, void *source)
|
||||
{
|
||||
if (GC_base(destination) == 0)
|
||||
{
|
||||
return NO; // Destination is not in garbage collection system.
|
||||
}
|
||||
if (*destination == source)
|
||||
{
|
||||
return YES; // Already assigned.
|
||||
}
|
||||
if (source != 0 && GC_base(source) == 0)
|
||||
{
|
||||
return NO; // Source is not garbage collectable.
|
||||
}
|
||||
if (*destination != 0)
|
||||
{
|
||||
GC_unregister_disappearing_link((GC_PTR*)destination);
|
||||
}
|
||||
*destination = source;
|
||||
GC_general_register_disappearing_link((GC_PTR*)destination, source);
|
||||
return YES;
|
||||
}
|
||||
|
||||
void*
|
||||
NSZoneMalloc (NSZone *zone, size_t size)
|
||||
{
|
||||
return NSZoneCalloc(zone, 1, size);
|
||||
}
|
||||
|
||||
void*
|
||||
NSZoneCalloc (NSZone *zone, size_t elems, size_t bytes)
|
||||
{
|
||||
size_t size = elems * bytes;
|
||||
void *ptr;
|
||||
|
||||
if (zone == &atomic_zone)
|
||||
{
|
||||
ptr = (void*)GC_MALLOC_ATOMIC(size);
|
||||
}
|
||||
else if (zone == &scanned_zone)
|
||||
{
|
||||
ptr = (void*)GC_MALLOC(size);
|
||||
}
|
||||
else
|
||||
{
|
||||
ptr = (void*)malloc(size);
|
||||
if (ptr == 0)
|
||||
{
|
||||
ptr = GSOutOfMemory(size, NO);
|
||||
}
|
||||
if (ptr != 0)
|
||||
{
|
||||
memset(ptr, '\0', size);
|
||||
}
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void*
|
||||
NSZoneRealloc (NSZone *zone, void *ptr, size_t size)
|
||||
{
|
||||
if (GC_base(ptr) != 0)
|
||||
{
|
||||
ptr = GC_REALLOC(ptr, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
ptr = realloc(ptr, size);
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void
|
||||
NSZoneFree (NSZone *zone, void *ptr)
|
||||
{
|
||||
if (GC_base(ptr) != 0)
|
||||
{
|
||||
GC_FREE(ptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
free(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
#else /* GS_WITH_GC */
|
||||
|
||||
NSZone*
|
||||
|
@ -1989,6 +2013,23 @@ GSScannedMallocZone (void)
|
|||
return &default_zone;
|
||||
}
|
||||
|
||||
void
|
||||
GSMakeWeakPointer(Class class, const char *iVarName)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
BOOL
|
||||
GSAssignZeroingWeakPointer(void **destination, void *source)
|
||||
{
|
||||
if (destination == 0)
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
*destination = source;
|
||||
return YES;
|
||||
}
|
||||
|
||||
void*
|
||||
NSZoneMalloc (NSZone *zone, size_t size)
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue