Tweaks to match OSX pointer array behaviors more accurately.

This commit is contained in:
rfm 2024-07-22 12:22:40 +01:00
parent 5699959d39
commit a1514249f3
3 changed files with 223 additions and 125 deletions

View file

@ -179,6 +179,9 @@ relinquishRetainedMemory(const void *item,
- (id) initWithOptions: (NSPointerFunctionsOptions)options
{
int memoryType = options & 0x00ff;
int personality = options & 0xff00;
#define Unsupported(X) ({\
NSLog(@"*** An unsupported PointerFunctions configuration was requested,"\
@" probably for use by NSMapTable, NSHashTable, or NSPointerArray. %@",\
@ -186,130 +189,155 @@ relinquishRetainedMemory(const void *item,
DESTROY(self);\
})
if (memoryType(options, NSPointerFunctionsZeroingWeakMemory))
/* Check that we have a valid memory management option.
*/
switch (memoryType)
{
case NSPointerFunctionsMachVirtualMemory:
case NSPointerFunctionsMallocMemory:
case NSPointerFunctionsOpaqueMemory:
case NSPointerFunctionsStrongMemory:
case NSPointerFunctionsWeakMemory:
case NSPointerFunctionsZeroingWeakMemory:
break;
default:
Unsupported(@"The requested configuration fails due to"
@" an unknown memory type being specified.");
return self;
}
/* Save the supplied options (with modification if needed).
*/
if (NSPointerFunctionsZeroingWeakMemory == memoryType)
{
/* Garbage Collection is no longer supported, so we treat all weak
* memory the same way.
*/
_x.options = (options & 0xffffff00) | NSPointerFunctionsWeakMemory;
memoryType = NSPointerFunctionsWeakMemory;
_x.options = (options & 0xffffff00) | memoryType;
}
else
{
_x.options = options;
}
/* First we look at the memory management options to see which function
* should be used to relinquish contents of a container with these
* options.
/* Check for unsupported memory/personality combinations
*/
if (memoryType(options, NSPointerFunctionsWeakMemory)
|| memoryType(options, NSPointerFunctionsZeroingWeakMemory))
if (NSPointerFunctionsIntegerPersonality == personality)
{
_x.relinquishFunction = 0;
}
else if (memoryType(options, NSPointerFunctionsOpaqueMemory))
{
_x.relinquishFunction = 0;
}
else if (memoryType(options, NSPointerFunctionsMallocMemory))
{
_x.relinquishFunction = relinquishMallocMemory;
}
else if (memoryType(options, NSPointerFunctionsMachVirtualMemory))
{
_x.relinquishFunction = relinquishMallocMemory;
}
else
{
/* NSPointerFunctionsStrongMemory uses -release for objects
*/
if (personalityType(options, NSPointerFunctionsObjectPersonality)
|| personalityType(options, NSPointerFunctionsObjectPointerPersonality))
{
_x.relinquishFunction = relinquishRetainedMemory;
}
else
{
_x.relinquishFunction = 0;
}
}
/* Now we look at the personality options to determine other functions.
*/
if (personalityType(options, NSPointerFunctionsOpaquePersonality))
{
_x.acquireFunction = 0;
_x.descriptionFunction = describePointer;
_x.hashFunction = hashShifted;
_x.isEqualFunction = equalDirect;
}
else if (personalityType(options, NSPointerFunctionsObjectPointerPersonality))
{
if (memoryType(options, NSPointerFunctionsWeakMemory)
|| memoryType(options, NSPointerFunctionsZeroingWeakMemory))
{
_x.acquireFunction = 0;
}
else
{
_x.acquireFunction = acquireRetainedObject;
}
_x.descriptionFunction = describeObject;
_x.hashFunction = hashShifted;
_x.isEqualFunction = equalDirect;
}
else if (personalityType(options, NSPointerFunctionsCStringPersonality))
{
if (memoryType(options, NSPointerFunctionsMallocMemory))
{
_x.acquireFunction = acquireMallocMemory;
}
else
{
_x.acquireFunction = NULL;
}
_x.descriptionFunction = describeString;
_x.hashFunction = hashString;
_x.isEqualFunction = equalString;
}
else if (personalityType(options, NSPointerFunctionsStructPersonality))
{
_x.acquireFunction = acquireMallocMemory;
_x.descriptionFunction = describePointer;
_x.hashFunction = hashMemory;
_x.isEqualFunction = equalMemory;
}
else if (personalityType(options, NSPointerFunctionsIntegerPersonality))
{
if (memoryType(options, NSPointerFunctionsOpaqueMemory))
{
_x.acquireFunction = 0;
_x.descriptionFunction = describeInteger;
_x.hashFunction = hashDirect;
_x.isEqualFunction = equalDirect;
}
else
if (NSPointerFunctionsOpaqueMemory != memoryType)
{
Unsupported(@"The requested configuration fails due to"
@" integer personality not using opaque memory.");
return self;
}
}
else /* objects */
{
if (memoryType(options, NSPointerFunctionsWeakMemory)
|| memoryType(options, NSPointerFunctionsZeroingWeakMemory))
{
_x.acquireFunction = 0;
}
else
{
_x.acquireFunction = acquireRetainedObject;
}
_x.descriptionFunction = describeObject;
_x.hashFunction = hashObject;
_x.isEqualFunction = equalObject;
}
if (NSPointerFunctionsObjectPersonality == personality
|| NSPointerFunctionsObjectPointerPersonality == personality)
{
if (NSPointerFunctionsMachVirtualMemory == memoryType
|| NSPointerFunctionsMallocMemory == memoryType)
{
Unsupported(@"The requested configuration fails due to"
@" integer personality not using opaque memory.");
return self;
}
}
/* Now we look at the personality options to determine functions.
*/
switch (personality)
{
case NSPointerFunctionsCStringPersonality:
if (NSPointerFunctionsMachVirtualMemory == memoryType
|| NSPointerFunctionsMallocMemory == memoryType)
{
_x.acquireFunction = acquireMallocMemory;
_x.relinquishFunction = relinquishMallocMemory;
}
else
{
_x.acquireFunction = 0;
_x.relinquishFunction = 0;
}
_x.descriptionFunction = describeString;
_x.hashFunction = hashString;
_x.isEqualFunction = equalString;
break;
case NSPointerFunctionsIntegerPersonality:
_x.acquireFunction = 0;
_x.relinquishFunction = 0;
_x.descriptionFunction = describeInteger;
_x.hashFunction = hashDirect;
_x.isEqualFunction = equalDirect;
break;
case NSPointerFunctionsObjectPersonality:
if (NSPointerFunctionsWeakMemory == memoryType)
{
_x.acquireFunction = 0;
_x.relinquishFunction = 0;
}
else
{
_x.acquireFunction = acquireRetainedObject;
_x.relinquishFunction = relinquishRetainedMemory;
}
_x.descriptionFunction = describeObject;
_x.hashFunction = hashObject;
_x.isEqualFunction = equalObject;
break;
case NSPointerFunctionsObjectPointerPersonality:
if (NSPointerFunctionsWeakMemory == memoryType)
{
_x.acquireFunction = 0;
_x.relinquishFunction = 0;
}
else
{
_x.acquireFunction = acquireRetainedObject;
_x.relinquishFunction = 0;
}
_x.descriptionFunction = describeObject;
_x.hashFunction = hashShifted;
_x.isEqualFunction = equalDirect;
break;
case NSPointerFunctionsOpaquePersonality:
_x.acquireFunction = 0;
_x.relinquishFunction = 0;
_x.descriptionFunction = describePointer;
_x.hashFunction = hashShifted;
_x.isEqualFunction = equalDirect;
break;
case NSPointerFunctionsStructPersonality:
if (NSPointerFunctionsMachVirtualMemory == memoryType
|| NSPointerFunctionsMallocMemory == memoryType)
{
_x.acquireFunction = acquireMallocMemory;
_x.relinquishFunction = relinquishMallocMemory;
}
else
{
_x.acquireFunction = 0;
_x.relinquishFunction = 0;
}
_x.descriptionFunction = describePointer;
_x.hashFunction = hashMemory;
_x.isEqualFunction = equalMemory;
break;
default:
Unsupported(@"The requested configuration fails due to"
@" an unknown personality being specified.");
return self;
}
return self;
}

View file

@ -24,13 +24,15 @@ int main()
id testObj = [[[NSObject alloc] init] autorelease];
for (index = 0; index < 10; index++)
{
[array addPointer: testObj];
[array addPointer: testObj];
}
PASS([[array allObjects] count] == 10, "Array retains active weak reference");
PASS([[array allObjects] count] == index,
"Array retains active weak reference");
[arp2 release]; arp2 = nil;
PASS([[array allObjects] count] == 0, "Array removes dead weak reference");
PASS([[array allObjects] count] == 0,
"Array removes dead weak reference");
[arp release]; arp = nil;
END_SET("NSPointerArray weak objects")

View file

@ -69,6 +69,10 @@ static NSUInteger aStructSize(const void *item)
@end
typedef struct {
int code;
const char *name;
} OptInfo;
int main()
@ -83,6 +87,86 @@ int main()
(const void *item, NSUInteger (*size)(const void *item));
NSUInteger (*sizeFunction)(const void *item);
START_SET("Combinations")
OptInfo MemoryType[] = {
{ NSPointerFunctionsMachVirtualMemory,
"NSPointerFunctionsMachVirtualMemory" },
{ NSPointerFunctionsMallocMemory,
"NSPointerFunctionsMallocMemory" },
{ NSPointerFunctionsOpaqueMemory,
"NSPointerFunctionsOpaqueMemory" },
{ NSPointerFunctionsStrongMemory,
"NSPointerFunctionsStrongMemory" },
{ NSPointerFunctionsWeakMemory,
"NSPointerFunctionsWeakMemory" },
{ NSPointerFunctionsZeroingWeakMemory,
"NSPointerFunctionsZeroingWeakMemory" },
{ 0x00ff, "Unknown/BadMemory" }
};
OptInfo Personality[] = {
{ NSPointerFunctionsCStringPersonality,
"NSPointerFunctionsCStringPersonality" },
{ NSPointerFunctionsIntegerPersonality,
"NSPointerFunctionsIntegerPersonality" },
{ NSPointerFunctionsObjectPersonality,
"NSPointerFunctionsObjectPersonality" },
{ NSPointerFunctionsObjectPointerPersonality,
"NSPointerFunctionsObjectPointerPersonality" },
{ NSPointerFunctionsOpaquePersonality,
"NSPointerFunctionsOpaquePersonality" },
{ NSPointerFunctionsStructPersonality,
"NSPointerFunctionsStructPersonality" },
{ 0xff00, "Unknown/BadPersonality" }
};
int mem;
int per;
for (mem = 0; mem < sizeof(MemoryType) / sizeof(*MemoryType); mem++)
{
for (per = 0; per < sizeof(Personality) / sizeof(*Personality); per++)
{
int mc = MemoryType[mem].code;
int pc = Personality[per].code;
BOOL ok = (0x00ff != mc && 0xff00 != pc);
const char *msg;
if (NSPointerFunctionsIntegerPersonality == pc)
{
if (NSPointerFunctionsOpaqueMemory != mc)
{
ok = NO;
}
}
if (NSPointerFunctionsObjectPersonality == pc
|| NSPointerFunctionsObjectPointerPersonality == pc)
{
if (NSPointerFunctionsMachVirtualMemory == mc
|| NSPointerFunctionsMallocMemory == mc)
{
ok = NO;
}
}
pf = [NSPointerFunctions pointerFunctionsWithOptions: mc | pc];
if (ok)
{
msg = [[NSString stringWithFormat: @"Create with %s %s allowed",
MemoryType[mem].name, Personality[per].name] UTF8String];
PASS(pf != nil, "%s", msg)
}
else
{
msg = [[NSString stringWithFormat: @"Create with %s %s refused",
MemoryType[mem].name, Personality[per].name] UTF8String];
PASS(nil == pf, "%s", msg)
}
}
}
END_SET("Combinations")
START_SET("GarbageCollection")
NSPointerFunctions *pf;
NSPointerFunctions *zpf;
@ -101,27 +185,11 @@ int main()
END_SET("GarbageCollection")
START_SET("Personality/Memory")
PASS(nil == [NSPointerFunctions pointerFunctionsWithOptions:
NSPointerFunctionsZeroingWeakMemory
| NSPointerFunctionsIntegerPersonality],
"nil on create with integer personality and zeroing weak memory")
PASS(nil == [NSPointerFunctions pointerFunctionsWithOptions:
NSPointerFunctionsWeakMemory
| NSPointerFunctionsIntegerPersonality],
"nil on create with integer personality and weak memory")
PASS(nil == [NSPointerFunctions pointerFunctionsWithOptions:
NSPointerFunctionsStrongMemory
| NSPointerFunctionsIntegerPersonality],
"nil on create with integer personality and strong memory")
END_SET("Personality/Memory")
START_SET("CStringPersonality")
{
const char *cstr1 = "hello";
const char *cstr2 = "hello";
const char *cstr3 = "goodbye";
const char *cstr;
pf = [NSPointerFunctions pointerFunctionsWithOptions:
NSPointerFunctionsCStringPersonality];