From dbc1ac0ca04dd5e8b79acbaa0c24c11c36d9c565 Mon Sep 17 00:00:00 2001 From: Mike Ash Date: Sun, 3 Jun 2012 17:45:00 -0400 Subject: [PATCH] refactor the cycle finder into a few additional functions for better clarity, and stop leaking all the CF objects --- Circle/CircleSimpleCycleFinder.h | 9 +++++- Circle/CircleSimpleCycleFinder.m | 53 ++++++++++++++++++++++---------- Circle/MAAppDelegate.m | 14 ++++++--- 3 files changed, 54 insertions(+), 22 deletions(-) diff --git a/Circle/CircleSimpleCycleFinder.h b/Circle/CircleSimpleCycleFinder.h index ab9efe2..bb7d453 100644 --- a/Circle/CircleSimpleCycleFinder.h +++ b/Circle/CircleSimpleCycleFinder.h @@ -9,4 +9,11 @@ #import -void CircleSimpleSearchCycle(id obj); \ No newline at end of file +struct CircleSearchResults +{ + BOOL isUnclaimedCycle; + CFSetRef incomingReferences; +}; + +struct CircleSearchResults CircleSimpleSearchCycle(id obj); +void CircleZeroReferences(CFSetRef references); diff --git a/Circle/CircleSimpleCycleFinder.m b/Circle/CircleSimpleCycleFinder.m index 0c092f0..e54e1a8 100644 --- a/Circle/CircleSimpleCycleFinder.m +++ b/Circle/CircleSimpleCycleFinder.m @@ -43,7 +43,7 @@ - (void)dealloc @end -void CircleSimpleSearchCycle(id obj) +static CFDictionaryRef CopyInfosForReferents(id obj) { CFMutableDictionaryRef searchedObjs = CFDictionaryCreateMutable(NULL, 0, NULL, &kCFTypeDictionaryValueCallBacks); CFMutableArrayRef toSearchObjs = CFArrayCreateMutable(NULL, 0, NULL); @@ -78,26 +78,35 @@ void CircleSimpleSearchCycle(id obj) } } } + CFRelease(toSearchObjs); - _CircleObjectInfo *info = (__bridge _CircleObjectInfo *)CFDictionaryGetValue(searchedObjs, (__bridge void *)obj); + return searchedObjs; +} + +struct CircleSearchResults CircleSimpleSearchCycle(id obj) +{ + CFDictionaryRef infos = CopyInfosForReferents(obj); + + _CircleObjectInfo *info = (__bridge _CircleObjectInfo *)CFDictionaryGetValue(infos, (__bridge void *)obj); CFSetRef incomingReferences = [info incomingReferences]; NSUInteger retainCount = CFGetRetainCount((__bridge CFTypeRef)obj); LOG(@"%@ retain count is %lu, scanned incoming references are %@", obj, retainCount, CFBridgingRelease(CFCopyDescription(incomingReferences))); - CFArrayRemoveAllValues(toSearchObjs); + CFMutableArrayRef toSearchObjs = CFArrayCreateMutable(NULL, 0, NULL); CFArrayAppendValue(toSearchObjs, (__bridge void*)obj); CFMutableSetRef didSearchObjs = CFSetCreateMutable(NULL, 0, NULL); BOOL foundExternallyRetained = NO; + CFIndex count; while((count = CFArrayGetCount(toSearchObjs)) > 0) { void *cycleObj = (void *)CFArrayGetValueAtIndex(toSearchObjs, count - 1); CFArrayRemoveValueAtIndex(toSearchObjs, count - 1); CFSetAddValue(didSearchObjs, cycleObj); - _CircleObjectInfo *info = (__bridge _CircleObjectInfo *)CFDictionaryGetValue(searchedObjs, cycleObj); + _CircleObjectInfo *info = (__bridge _CircleObjectInfo *)CFDictionaryGetValue(infos, cycleObj); CFSetRef referencesCF = [info incomingReferences]; CFIndex referencesCount = CFSetGetCount(referencesCF); @@ -127,19 +136,29 @@ void CircleSimpleSearchCycle(id obj) LOG(@"foundExternallyRetained is %d", foundExternallyRetained); - if(!foundExternallyRetained) + struct CircleSearchResults results; + results.isUnclaimedCycle = !foundExternallyRetained; + results.incomingReferences = CFRetain(incomingReferences); + + CFRelease(infos); + CFRelease(toSearchObjs); + CFRelease(didSearchObjs); + + return results; +} + +void CircleZeroReferences(CFSetRef references) +{ + NSUInteger incomingReferencesCount = CFSetGetCount(references); + + const void *locations[incomingReferencesCount]; + CFSetGetValues(references, locations); + for(unsigned i = 0; i < incomingReferencesCount; i++) { - NSUInteger incomingReferencesCount = CFSetGetCount(incomingReferences); - - const void *locations[incomingReferencesCount]; - CFSetGetValues(incomingReferences, locations); - for(unsigned i = 0; i < incomingReferencesCount; i++) - { - void **reference = (void **)locations[i]; - void *target = *reference; - LOG(@"Zeroing reference %p to %p", reference, target); - *reference = NULL; - CFRelease(target); - } + void **reference = (void **)locations[i]; + void *target = *reference; + LOG(@"Zeroing reference %p to %p", reference, target); + *reference = NULL; + CFRelease(target); } } diff --git a/Circle/MAAppDelegate.m b/Circle/MAAppDelegate.m index eee9f30..1515936 100644 --- a/Circle/MAAppDelegate.m +++ b/Circle/MAAppDelegate.m @@ -88,7 +88,10 @@ - (void)applicationDidFinishLaunching:(NSNotification *)aNotification [c setPtr: a]; weakObj = a; } - CircleSimpleSearchCycle(weakObj); + struct CircleSearchResults results = CircleSimpleSearchCycle(weakObj); + if(results.isUnclaimedCycle) + CircleZeroReferences(results.incomingReferences); + CFRelease(results.incomingReferences); } NSLog(@"After collecting, weak object is %@", weakObj); @@ -105,11 +108,14 @@ - (void)applicationDidFinishLaunching:(NSNotification *)aNotification weakObj = a; self->strong = b; - NSLog(@"Before collecting, chaining gives", [self->strong ptr]); + NSLog(@"Before collecting, chaining gives %@", [self->strong ptr]); } - CircleSimpleSearchCycle(weakObj); + struct CircleSearchResults results = CircleSimpleSearchCycle(weakObj); + if(results.isUnclaimedCycle) + CircleZeroReferences(results.incomingReferences); + CFRelease(results.incomingReferences); } - NSLog(@"After collecting, chaining gives", [self->strong ptr]); + NSLog(@"After collecting, chaining gives %@", [self->strong ptr]); NSLog(@"After collecting, weak object is %@", weakObj); }