Skip to content

Instantly share code, notes, and snippets.

@rpplusplus
Last active August 29, 2015 14:05
Show Gist options
  • Save rpplusplus/f7cbf551cbefc7f9b4dc to your computer and use it in GitHub Desktop.
Save rpplusplus/f7cbf551cbefc7f9b4dc to your computer and use it in GitHub Desktop.
CFRuntime.__CFDoExternRefOperation
// we disguise pointers so that programs like 'leaks' forget about these references
#define DISGUISE(O) (~(uintptr_t)(O))
#if DEPLOYMENT_TARGET_MACOSX
#define NUM_EXTERN_TABLES 8
#define EXTERN_TABLE_IDX(O) (((uintptr_t)(O) >> 8) & 0x7)
#elif DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
#define NUM_EXTERN_TABLES 1
#define EXTERN_TABLE_IDX(O) 0
#else
#error
#endif
static struct {
CFSpinLock_t lock;
CFBasicHashRef table;
uint8_t padding[64 - sizeof(CFBasicHashRef) - sizeof(CFSpinLock_t)];
} __NSRetainCounters[NUM_EXTERN_TABLES];
CF_EXPORT uintptr_t __CFDoExternRefOperation(uintptr_t op, id obj) {
if (nil == obj) HALT;
uintptr_t idx = EXTERN_TABLE_IDX(obj);
uintptr_t disguised = DISGUISE(obj);
CFSpinLock_t *lock = &__NSRetainCounters[idx].lock;
CFBasicHashRef table = __NSRetainCounters[idx].table;
uintptr_t count;
switch (op) {
case 300: // increment
case 350: // increment, no event
__CFSpinLock(lock);
CFBasicHashAddValue(table, disguised, disguised);
__CFSpinUnlock(lock);
if (__CFOASafe && op != 350) __CFRecordAllocationEvent(__kCFObjectRetainedEvent, obj, 0, 0, NULL);
return (uintptr_t)obj;
case 400: // decrement
if (__CFOASafe) __CFRecordAllocationEvent(__kCFObjectReleasedEvent, obj, 0, 0, NULL);
case 450: // decrement, no event
__CFSpinLock(lock);
count = (uintptr_t)CFBasicHashRemoveValue(table, disguised);
__CFSpinUnlock(lock);
return 0 == count;
case 500:
__CFSpinLock(lock);
count = (uintptr_t)CFBasicHashGetCountOfKey(table, disguised);
__CFSpinUnlock(lock);
return count;
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment