mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-22 16:33:29 +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
14
ChangeLog
14
ChangeLog
|
@ -1,3 +1,17 @@
|
|||
2009-01-20 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* Source/NSKeyValueObserving.m: Automtically remove collected observers
|
||||
In a garbage collecting environment.
|
||||
* Headers/Foundation/NSZone.h:
|
||||
* Source/NSZone.m:
|
||||
Add new functions for handling weak pointers. This allows all code
|
||||
which uses the boehm garbage collector header to be localised in
|
||||
NSZone.m and NSGarbageCollector.m
|
||||
* Source/NSNotificationCenter.m:
|
||||
Update to use new functions.
|
||||
* Source/Additions/GSInsensitiveDictionary.m:
|
||||
Fix to use scanned memory in a garbage collecting environment.
|
||||
|
||||
2009-01-19 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* configure.ac: Add options from pathconfig
|
||||
|
|
|
@ -62,37 +62,6 @@ typedef struct _NSZone NSZone;
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* <code>NSZoneStats</code> is the structure returned by the NSZoneStats()
|
||||
* function that summarizes the current usage of a zone. It is similar to
|
||||
* the structure <em>mstats</em> in the GNU C library. It has 5 fields of
|
||||
* type <code>size_t</code>-
|
||||
* <deflist>
|
||||
* <term><code>bytes_total</code></term>
|
||||
* <desc>
|
||||
* This is the total size of memory managed by the zone, in bytes.</desc>
|
||||
* <term><code>chunks_used</code></term>
|
||||
* <desc>This is the number of memory chunks in use in the zone.</desc>
|
||||
* <term><code>bytes_used</code></term>
|
||||
* <desc>This is the number of bytes in use.</desc>
|
||||
* <term><code>chunks_free</code></term>
|
||||
* <desc>This is the number of memory chunks that are not in use.</desc>
|
||||
* <term><code>bytes_free</code></term>
|
||||
* <desc>
|
||||
* This is the number of bytes managed by the zone that are not in use.
|
||||
* </desc>
|
||||
* </deflist>
|
||||
*/
|
||||
struct NSZoneStats
|
||||
{
|
||||
size_t bytes_total;
|
||||
size_t chunks_used;
|
||||
size_t bytes_used;
|
||||
size_t chunks_free;
|
||||
size_t bytes_free;
|
||||
};
|
||||
|
||||
/**
|
||||
* Primary structure representing an <code>NSZone</code>. Technically it
|
||||
* consists of a set of function pointers for zone upkeep functions plus some
|
||||
|
@ -131,35 +100,13 @@ struct _NSZone
|
|||
NSZone *next;
|
||||
};
|
||||
|
||||
/**
|
||||
* Try to get more memory - the normal process has failed.
|
||||
* If we can't do anything, just return a null pointer.
|
||||
* Try to do some logging if possible.
|
||||
*/
|
||||
void*
|
||||
GSOutOfMemory(size_t size, BOOL retry);
|
||||
|
||||
NSZone*
|
||||
GS_EXPORT NSZone*
|
||||
NSCreateZone (size_t start, size_t gran, BOOL canFree);
|
||||
|
||||
NSZone*
|
||||
GS_EXPORT NSZone*
|
||||
NSDefaultMallocZone (void);
|
||||
|
||||
/**
|
||||
* Returns the default zone used for memory allocation, created at startup.
|
||||
* This zone cannot be recycled.
|
||||
*/
|
||||
NSZone*
|
||||
GSAtomicMallocZone (void);
|
||||
|
||||
/**
|
||||
* Returns the default zone used for scanned memory allocation ... a
|
||||
* garbage collectable chunk of memory which is scanned for pointers.
|
||||
*/
|
||||
NSZone*
|
||||
GSScannedMallocZone (void);
|
||||
|
||||
NSZone*
|
||||
GS_EXPORT NSZone*
|
||||
NSZoneFromPointer (void *ptr);
|
||||
|
||||
/**
|
||||
|
@ -169,7 +116,7 @@ NSZoneFromPointer (void *ptr);
|
|||
* allocate and no more can be obtained from system, unless using the
|
||||
* default zone, in which case NULL is returned.
|
||||
*/
|
||||
void*
|
||||
GS_EXPORT void*
|
||||
NSZoneMalloc (NSZone *zone, size_t size);
|
||||
|
||||
/**
|
||||
|
@ -179,7 +126,7 @@ NSZoneMalloc (NSZone *zone, size_t size);
|
|||
* allocate and no more can be obtained from system, unless using the
|
||||
* default zone, in which case NULL is returned.
|
||||
*/
|
||||
void*
|
||||
GS_EXPORT void*
|
||||
NSZoneCalloc (NSZone *zone, size_t elems, size_t bytes);
|
||||
|
||||
/**
|
||||
|
@ -189,7 +136,7 @@ NSZoneCalloc (NSZone *zone, size_t elems, size_t bytes);
|
|||
* zone and no more memory can be obtained from the system, unless using the
|
||||
* default zone, in which case NULL is returned.
|
||||
*/
|
||||
void*
|
||||
GS_EXPORT void*
|
||||
NSZoneRealloc (NSZone *zone, void *ptr, size_t size);
|
||||
|
||||
/**
|
||||
|
@ -199,7 +146,7 @@ NSZoneRealloc (NSZone *zone, void *ptr, size_t size);
|
|||
* must simply equal the number of allocation calls. The default zone, on the
|
||||
* other hand, cannot be recycled.
|
||||
*/
|
||||
void
|
||||
GS_EXPORT void
|
||||
NSRecycleZone (NSZone *zone);
|
||||
|
||||
/**
|
||||
|
@ -208,36 +155,121 @@ NSRecycleZone (NSZone *zone);
|
|||
* returns it to zone. Note, if this is a nonfreeable zone, the memory is
|
||||
* not actually freed, but the count of number of free()s is updated.
|
||||
*/
|
||||
void
|
||||
GS_EXPORT void
|
||||
NSZoneFree (NSZone *zone, void *ptr);
|
||||
|
||||
/**
|
||||
* Sets name of the given zone (useful for debugging and logging).
|
||||
*/
|
||||
void
|
||||
GS_EXPORT void
|
||||
NSSetZoneName (NSZone *zone, NSString *name);
|
||||
|
||||
/**
|
||||
* Sets name of the given zone (useful for debugging and logging).
|
||||
*/
|
||||
NSString*
|
||||
GS_EXPORT NSString*
|
||||
NSZoneName (NSZone *zone);
|
||||
|
||||
#if OS_API_VERSION(GS_API_NONE, GS_API_NONE)
|
||||
|
||||
/**
|
||||
/** Deprecated ...<br />
|
||||
* Checks integrity of a zone. Not defined by OpenStep or OS X.
|
||||
*/
|
||||
BOOL
|
||||
NSZoneCheck (NSZone *zone);
|
||||
|
||||
/**
|
||||
* <code>NSZoneStats</code> is the structure returned by the NSZoneStats()
|
||||
* function that summarizes the current usage of a zone. It is similar to
|
||||
* the structure <em>mstats</em> in the GNU C library. It has 5 fields of
|
||||
* type <code>size_t</code>-
|
||||
* <deflist>
|
||||
* <term><code>bytes_total</code></term>
|
||||
* <desc>
|
||||
* This is the total size of memory managed by the zone, in bytes.</desc>
|
||||
* <term><code>chunks_used</code></term>
|
||||
* <desc>This is the number of memory chunks in use in the zone.</desc>
|
||||
* <term><code>bytes_used</code></term>
|
||||
* <desc>This is the number of bytes in use.</desc>
|
||||
* <term><code>chunks_free</code></term>
|
||||
* <desc>This is the number of memory chunks that are not in use.</desc>
|
||||
* <term><code>bytes_free</code></term>
|
||||
* <desc>
|
||||
* This is the number of bytes managed by the zone that are not in use.
|
||||
* </desc>
|
||||
* </deflist>
|
||||
*/
|
||||
struct NSZoneStats
|
||||
{
|
||||
size_t bytes_total;
|
||||
size_t chunks_used;
|
||||
size_t bytes_used;
|
||||
size_t chunks_free;
|
||||
size_t bytes_free;
|
||||
};
|
||||
|
||||
/** Deprecated ...<br />
|
||||
* Obtain statistics about the zone. Implementation emphasis is on
|
||||
* correctness, not speed. Not defined by OpenStep or OS X.
|
||||
*/
|
||||
struct NSZoneStats
|
||||
NSZoneStats (NSZone *zone);
|
||||
|
||||
/**
|
||||
* Try to get more memory - the normal process has failed.
|
||||
* If we can't do anything, just return a null pointer.
|
||||
* Try to do some logging if possible.
|
||||
*/
|
||||
void*
|
||||
GSOutOfMemory(size_t size, BOOL retry);
|
||||
|
||||
/**
|
||||
* Returns the default zone used for memory allocation, created at startup.
|
||||
* This zone cannot be recycled.
|
||||
*/
|
||||
GS_EXPORT NSZone*
|
||||
GSAtomicMallocZone (void);
|
||||
|
||||
/**
|
||||
* Returns the default zone used for scanned memory allocation ... a
|
||||
* garbage collectable chunk of memory which is scanned for pointers.
|
||||
*/
|
||||
GS_EXPORT NSZone*
|
||||
GSScannedMallocZone (void);
|
||||
|
||||
/**
|
||||
* Called during +initialize to tell the class that instances created
|
||||
* in future should have the specified instance variable as a weak
|
||||
* pointer for garbage collection.<br />
|
||||
* NB. making a pointer weak does not mean that it is automatically
|
||||
* zeroed when the object it points to is garbage collected. To get that
|
||||
* behavior you must asign values to the pointer using the
|
||||
* GSAssignZeroingWeakPointer() function.<rb />
|
||||
* This function has no effect if the system is
|
||||
* not built for garbage collection.
|
||||
*/
|
||||
GS_EXPORT void
|
||||
GSMakeWeakPointer(Class class, const char *iVarName);
|
||||
|
||||
/**
|
||||
* This function must be used to assign a value to a zeroing weak pointer.<br />
|
||||
* A zeroing weak pointer is one where, when the garbage collector collects
|
||||
* the object pointed to, it also clears the weak pointer.<br />
|
||||
* Assigning zero (nil) will always succeed and has the effect of telling the
|
||||
* garbage collector that it no longer needs to track the previously assigned
|
||||
* object. Apart from that case, a source needs to be garbage collectable for
|
||||
* this function to work, and using a non-garbage collectable value will
|
||||
* cause the function to return NO.<br />
|
||||
* The destination object (watching the source object) must also be memory
|
||||
* allocated by the garbage colleector, and if it is not the function will
|
||||
* return NO.<br />
|
||||
* If garbage collection is not in use, this function performs a simple
|
||||
* assignment returning YES, unless destination is null in which case it
|
||||
* returns NO.
|
||||
*/
|
||||
GS_EXPORT BOOL
|
||||
GSAssignZeroingWeakPointer(void **destination, void *source);
|
||||
|
||||
#endif
|
||||
|
||||
GS_EXPORT NSUInteger
|
||||
|
|
|
@ -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…
Reference in a new issue