From a1514249f3d7ab4dabeb03894840061ab22a71a4 Mon Sep 17 00:00:00 2001 From: rfm Date: Mon, 22 Jul 2024 12:22:40 +0100 Subject: [PATCH] Tweaks to match OSX pointer array behaviors more accurately. --- Source/NSConcretePointerFunctions.m | 240 +++++++++++++----------- Tests/base/NSPointerArray/weakObjects.m | 8 +- Tests/base/NSPointerFunctions/general.m | 100 ++++++++-- 3 files changed, 223 insertions(+), 125 deletions(-) diff --git a/Source/NSConcretePointerFunctions.m b/Source/NSConcretePointerFunctions.m index a16bc7504..ce5a78a23 100644 --- a/Source/NSConcretePointerFunctions.m +++ b/Source/NSConcretePointerFunctions.m @@ -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; } diff --git a/Tests/base/NSPointerArray/weakObjects.m b/Tests/base/NSPointerArray/weakObjects.m index 0dd2efc54..ed3458afd 100644 --- a/Tests/base/NSPointerArray/weakObjects.m +++ b/Tests/base/NSPointerArray/weakObjects.m @@ -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") diff --git a/Tests/base/NSPointerFunctions/general.m b/Tests/base/NSPointerFunctions/general.m index a4c2c0185..3759dccdc 100644 --- a/Tests/base/NSPointerFunctions/general.m +++ b/Tests/base/NSPointerFunctions/general.m @@ -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];