/** * The callback for when the main thread has issued a command to the run loop * thread. Reads all the pending commands and executes them */ static void command_callback( CFFileDescriptorRef fdref, CFOptionFlags callBackTypes, void *context) { int fd = CFFileDescriptorGetNativeDescriptor(fdref); struct thread_env *thread_env = (struct thread_env *)context; struct command *to_do = NULL; struct command *to_free = NULL; clear_pipe(fd); do { to_do = *(thread_env->commands); } while (OSAtomicCompareAndSwapPtr(to_do, NULL, (void *)(thread_env->commands)) == false); while (to_do != NULL) { switch (to_do->type) { case ADD_WATCH: add_watch(to_do->arg, thread_env); break; case RM_WATCH: // hh_server doesn't need this at the moment. Shouldn't be too hard to // do...just need to map of paths to FSEvent streams. fprintf(stderr, "fsevents impl doesn't support removing watches yet\n"); break; } to_free = to_do; to_do = to_do->next; free(to_free->arg); free(to_free); } // For some reason you have to re-enable this callback every bloody time CFFileDescriptorEnableCallBacks(fdref, kCFFileDescriptorReadCallBack); }
/** * Grabs the events that are ready to be processed from the linked list and * clears the list */ static struct event *read_events(struct env *env) { struct event *to_do = NULL; clear_pipe(env->read_event_fd); do { to_do = *(env->events); } while (OSAtomicCompareAndSwapPtr(to_do, NULL, (void *)(env->events)) == false); return to_do; }
void cmus_provide_next_track(void) { clear_pipe(cmus_next_track_request_fd, 1); cmus_next_file_lock(); cmus_next_file = cmus_get_next_from_main_thread(); cmus_next_file_provided = 1; cmus_next_file_unlock(); pthread_cond_broadcast(&cmus_next_file_cond); }