Skip to content

Commit

Permalink
refactor the cycle finder into a few additional functions for better …
Browse files Browse the repository at this point in the history
…clarity, and stop leaking all the CF objects
  • Loading branch information
mikeash committed Jun 3, 2012
1 parent a17c615 commit dbc1ac0
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 22 deletions.
9 changes: 8 additions & 1 deletion Circle/CircleSimpleCycleFinder.h
Expand Up @@ -9,4 +9,11 @@
#import <Foundation/Foundation.h>


void CircleSimpleSearchCycle(id obj);
struct CircleSearchResults
{
BOOL isUnclaimedCycle;
CFSetRef incomingReferences;
};

struct CircleSearchResults CircleSimpleSearchCycle(id obj);
void CircleZeroReferences(CFSetRef references);
53 changes: 36 additions & 17 deletions Circle/CircleSimpleCycleFinder.m
Expand Up @@ -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);
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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);
}
}
14 changes: 10 additions & 4 deletions Circle/MAAppDelegate.m
Expand Up @@ -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);

Expand All @@ -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);
}

Expand Down

0 comments on commit dbc1ac0

Please sign in to comment.