📄 gmain.c
字号:
UNLOCK_CONTEXT (context); return FALSE; } } else LOCK_CONTEXT (context);#endif /* G_THREADS_ENABLED */ if (!context->cached_poll_array) { context->cached_poll_array_size = context->n_poll_records; context->cached_poll_array = g_new (GPollFD, context->n_poll_records); } allocated_nfds = context->cached_poll_array_size; fds = context->cached_poll_array; UNLOCK_CONTEXT (context); some_ready = g_main_context_prepare (context, &max_priority); while ((nfds = g_main_context_query (context, max_priority, &timeout, fds, allocated_nfds)) > allocated_nfds) { LOCK_CONTEXT (context); g_free (fds); context->cached_poll_array_size = allocated_nfds = nfds; context->cached_poll_array = fds = g_new (GPollFD, nfds); UNLOCK_CONTEXT (context); } if (!block) timeout = 0; g_main_context_poll (context, timeout, max_priority, fds, nfds); g_main_context_check (context, max_priority, fds, nfds); if (dispatch) g_main_context_dispatch (context); #ifdef G_THREADS_ENABLED g_main_context_release (context);#endif /* G_THREADS_ENABLED */ LOCK_CONTEXT (context); return some_ready;}/** * g_main_context_pending: * @context: a #GMainContext (if %NULL, the default context will be used) * * Checks if any sources have pending events for the given context. * * Return value: %TRUE if events are pending. **/gboolean g_main_context_pending (GMainContext *context){ gboolean retval; if (!context) context = g_main_context_default(); LOCK_CONTEXT (context); retval = g_main_context_iterate (context, FALSE, FALSE, G_THREAD_SELF); UNLOCK_CONTEXT (context); return retval;}/** * g_main_context_iteration: * @context: a #GMainContext (if %NULL, the default context will be used) * @may_block: whether the call may block. * * Runs a single iteration for the given main loop. This involves * checking to see if any event sources are ready to be processed, * then if no events sources are ready and @may_block is %TRUE, waiting * for a source to become ready, then dispatching the highest priority * events sources that are ready. Note that even when @may_block is %TRUE, * it is still possible for g_main_context_iteration() to return * %FALSE, since the the wait may be interrupted for other * reasons than an event source becoming ready. * * Return value: %TRUE if events were dispatched. **/gbooleang_main_context_iteration (GMainContext *context, gboolean may_block){ gboolean retval; if (!context) context = g_main_context_default(); LOCK_CONTEXT (context); retval = g_main_context_iterate (context, may_block, TRUE, G_THREAD_SELF); UNLOCK_CONTEXT (context); return retval;}/** * g_main_loop_new: * @context: a #GMainContext (if %NULL, the default context will be used). * @is_running: set to %TRUE to indicate that the loop is running. This * is not very important since calling g_main_loop_run() will set this to * %TRUE anyway. * * Creates a new #GMainLoop structure. * * Return value: a new #GMainLoop. **/GMainLoop *g_main_loop_new (GMainContext *context, gboolean is_running){ GMainLoop *loop; if (!context) context = g_main_context_default(); g_main_context_ref (context); loop = g_new0 (GMainLoop, 1); loop->context = context; loop->is_running = is_running != FALSE; loop->ref_count = 1; return loop;}/** * g_main_loop_ref: * @loop: a #GMainLoop * * Increases the reference count on a #GMainLoop object by one. * * Return value: @loop **/GMainLoop *g_main_loop_ref (GMainLoop *loop){ g_return_val_if_fail (loop != NULL, NULL); g_return_val_if_fail (loop->ref_count > 0, NULL); LOCK_CONTEXT (loop->context); loop->ref_count++; UNLOCK_CONTEXT (loop->context); return loop;}static voidg_main_loop_unref_and_unlock (GMainLoop *loop){ loop->ref_count--; if (loop->ref_count == 0) { /* When the ref_count is 0, there can be nobody else using the * loop, so it is safe to unlock before destroying. */ g_main_context_unref_and_unlock (loop->context); g_free (loop); } else UNLOCK_CONTEXT (loop->context);}/** * g_main_loop_unref: * @loop: a #GMainLoop * * Decreases the reference count on a #GMainLoop object by one. If * the result is zero, free the loop and free all associated memory. **/voidg_main_loop_unref (GMainLoop *loop){ g_return_if_fail (loop != NULL); g_return_if_fail (loop->ref_count > 0); LOCK_CONTEXT (loop->context); g_main_loop_unref_and_unlock (loop);}/** * g_main_loop_run: * @loop: a #GMainLoop * * Runs a main loop until g_main_loop_quit() is called on the loop. * If this is called for the thread of the loop's #GMainContext, * it will process events from the loop, otherwise it will * simply wait. **/void g_main_loop_run (GMainLoop *loop){ GThread *self = G_THREAD_SELF; g_return_if_fail (loop != NULL); g_return_if_fail (loop->ref_count > 0);#ifdef G_THREADS_ENABLED if (!g_main_context_acquire (loop->context)) { gboolean got_ownership = FALSE; /* Another thread owns this context */ if (!g_thread_supported ()) { g_warning ("g_main_loop_run() was called from second thread but " "g_thread_init() was never called."); return; } LOCK_CONTEXT (loop->context); loop->ref_count++; if (!loop->is_running) loop->is_running = TRUE; if (!loop->context->cond) loop->context->cond = g_cond_new (); while (loop->is_running || !got_ownership) got_ownership = g_main_context_wait (loop->context, loop->context->cond, g_static_mutex_get_mutex (&loop->context->mutex)); if (!loop->is_running) { UNLOCK_CONTEXT (loop->context); if (got_ownership) g_main_context_release (loop->context); g_main_loop_unref (loop); return; } g_assert (got_ownership); } else LOCK_CONTEXT (loop->context);#endif /* G_THREADS_ENABLED */ if (loop->context->in_check_or_prepare) { g_warning ("g_main_loop_run(): called recursively from within a source's " "check() or prepare() member, iteration not possible."); return; } loop->ref_count++; loop->is_running = TRUE; while (loop->is_running) g_main_context_iterate (loop->context, TRUE, TRUE, self); UNLOCK_CONTEXT (loop->context); #ifdef G_THREADS_ENABLED g_main_context_release (loop->context);#endif /* G_THREADS_ENABLED */ g_main_loop_unref (loop);}/** * g_main_loop_quit: * @loop: a #GMainLoop * * Stops a #GMainLoop from running. Any calls to g_main_loop_run() * for the loop will return. **/void g_main_loop_quit (GMainLoop *loop){ g_return_if_fail (loop != NULL); g_return_if_fail (loop->ref_count > 0); LOCK_CONTEXT (loop->context); loop->is_running = FALSE; g_main_context_wakeup_unlocked (loop->context);#ifdef G_THREADS_ENABLED if (loop->context->cond) g_cond_broadcast (loop->context->cond);#endif /* G_THREADS_ENABLED */ UNLOCK_CONTEXT (loop->context);}/** * g_main_loop_is_running: * @loop: a #GMainLoop. * * Checks to see if the main loop is currently being run via g_main_loop_run(). * * Return value: %TRUE if the mainloop is currently being run. **/gbooleang_main_loop_is_running (GMainLoop *loop){ g_return_val_if_fail (loop != NULL, FALSE); g_return_val_if_fail (loop->ref_count > 0, FALSE); return loop->is_running;}/** * g_main_loop_get_context: * @loop: a #GMainLoop. * * Returns the #GMainContext of @loop. * * Return value: the #GMainContext of @loop **/GMainContext *g_main_loop_get_context (GMainLoop *loop){ g_return_val_if_fail (loop != NULL, NULL); g_return_val_if_fail (loop->ref_count > 0, NULL); return loop->context;}/* HOLDS: context's lock */static voidg_main_context_poll (GMainContext *context, gint timeout, gint priority, GPollFD *fds, gint n_fds){#ifdef G_MAIN_POLL_DEBUG GTimer *poll_timer; GPollRec *pollrec; gint i;#endif GPollFunc poll_func; if (n_fds || timeout != 0) {#ifdef G_MAIN_POLL_DEBUG g_print ("g_main_poll(%d) timeout: %d\n", n_fds, timeout); poll_timer = g_timer_new ();#endif LOCK_CONTEXT (context); poll_func = context->poll_func; UNLOCK_CONTEXT (context); if ((*poll_func) (fds, n_fds, timeout) < 0 && errno != EINTR) g_warning ("poll(2) failed due to: %s.", g_strerror (errno)); #ifdef G_MAIN_POLL_DEBUG LOCK_CONTEXT (context); g_print ("g_main_poll(%d) timeout: %d - elapsed %12.10f seconds", n_fds, timeout, g_timer_elapsed (poll_timer, NULL)); g_timer_destroy (poll_timer); pollrec = context->poll_records; i = 0; while (i < n_fds) { if (pollrec->fd->events) { if (fds[i].revents) { g_print (" [%d:", fds[i].fd); if (fds[i].revents & G_IO_IN) g_print ("i"); if (fds[i].revents & G_IO_OUT) g_print ("o"); if (fds[i].revents & G_IO_PRI) g_print ("p"); if (fds[i].revents & G_IO_ERR) g_print ("e"); if (fds[i].revents & G_IO_HUP) g_print ("h"); if (fds[i].revents & G_IO_NVAL) g_print ("n"); g_print ("]"); } i++; } pollrec = pollrec->next; } g_print ("\n"); UNLOCK_CONTEXT (context);#endif } /* if (n_fds || timeout != 0) */}/** * g_main_context_add_poll: * @context: a #GMainContext (or %NULL for the default context) * @fd: a #GPollFD structure holding information about a file * descriptor to watch. * @priority: the priority for this file descriptor which should be * the same as the priority used for g_source_attach() to ensure that the * file descriptor is polled whenever the results may be needed. * * Adds a file descriptor to the set of file descriptors polled for * this context. This will very seldomly be used directly. Instead * a typical event source will use g_source_add_poll() instead. **/voidg_main_context_add_poll (GMainContext *context, GPollFD *fd, gint priority){ if (!context) context = g_main_context_default (); g_return_if_fail (context->ref_count > 0); g_return_if_fail (fd); LOCK_CONTEXT (context); g_main_context_add_poll_unlocked (context, priority, fd); UNLOCK_CONTEXT (context);}/* HOLDS: main_loop_lock */static void g_main_context_add_poll_unlocked (GMainContext *context, gint priority, GPollFD *fd){ GPollRec *lastrec, *pollrec, *newrec; if (!context->poll_chunk) context->poll_chunk = g_mem_chunk_create (GPollRec, 32, G_ALLOC_ONLY); if (context->poll_free_list) { newrec = context->poll_free_list; context->poll_free_list = newrec->next; } else newrec = g_chunk_new (GPollRec, context->poll_chunk); /* This file descriptor may be checked before we ever poll */ fd->revents = 0; newrec->fd = fd; newrec->priority = priority; lastrec = NULL; pollrec = context->poll_records; while (pollrec && priority >= pollrec->priority) { lastrec = pollrec; pollrec = pollrec->next; } if (lastrec) lastrec->next = newrec; else context->poll_records = newrec; newrec->next = pollrec; context->n_poll_records++;#ifdef G_THREADS_ENABLED context->poll_changed = TRUE; /* Now wake up the main loop if it is waiting in the poll() */ g_main_context_wakeup_unlocked (context);#endif}/** * g_main_context_remove_poll: * @context:a #GMainContext * @fd: a #GPollFD descriptor previously added with g_main_context_add_poll() * * Removes file descriptor from the set of file descriptors to be * polled for a particular context. **/voidg_main_context_remove_poll (GMainContext *context, GPollFD *fd){ if (!context) context = g_main_context_default (); g_return_if_fail (context->ref_count > 0); g_return_if_fail (fd); LOCK_CONTEXT (context); g_main_context_remove_poll_unlocked (context, fd); UNLOCK_CONTEXT (context);}static voidg_main_context_remove_poll_unlocked (GMainContext *context, GPollFD *fd){ GPollRec *pollrec, *lastrec; lastrec = NULL; pollrec = context->poll_records; while (pollrec) { if (pollrec->fd == fd) { if (lastrec != NULL) lastrec->next = pollrec->next; else context->poll_records = pollrec->next;#ifdef ENABLE_GC_FRIENDLY pollrec->fd = NULL; #endif /* ENABLE_GC_FRIENDLY */ pollrec->next = context->poll_free_list; context->poll_free_list = pollrec; context->n_poll_records--; break; } lastrec = pollrec; pollrec = pollrec->next; }#ifdef G_THREADS_ENABLED context->poll_changed = TRUE; /* Now wake up the main loop if it is waiting in the poll() */ g_main_context_wakeup_unlocked (context);#endif}/** * g_source_get_current_time: * @source: a #GSource * @timeval: #GTimeVal structure in which to store current time. * * Gets the "current time" to be used when checking * this source. The advantage of calling this function over * calling g_get_current_time() directly is that when * checking multiple sources, GLib can cache a single value * instead of having to repeatedly get the system time. **/voidg_source_get_curr
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -