From: Apple Date: Tue, 12 May 2009 22:31:02 +0000 (+0000) Subject: CF-476.18.tar.gz X-Git-Tag: mac-os-x-1057^0 X-Git-Url: https://git.saurik.com/apple/cf.git/commitdiff_plain/5645d61fe6f25ed86b990370f8fdb97b6f7679ee CF-476.18.tar.gz --- diff --git a/CFRunLoop.c b/CFRunLoop.c index 5eed260..824f077 100644 --- a/CFRunLoop.c +++ b/CFRunLoop.c @@ -509,7 +509,7 @@ CF_INLINE void __CFRunLoopSourceUnlock(CFRunLoopSourceRef rls) { static void __CFRunLoopSourceSchedule(CFRunLoopSourceRef rls, CFRunLoopRef rl, CFRunLoopModeRef rlm) { /* DOES CALLOUT */ __CFRunLoopSourceLock(rls); if (NULL == rls->_runLoops) { - rls->_runLoops = CFBagCreateMutable(CFGetAllocator(rls), 0, NULL); + rls->_runLoops = CFBagCreateMutable(kCFAllocatorSystemDefault, 0, NULL); } CFBagAddValue(rls->_runLoops, rl); __CFRunLoopSourceUnlock(rls); // have to unlock before the callout -- cannot help clients with safety @@ -793,6 +793,32 @@ static CFRunLoopTimerRef __CFRunLoopModeFindTimerForMachPort(CFRunLoopModeRef rl } #endif +// Remove backreferences the mode's sources have to the rl (context); +// the primary purpose of rls->_runLoops is so that Invalidation can remove +// the source from the run loops it is in, but during deallocation of a +// run loop, we already know that the sources are going to be punted +// from it, so invalidation of sources does not need to remove from a +// deallocating run loop. +static void __CFRunLoopCleanseSources(const void *value, void *context) { + CFRunLoopModeRef rlm = (CFRunLoopModeRef)value; + CFRunLoopRef rl = (CFRunLoopRef)context; + CFIndex idx, cnt; + const void **list, *buffer[256]; + if (NULL == rlm->_sources) return; + cnt = CFSetGetCount(rlm->_sources); + list = (cnt <= 256) ? buffer : CFAllocatorAllocate(kCFAllocatorSystemDefault, cnt * sizeof(void *), 0); + CFSetGetValues(rlm->_sources, list); + for (idx = 0; idx < cnt; idx++) { + CFRunLoopSourceRef rls = (CFRunLoopSourceRef)list[idx]; + __CFRunLoopSourceLock(rls); + if (NULL != rls->_runLoops) { + CFBagRemoveValue(rls->_runLoops, rl); + } + __CFRunLoopSourceUnlock(rls); + } + if (list != buffer) CFAllocatorDeallocate(kCFAllocatorSystemDefault, list); +} + static void __CFRunLoopDeallocateSources(const void *value, void *context) { CFRunLoopModeRef rlm = (CFRunLoopModeRef)value; CFRunLoopRef rl = (CFRunLoopRef)context; @@ -865,6 +891,7 @@ static void __CFRunLoopDeallocate(CFTypeRef cf) { three lines. */ __CFRunLoopSetDeallocating(rl); if (NULL != rl->_modes) { + CFSetApplyFunction(rl->_modes, (__CFRunLoopCleanseSources), rl); // remove references to rl CFSetApplyFunction(rl->_modes, (__CFRunLoopDeallocateSources), rl); CFSetApplyFunction(rl->_modes, (__CFRunLoopDeallocateObservers), rl); CFSetApplyFunction(rl->_modes, (__CFRunLoopDeallocateTimers), rl); @@ -941,7 +968,9 @@ static CFRunLoopRef __CFRunLoopCreate(void) { return loop; } -static CFMutableDictionaryRef runLoops = NULL; +static void __CFRunLoopRemoveAllSources(CFRunLoopRef rl, CFStringRef modeName); + +static CFMutableDictionaryRef __CFRunLoops = NULL; static char setMainLoop = 0; static CFSpinLock_t loopsLock = CFSpinLockInit; @@ -952,43 +981,41 @@ static CFSpinLock_t loopsLock = CFSpinLockInit; // fetch the main thread's pthread_t from the pthreads subsystem. // t==0 is a synonym for "main thread" that always works -__private_extern__ CFRunLoopRef _CFRunLoop0(pthread_t t) { - CFRunLoopRef loop = NULL; +static CFRunLoopRef _CFRunLoop0(pthread_t t) { + CFRunLoopRef loop; __CFSpinLock(&loopsLock); - if (!runLoops) { + if (!__CFRunLoops) { __CFSpinUnlock(&loopsLock); - CFMutableDictionaryRef dict = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, NULL, NULL); + CFMutableDictionaryRef dict = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, NULL, &kCFTypeDictionaryValueCallBacks); CFRunLoopRef mainLoop = __CFRunLoopCreate(); - CFDictionarySetValue(dict, 0, mainLoop); - if (!OSAtomicCompareAndSwapPtrBarrier(NULL, dict, (void * volatile *)&runLoops)) { + CFDictionarySetValue(dict, pthreadPointer(kNilPthreadT), mainLoop); + if (!OSAtomicCompareAndSwapPtrBarrier(NULL, dict, (void * volatile *)&__CFRunLoops)) { CFRelease(dict); - CFRelease(mainLoop); } + CFRelease(mainLoop); __CFSpinLock(&loopsLock); } if (pthread_main_np() && pthread_equal(t, pthread_self())) { t = kNilPthreadT; } - loop = (CFRunLoopRef)CFDictionaryGetValue(runLoops, pthreadPointer(t)); + loop = (CFRunLoopRef)CFDictionaryGetValue(__CFRunLoops, pthreadPointer(t)); if (!loop) { __CFSpinUnlock(&loopsLock); CFRunLoopRef newLoop = __CFRunLoopCreate(); - __CFGetThreadSpecificData(); // just cause the thread finalizer to be called as a side effect __CFSpinLock(&loopsLock); - loop = (CFRunLoopRef)CFDictionaryGetValue(runLoops, pthreadPointer(t)); - if (loop) { - CFRelease(newLoop); - } else { - CFDictionarySetValue(runLoops, pthreadPointer(t), newLoop); + loop = (CFRunLoopRef)CFDictionaryGetValue(__CFRunLoops, pthreadPointer(t)); + if (!loop) { + CFDictionarySetValue(__CFRunLoops, pthreadPointer(t), newLoop); loop = newLoop; } + CFRelease(newLoop); } if (!setMainLoop && pthread_main_np()) { if (pthread_equal(t, kNilPthreadT)) { - CFDictionarySetValue(runLoops, pthreadPointer(pthread_self()), loop); + CFDictionarySetValue(__CFRunLoops, pthreadPointer(pthread_self()), loop); } else { - CFRunLoopRef mainLoop = (CFRunLoopRef)CFDictionaryGetValue(runLoops, pthreadPointer(kNilPthreadT)); - CFDictionarySetValue(runLoops, pthreadPointer(pthread_self()), mainLoop); + CFRunLoopRef mainLoop = (CFRunLoopRef)CFDictionaryGetValue(__CFRunLoops, pthreadPointer(kNilPthreadT)); + CFDictionarySetValue(__CFRunLoops, pthreadPointer(pthread_self()), mainLoop); } setMainLoop = 1; } @@ -996,18 +1023,44 @@ __private_extern__ CFRunLoopRef _CFRunLoop0(pthread_t t) { return loop; } -__private_extern__ void _CFRunLoop1(void) { +// Called for each thread as it exits +static void __CFFinalizeRunLoop(void *arg) { + CFRunLoopRef rl = NULL; __CFSpinLock(&loopsLock); - if (runLoops) { - pthread_t t = pthread_self(); - CFRunLoopRef currentLoop = (CFRunLoopRef)CFDictionaryGetValue(runLoops, pthreadPointer(t)); - CFRunLoopRef mainLoop = (CFRunLoopRef)CFDictionaryGetValue(runLoops, pthreadPointer(kNilPthreadT)); - if (currentLoop && mainLoop != currentLoop) { - CFDictionaryRemoveValue(runLoops, pthreadPointer(t)); - CFRelease(currentLoop); + if (__CFRunLoops) { + rl = (CFRunLoopRef)CFDictionaryGetValue(__CFRunLoops, pthreadPointer(pthread_self())); + if (rl) CFRetain(rl); + CFDictionaryRemoveValue(__CFRunLoops, pthreadPointer(pthread_self())); } + __CFSpinUnlock(&loopsLock); + if (rl && CFRunLoopGetMain() != rl) { + // purge all sources before deallocation + CFArrayRef array = CFRunLoopCopyAllModes(rl); + for (CFIndex idx = CFArrayGetCount(array); idx--;) { + CFStringRef modeName = CFArrayGetValueAtIndex(array, idx); + __CFRunLoopRemoveAllSources(rl, modeName); + } + __CFRunLoopRemoveAllSources(rl, kCFRunLoopCommonModes); + CFRelease(array); + } + if (rl) { + CFRelease(rl); + } +} + +__private_extern__ void _CFRunLoop1(void) { __CFFinalizeRunLoop(0); } + +void _CFRunLoopSetCurrent(CFRunLoopRef rl) { + CFRunLoopRef currentLoop = CFRunLoopGetCurrent(); + if (rl != currentLoop) { + __CFSpinLock(&loopsLock); + if (rl) { + CFDictionarySetValue(__CFRunLoops, pthreadPointer(pthread_self()), rl); + } else { + CFDictionaryRemoveValue(__CFRunLoops, pthreadPointer(pthread_self())); } __CFSpinUnlock(&loopsLock); + } } CFRunLoopRef CFRunLoopGetMain(void) { @@ -1020,27 +1073,6 @@ CFRunLoopRef CFRunLoopGetCurrent(void) { return _CFRunLoop0(pthread_self()); } -void _CFRunLoopSetCurrent(CFRunLoopRef rl) { - __CFSpinLock(&loopsLock); - CFRunLoopRef currentLoop = runLoops ? (CFRunLoopRef)CFDictionaryGetValue(runLoops, pthreadPointer(pthread_self())) : NULL; - if (rl != currentLoop) { - // intentionally leak currentLoop so we don't kill any ports in the child - // if (currentLoop) CFRelease(currentLoop); - if (rl) { - if (!runLoops) { - runLoops = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, NULL, NULL); - CFRunLoopRef mainLoop = __CFRunLoopCreate(); - CFDictionarySetValue(runLoops, pthreadPointer(kNilPthreadT), mainLoop); - } - CFRetain(rl); - CFDictionarySetValue(runLoops, pthreadPointer(pthread_self()), rl); - } else { - CFDictionaryRemoveValue(runLoops, pthreadPointer(pthread_self())); - } - } - __CFSpinUnlock(&loopsLock); -} - CFStringRef CFRunLoopCopyCurrentMode(CFRunLoopRef rl) { CHECK_FOR_FORK(); CFStringRef result = NULL; @@ -1610,7 +1642,7 @@ static int32_t __CFRunLoopRun(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFTimeInter if (seconds <= 0.0) { poll = true; } - if (rl == _CFRunLoop0(kNilPthreadT)) _LastMainWaitSet = CFPORT_NULL; + if (rl == CFRunLoopGetMain()) _LastMainWaitSet = CFPORT_NULL; for (;;) { __CFPortSet waitSet = CFPORT_NULL; waitSet = CFPORT_NULL; @@ -1663,7 +1695,7 @@ static int32_t __CFRunLoopRun(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFTimeInter } #endif } - if (rl == _CFRunLoop0(kNilPthreadT)) _LastMainWaitSet = waitSet; + if (rl == CFRunLoopGetMain()) _LastMainWaitSet = waitSet; __CFRunLoopModeUnlock(rlm); #if DEPLOYMENT_TARGET_MACOSX @@ -1739,7 +1771,7 @@ static int32_t __CFRunLoopRun(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFTimeInter #endif if (destroyWaitSet) { __CFPortSetFree(waitSet); - if (rl == _CFRunLoop0(kNilPthreadT)) _LastMainWaitSet = 0; + if (rl == CFRunLoopGetMain()) _LastMainWaitSet = 0; } __CFRunLoopLock(rl); __CFRunLoopModeLock(rlm); @@ -2172,6 +2204,49 @@ void CFRunLoopRemoveSource(CFRunLoopRef rl, CFRunLoopSourceRef rls, CFStringRef } } +static void __CFRunLoopRemoveSourcesFromCommonMode(const void *value, void *ctx) { + CFStringRef modeName = (CFStringRef)value; + CFRunLoopRef rl = (CFRunLoopRef)ctx; + __CFRunLoopRemoveAllSources(rl, modeName); +} + +static void __CFRunLoopRemoveSourceFromMode(const void *value, void *ctx) { + CFRunLoopSourceRef rls = (CFRunLoopSourceRef)value; + CFRunLoopRef rl = (CFRunLoopRef)(((CFTypeRef *)ctx)[0]); + CFStringRef modeName = (CFStringRef)(((CFTypeRef *)ctx)[1]); + CFRunLoopRemoveSource(rl, rls, modeName); +} + +static void __CFRunLoopRemoveAllSources(CFRunLoopRef rl, CFStringRef modeName) { + CHECK_FOR_FORK(); + CFRunLoopModeRef rlm; + __CFRunLoopLock(rl); + if (modeName == kCFRunLoopCommonModes) { + if (NULL != rl->_commonModeItems) { + CFSetRef set = rl->_commonModes ? CFSetCreateCopy(kCFAllocatorSystemDefault, rl->_commonModes) : NULL; + __CFRunLoopUnlock(rl); + if (NULL != set) { + CFSetApplyFunction(set, (__CFRunLoopRemoveSourcesFromCommonMode), (void *)rl); + CFRelease(set); + } + } else { + __CFRunLoopUnlock(rl); + } + } else { + rlm = __CFRunLoopFindMode(rl, modeName, false); + __CFRunLoopUnlock(rl); + if (NULL != rlm && NULL != rlm->_sources) { + CFSetRef set = CFSetCreateCopy(kCFAllocatorSystemDefault, rlm->_sources); + __CFRunLoopModeUnlock(rlm); + CFTypeRef context[2] = {rl, modeName}; + CFSetApplyFunction(set, (__CFRunLoopRemoveSourceFromMode), (void *)context); + CFRelease(set); + } else if (NULL != rlm) { + __CFRunLoopModeUnlock(rlm); + } + } +} + Boolean CFRunLoopContainsObserver(CFRunLoopRef rl, CFRunLoopObserverRef rlo, CFStringRef modeName) { CHECK_FOR_FORK(); CFRunLoopModeRef rlm;