static void rlsPerform(void *info) { CFArrayRef changedKeys; void *context_info; void (*context_release)(const void *); SCDynamicStoreCallBack rlsFunction; SCDynamicStoreRef store = (SCDynamicStoreRef)info; SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; #ifdef DEBUG SCLog(_sc_verbose, LOG_DEBUG, CFSTR(" executing notification function")); #endif /* DEBUG */ changedKeys = SCDynamicStoreCopyNotifiedKeys(store); if (storePrivate->disconnectForceCallBack) { storePrivate->disconnectForceCallBack = FALSE; if (changedKeys == NULL) { changedKeys = CFArrayCreate(NULL, NULL, 0, &kCFTypeArrayCallBacks); } } else { if (changedKeys == NULL) { /* if no changes or something happened to the server */ return; } else if (CFArrayGetCount(changedKeys) == 0) { goto done; } } rlsFunction = storePrivate->rlsFunction; if (storePrivate->rlsContext.retain != NULL) { context_info = (void *)storePrivate->rlsContext.retain(storePrivate->rlsContext.info); context_release = storePrivate->rlsContext.release; } else { context_info = storePrivate->rlsContext.info; context_release = NULL; } if (rlsFunction != NULL) { (*rlsFunction)(store, changedKeys, context_info); } if (context_release != NULL) { context_release(context_info); } done : CFRelease(changedKeys); return; }
static Boolean __SCPreferencesUnscheduleFromRunLoop(SCPreferencesRef prefs, CFRunLoopRef runLoop, CFStringRef runLoopMode) { SCPreferencesPrivateRef prefsPrivate = (SCPreferencesPrivateRef)prefs; CFIndex n = 0; Boolean ok = FALSE; pthread_mutex_lock(&prefsPrivate->lock); if ((runLoop != NULL) && !prefsPrivate->scheduled) { // if we should be scheduled (but are not) _SCErrorSet(kSCStatusInvalidArgument); goto done; } if (((runLoop == NULL) && (prefsPrivate->dispatchQueue == NULL)) || // if we should be scheduled on a dispatch queue (but are not) ((runLoop != NULL) && (prefsPrivate->dispatchQueue != NULL))) { // if we should be scheduled on a CFRunLoop (but are scheduled on a dispatch queue) _SCErrorSet(kSCStatusInvalidArgument); goto done; } if (runLoop == NULL) { SCDynamicStoreSetDispatchQueue(prefsPrivate->session, NULL); dispatch_release(prefsPrivate->dispatchQueue); prefsPrivate->dispatchQueue = NULL; } else { if (!_SC_unschedule(prefs, runLoop, runLoopMode, prefsPrivate->rlList, FALSE)) { // if not currently scheduled on this runLoop / runLoopMode _SCErrorSet(kSCStatusInvalidArgument); goto done; } n = CFArrayGetCount(prefsPrivate->rlList); if (n == 0 || !_SC_isScheduled(NULL, runLoop, runLoopMode, prefsPrivate->rlList)) { /* * if we are no longer scheduled to receive notifications for * this runLoop / runLoopMode */ CFRunLoopRemoveSource(runLoop, prefsPrivate->rls, runLoopMode); if (n == 0) { // if *all* notifications have been unscheduled CFRelease(prefsPrivate->rlList); prefsPrivate->rlList = NULL; CFRunLoopSourceInvalidate(prefsPrivate->rls); CFRelease(prefsPrivate->rls); prefsPrivate->rls = NULL; } } } if (n == 0) { CFArrayRef changedKeys; // if *all* notifications have been unscheduled prefsPrivate->scheduled = FALSE; // no need to track changes (void) SCDynamicStoreSetNotificationKeys(prefsPrivate->session, NULL, NULL); // clear out any pending notifications changedKeys = SCDynamicStoreCopyNotifiedKeys(prefsPrivate->session); if (changedKeys != NULL) { CFRelease(changedKeys); } // release our reference to the prefs CFRelease(prefs); } ok = TRUE; done : pthread_mutex_unlock(&prefsPrivate->lock); return ok; }