📄 gmain.c
字号:
g_static_mutex_free (&context->mutex);#endif g_ptr_array_free (context->pending_dispatches, TRUE); g_free (context->cached_poll_array); g_mem_chunk_destroy (context->poll_chunk);#ifdef G_THREADS_ENABLED if (g_thread_supported()) {#ifndef G_OS_WIN32 close (context->wake_up_pipe[0]); close (context->wake_up_pipe[1]);#else CloseHandle (context->wake_up_semaphore);#endif } else main_contexts_without_pipe = g_slist_remove (main_contexts_without_pipe, context);#endif g_free (context);}/** * g_main_context_unref: * @context: a #GMainContext * * Decreases the reference count on a #GMainContext object by one. If * the result is zero, free the context and free all associated memory. **/voidg_main_context_unref (GMainContext *context){ g_return_if_fail (context != NULL); g_return_if_fail (context->ref_count > 0); LOCK_CONTEXT (context); g_main_context_unref_and_unlock (context);}#ifdef G_THREADS_ENABLEDstatic void g_main_context_init_pipe (GMainContext *context){# ifndef G_OS_WIN32 if (pipe (context->wake_up_pipe) < 0) g_error ("Cannot create pipe main loop wake-up: %s\n", g_strerror (errno)); context->wake_up_rec.fd = context->wake_up_pipe[0]; context->wake_up_rec.events = G_IO_IN;# else context->wake_up_semaphore = CreateSemaphore (NULL, 0, 100, NULL); if (context->wake_up_semaphore == NULL) g_error ("Cannot create wake-up semaphore: %s", g_win32_error_message (GetLastError ())); context->wake_up_rec.fd = (gint) context->wake_up_semaphore; context->wake_up_rec.events = G_IO_IN;# ifdef G_MAIN_POLL_DEBUG g_print ("wake-up semaphore: %#x\n", (guint) context->wake_up_semaphore);# endif# endif g_main_context_add_poll_unlocked (context, 0, &context->wake_up_rec);}voidg_main_thread_init (){ GSList *curr = main_contexts_without_pipe; while (curr) { g_main_context_init_pipe ((GMainContext *)curr->data); curr = curr->next; } g_slist_free (main_contexts_without_pipe); main_contexts_without_pipe = NULL; }#endif /* G_THREADS_ENABLED *//** * g_main_context_new: * * Creates a new #GMainContext strcuture * * Return value: the new #GMainContext **/GMainContext *g_main_context_new (){ GMainContext *context = g_new0 (GMainContext, 1);#ifdef G_THREADS_ENABLED g_static_mutex_init (&context->mutex); context->owner = NULL; context->waiters = NULL;#endif context->ref_count = 1; context->next_id = 1; context->source_list = NULL;#if HAVE_POLL context->poll_func = (GPollFunc)poll;#else context->poll_func = g_poll;#endif context->cached_poll_array = NULL; context->cached_poll_array_size = 0; context->pending_dispatches = g_ptr_array_new (); context->time_is_current = FALSE;#ifdef G_THREADS_ENABLED if (g_thread_supported ()) g_main_context_init_pipe (context); else main_contexts_without_pipe = g_slist_prepend (main_contexts_without_pipe, context);#endif return context;}/** * g_main_context_default: * * Returns the default main context. This is the main context used * for main loop functions when a main loop is not explicitly * specified. * * Return value: the default main context. **/GMainContext *g_main_context_default (void){ /* Slow, but safe */ G_LOCK (main_loop); if (!default_main_context) default_main_context = g_main_context_new (); G_UNLOCK (main_loop); return default_main_context;}/* Hooks for adding to the main loop *//** * g_source_new: * @source_funcs: structure containing functions that implement * the sources behavior. * @struct_size: size of the #GSource structure to create. * * Creates a new #GSource structure. The size is specified to * allow creating structures derived from #GSource that contain * additional data. The size passed in must be at least * <literal>sizeof (GSource)</literal>. * * The source will not initially be associated with any #GMainContext * and must be added to one with g_source_add() before it will be * executed. * * Return value: the newly-created #GSource. **/GSource *g_source_new (GSourceFuncs *source_funcs, guint struct_size){ GSource *source; g_return_val_if_fail (source_funcs != NULL, NULL); g_return_val_if_fail (struct_size >= sizeof (GSource), NULL); source = (GSource*) g_malloc0 (struct_size); source->source_funcs = source_funcs; source->ref_count = 1; source->priority = G_PRIORITY_DEFAULT; source->flags = G_HOOK_FLAG_ACTIVE; /* NULL/0 initialization for all other fields */ return source;}/* Holds context's lock */static voidg_source_list_add (GSource *source, GMainContext *context){ GSource *tmp_source, *last_source; last_source = NULL; tmp_source = context->source_list; while (tmp_source && tmp_source->priority <= source->priority) { last_source = tmp_source; tmp_source = tmp_source->next; } source->next = tmp_source; if (tmp_source) tmp_source->prev = source; source->prev = last_source; if (last_source) last_source->next = source; else context->source_list = source;}/* Holds context's lock */static voidg_source_list_remove (GSource *source, GMainContext *context){ if (source->prev) source->prev->next = source->next; else context->source_list = source->next; if (source->next) source->next->prev = source->prev; source->prev = NULL; source->next = NULL;}/** * g_source_attach: * @source: a #GSource * @context: a #GMainContext (if %NULL, the default context will be used) * * Adds a #GSource to a @context so that it will be executed within * that context. * * Return value: the ID for the source within the #GMainContext **/guintg_source_attach (GSource *source, GMainContext *context){ guint result = 0; GSList *tmp_list; g_return_val_if_fail (source->context == NULL, 0); g_return_val_if_fail (!SOURCE_DESTROYED (source), 0); if (!context) context = g_main_context_default (); LOCK_CONTEXT (context); source->context = context; result = source->source_id = context->next_id++; source->ref_count++; g_source_list_add (source, context); tmp_list = source->poll_fds; while (tmp_list) { g_main_context_add_poll_unlocked (context, source->priority, tmp_list->data); tmp_list = tmp_list->next; }#ifdef G_THREADS_ENABLED /* Now wake up the main loop if it is waiting in the poll() */ g_main_context_wakeup_unlocked (context);#endif UNLOCK_CONTEXT (context); return result;}static voidg_source_destroy_internal (GSource *source, GMainContext *context, gboolean have_lock){ if (!have_lock) LOCK_CONTEXT (context); if (!SOURCE_DESTROYED (source)) { GSList *tmp_list; gpointer old_cb_data; GSourceCallbackFuncs *old_cb_funcs; source->flags &= ~G_HOOK_FLAG_ACTIVE; old_cb_data = source->callback_data; old_cb_funcs = source->callback_funcs; source->callback_data = NULL; source->callback_funcs = NULL; if (old_cb_funcs) { UNLOCK_CONTEXT (context); old_cb_funcs->unref (old_cb_data); LOCK_CONTEXT (context); } tmp_list = source->poll_fds; while (tmp_list) { g_main_context_remove_poll_unlocked (context, tmp_list->data); tmp_list = tmp_list->next; } g_source_unref_internal (source, context, TRUE); } if (!have_lock) UNLOCK_CONTEXT (context);}/** * g_source_destroy: * @source: a #GSource * * Removes a source from its #GMainContext, if any, and mark it as * destroyed. The source cannot be subsequently added to another * context. **/voidg_source_destroy (GSource *source){ GMainContext *context; g_return_if_fail (source != NULL); context = source->context; if (context) g_source_destroy_internal (source, context, FALSE); else source->flags &= ~G_HOOK_FLAG_ACTIVE;}/** * g_source_get_id: * @source: a #GSource * * Returns the numeric ID for a particular source. The ID of a source * is unique within a particular main loop context. The reverse * mapping from ID to source is done by g_main_context_find_source_by_id(). * * Return value: the ID for the source **/guintg_source_get_id (GSource *source){ guint result; g_return_val_if_fail (source != NULL, 0); g_return_val_if_fail (source->context != NULL, 0); LOCK_CONTEXT (source->context); result = source->source_id; UNLOCK_CONTEXT (source->context); return result;}/** * g_source_get_context: * @source: a #GSource * * Gets the #GMainContext with which the source is associated. * Calling this function on a destroyed source is an error. * * Return value: the #GMainContext with which the source is associated, * or %NULL if the context has not yet been added * to a source. **/GMainContext *g_source_get_context (GSource *source){ g_return_val_if_fail (!SOURCE_DESTROYED (source), NULL); return source->context;}/** * g_source_add_poll: * @source:a #GSource * @fd: a #GPollFD structure holding information about a file * descriptor to watch. * * Adds a file descriptor to the set of file descriptors polled for * this source. This is usually combined with g_source_new() to add an * event source. The event source's check function will typically test * the @revents field in the #GPollFD struct and return %TRUE if events need * to be processed. **/voidg_source_add_poll (GSource *source, GPollFD *fd){ GMainContext *context; g_return_if_fail (source != NULL); g_return_if_fail (fd != NULL); g_return_if_fail (!SOURCE_DESTROYED (source)); context = source->context; if (context) LOCK_CONTEXT (context); source->poll_fds = g_slist_prepend (source->poll_fds, fd); if (context) { g_main_context_add_poll_unlocked (context, source->priority, fd); UNLOCK_CONTEXT (context); }}/** * g_source_remove_poll: * @source:a #GSource * @fd: a #GPollFD structure previously passed to g_source_poll(). * * Removes a file descriptor from the set of file descriptors polled for * this source. **/voidg_source_remove_poll (GSource *source, GPollFD *fd){ GMainContext *context; g_return_if_fail (source != NULL); g_return_if_fail (fd != NULL); g_return_if_fail (!SOURCE_DESTROYED (source)); context = source->context; if (context) LOCK_CONTEXT (context); source->poll_fds = g_slist_remove (source->poll_fds, fd); if (context) { g_main_context_remove_poll_unlocked (context, fd); UNLOCK_CONTEXT (context); }}/** * g_source_set_callback_indirect: * @source: the source * @callback_data: pointer to callback data "object" * @callback_funcs: functions for reference counting @callback_data * and getting the callback and data * * Sets the callback function storing the data as a refcounted callback * "object". This is used to implement g_source_set_callback_closure() * and internally. Note that calling g_source_set_callback_indirect() assumes * an initial reference count on @callback_data, and thus * @callback_funcs->unref will eventually be called once more * than @callback_funcs->ref. **/voidg_source_set_callback_indirect (GSource *source, gpointer callback_data, GSourceCallbackFuncs *callback_funcs){ GMainContext *context; gpointer old_cb_data; GSourceCallbackFuncs *old_cb_funcs; g_return_if_fail (source != NULL); g_return_if_fail (callback_funcs != NULL || callback_data == NULL); context = source->context; if (context) LOCK_CONTEXT (context); old_cb_data = source->callback_data; old_cb_funcs = source->callback_funcs; source->callback_data = callback_data; source->callback_funcs = callback_funcs; if (context) UNLOCK_CONTEXT (context); if (old_cb_funcs) old_cb_funcs->unref (old_cb_data);}static voidg_source_callback_ref (gpointer cb_data){ GSourceCallback *callback = cb_data; callback->ref_count++;}static voidg_source_callback_unref (gpointer cb_data){ GSourceCallback *callback = cb_data; callback->ref_count--; if (callback->ref_count == 0) { if (callback->notify) callback->notify (callback->data); g_free (callback); }}static voidg_source_callback_get (gpointer cb_data, GSource *source, GSourceFunc *func, gpointer *data){ GSourceCallback *callback = cb_data; *func = callback->func; *data = callback->data;}static GSourceCallbackFuncs g_source_callback_funcs = { g_source_callback_ref, g_source_callback_unref, g_source_callback_get,};/** * g_source_set_callback: * @source: the source * @func: a callback function * @data: the data to pass to callback function
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -