/* IN EVENT OR INVOKE THREAD */ static void hrt_watcher_io_start(HrtWatcher *watcher) { HrtWatcherGLib *gwatcher = (HrtWatcherGLib*) watcher; HrtWatcherIo *io_watcher = (HrtWatcherIo*) watcher; if (gwatcher->source == NULL) { GSource *source; source = g_io_create_watch(io_watcher->channel, io_watcher->condition); _hrt_watcher_ref(watcher); g_source_set_callback(source, (GSourceFunc) run_watcher_io_func, watcher, watcher_dnotify); gwatcher->source = source; /* takes the ref */ /* When we attach the source, we're addding it to the event * thread, and it can IMMEDIATELY RUN so from here, the * watcher is subject to re-entrancy even on initial * construct. */ g_source_attach(source, hrt_watcher_get_g_main_context(watcher)); } }
static HrtInvoker* hrt_invoker_new(HrtTask *task, HrtWatcher *first_watcher) { HrtInvoker *invoker; invoker = g_slice_new(HrtInvoker); invoker->refcount = 1; invoker->task = task; g_object_ref(task); invoker->pending_watchers_lock = g_mutex_new(); g_queue_init(&invoker->pending_watchers); /* passing in first_watcher lets us avoid locking the queue for * just one watcher which is probably the most common case. * Using GStaticMutex we could even potentially * avoid creating a mutex, but for now skipping that. */ _hrt_watcher_ref(first_watcher); g_queue_push_tail(&invoker->pending_watchers, first_watcher); return invoker; }
static void hrt_invoker_queue_watcher(HrtInvoker *invoker, HrtWatcher *watcher) { _hrt_watcher_ref(watcher); g_mutex_lock(invoker->pending_watchers_lock); g_queue_push_tail(&invoker->pending_watchers, watcher); g_mutex_unlock(invoker->pending_watchers_lock); }