/** * g_hook_list_marshal: * @hook_list: a #GHookList * @may_recurse: %TRUE if hooks which are currently running * (e.g. in another thread) are considered valid. If set to %FALSE, * these are skipped * @marshaller: the function to call for each #GHook * @marshal_data: data to pass to @marshaller * * Calls a function on each valid #GHook. */ void g_hook_list_marshal (GHookList *hook_list, gboolean may_recurse, GHookMarshaller marshaller, gpointer data) { GHook *hook; g_return_if_fail (hook_list != NULL); g_return_if_fail (hook_list->is_setup); g_return_if_fail (marshaller != NULL); hook = g_hook_first_valid (hook_list, may_recurse); while (hook) { gboolean was_in_call; was_in_call = G_HOOK_IN_CALL (hook); hook->flags |= G_HOOK_FLAG_IN_CALL; marshaller (hook, data); if (!was_in_call) hook->flags &= ~G_HOOK_FLAG_IN_CALL; hook = g_hook_next_valid (hook_list, hook, may_recurse); } }
/** * g_hook_list_invoke_check: * @hook_list: a #GHookList * @may_recurse: %TRUE if functions which are already running * (e.g. in another thread) can be called. If set to %FALSE, * these are skipped * * Calls all of the #GHook functions in a #GHookList. * Any function which returns %FALSE is removed from the #GHookList. */ void g_hook_list_invoke_check (GHookList *hook_list, gboolean may_recurse) { GHook *hook; g_return_if_fail (hook_list != NULL); g_return_if_fail (hook_list->is_setup); hook = g_hook_first_valid (hook_list, may_recurse); while (hook) { GHookCheckFunc func; gboolean was_in_call; gboolean need_destroy; func = (GHookCheckFunc) hook->func; was_in_call = G_HOOK_IN_CALL (hook); hook->flags |= G_HOOK_FLAG_IN_CALL; need_destroy = !func (hook->data); if (!was_in_call) hook->flags &= ~G_HOOK_FLAG_IN_CALL; if (need_destroy) g_hook_destroy_link (hook_list, hook); hook = g_hook_next_valid (hook_list, hook, may_recurse); } }
EXPORT_C void g_hook_list_marshal_check (GHookList *hook_list, gboolean may_recurse, GHookCheckMarshaller marshaller, gpointer data) { GHook *hook; g_return_if_fail (hook_list != NULL); g_return_if_fail (hook_list->is_setup); g_return_if_fail (marshaller != NULL); hook = g_hook_first_valid (hook_list, may_recurse); while (hook) { gboolean was_in_call; gboolean need_destroy; was_in_call = G_HOOK_IN_CALL (hook); hook->flags |= G_HOOK_FLAG_IN_CALL; need_destroy = !marshaller (hook, data); if (!was_in_call) hook->flags &= ~G_HOOK_FLAG_IN_CALL; if (need_destroy) g_hook_destroy_link (hook_list, hook); hook = g_hook_next_valid (hook_list, hook, may_recurse); } }
EXPORT_C void g_hook_list_invoke (GHookList *hook_list, gboolean may_recurse) { GHook *hook; g_return_if_fail (hook_list != NULL); g_return_if_fail (hook_list->is_setup); hook = g_hook_first_valid (hook_list, may_recurse); while (hook) { GHookFunc func; gboolean was_in_call; func = (GHookFunc) hook->func; was_in_call = G_HOOK_IN_CALL (hook); hook->flags |= G_HOOK_FLAG_IN_CALL; func (hook->data); if (!was_in_call) hook->flags &= ~G_HOOK_FLAG_IN_CALL; hook = g_hook_next_valid (hook_list, hook, may_recurse); } }
void qof_session_call_close_hooks (QofSession *session) { GHook *hook; GFunc fn; if (session_closed_hooks == NULL) return; hook = g_hook_first_valid (session_closed_hooks, FALSE); while (hook) { fn = (GFunc)hook->func; fn(session, hook->data); hook = g_hook_next_valid (session_closed_hooks, hook, FALSE); } }
/* Run each process being managed by the process manager. DELTA_T is the time since this was last called, according to the timer in the main loop. */ int pm_iterate (double delta_t) { gint proc_count = 0; GHook *proc; pm_set_delta_time (delta_t); /* Call all the processes being managed by the process manager, skipping any slow processes that aren't complete from the last iteration. (Any process that returns FALSE is culled.) */ g_hook_list_invoke_check (pm, FALSE); proc = g_hook_first_valid (pm, TRUE); /* Count the number of processes being managed by the process manager. */ while (proc != NULL) { proc_count ++; proc = g_hook_next_valid (pm, proc, TRUE); } return proc_count; }
/* g_main_iterate () runs a single iteration of the mainloop, or, * if !dispatch checks to see if any sources need dispatching. * basic algorithm for dispatch=TRUE: * * 1) while the list of currently pending sources is non-empty, * we call (*dispatch) on those that are !IN_CALL or can_recurse, * removing sources from the list after each returns. * the return value of (*dispatch) determines whether the source * itself is kept alive. * * 2) call (*prepare) for sources that are not yet SOURCE_READY and * are !IN_CALL or can_recurse. a return value of TRUE determines * that the source would like to be dispatched immediatedly, it * is then flagged as SOURCE_READY. * * 3) poll with the pollfds from all sources at the priority of the * first source flagged as SOURCE_READY. if there are any sources * flagged as SOURCE_READY, we use a timeout of 0 or the minimum * of all timouts otherwise. * * 4) for each source !IN_CALL or can_recurse, if SOURCE_READY or * (*check) returns true, add the source to the pending list. * once one source returns true, stop after checking all sources * at that priority. * * 5) while the list of currently pending sources is non-empty, * call (*dispatch) on each source, removing the source * after the call. * */ static gboolean g_main_iterate (gboolean block, gboolean dispatch) { GHook *hook; GTimeVal current_time = { 0, 0 }; gint n_ready = 0; gint current_priority = 0; gint timeout; gboolean retval = FALSE; g_return_val_if_fail (!block || dispatch, FALSE); g_get_current_time (¤t_time); G_LOCK (main_loop); #ifdef G_THREADS_ENABLED if (poll_waiting) { g_warning("g_main_iterate(): main loop already active in another thread"); G_UNLOCK (main_loop); return FALSE; } #endif /* If recursing, finish up current dispatch, before starting over */ if (pending_dispatches) { if (dispatch) g_main_dispatch (¤t_time); G_UNLOCK (main_loop); return TRUE; } /* Prepare all sources */ timeout = block ? -1 : 0; hook = g_hook_first_valid (&source_list, TRUE); while (hook) { GSource *source = (GSource*) hook; gint source_timeout = -1; if ((n_ready > 0) && (source->priority > current_priority)) { g_hook_unref (&source_list, hook); break; } if (G_HOOK_IN_CALL (hook) && !(hook->flags & G_SOURCE_CAN_RECURSE)) { hook = g_hook_next_valid (&source_list, hook, TRUE); continue; } if (!(hook->flags & G_SOURCE_READY)) { gboolean (*prepare) (gpointer source_data, GTimeVal *current_time, gint *timeout, gpointer user_data); prepare = ((GSourceFuncs *) hook->func)->prepare; in_check_or_prepare++; G_UNLOCK (main_loop); if ((*prepare) (source->source_data, ¤t_time, &source_timeout, source->hook.data)) hook->flags |= G_SOURCE_READY; G_LOCK (main_loop); in_check_or_prepare--; } if (hook->flags & G_SOURCE_READY) { if (!dispatch) { g_hook_unref (&source_list, hook); G_UNLOCK (main_loop); return TRUE; } else { n_ready++; current_priority = source->priority; timeout = 0; } } if (source_timeout >= 0) { if (timeout < 0) timeout = source_timeout; else timeout = MIN (timeout, source_timeout); } hook = g_hook_next_valid (&source_list, hook, TRUE); } /* poll(), if necessary */ g_main_poll (timeout, n_ready > 0, current_priority); if (timeout != 0) g_get_current_time (¤t_time); /* Check to see what sources need to be dispatched */ n_ready = 0; hook = g_hook_first_valid (&source_list, TRUE); while (hook) { GSource *source = (GSource *)hook; if ((n_ready > 0) && (source->priority > current_priority)) { g_hook_unref (&source_list, hook); break; } if (G_HOOK_IN_CALL (hook) && !(hook->flags & G_SOURCE_CAN_RECURSE)) { hook = g_hook_next_valid (&source_list, hook, TRUE); continue; } if (!(hook->flags & G_SOURCE_READY)) { gboolean (*check) (gpointer source_data, GTimeVal *current_time, gpointer user_data); check = ((GSourceFuncs *) hook->func)->check; in_check_or_prepare++; G_UNLOCK (main_loop); if ((*check) (source->source_data, ¤t_time, source->hook.data)) hook->flags |= G_SOURCE_READY; G_LOCK (main_loop); in_check_or_prepare--; } if (hook->flags & G_SOURCE_READY) { if (dispatch) { hook->flags &= ~G_SOURCE_READY; g_hook_ref (&source_list, hook); pending_dispatches = g_slist_prepend (pending_dispatches, source); current_priority = source->priority; n_ready++; } else { g_hook_unref (&source_list, hook); G_UNLOCK (main_loop); return TRUE; } } hook = g_hook_next_valid (&source_list, hook, TRUE); } /* Now invoke the callbacks */ if (pending_dispatches) { pending_dispatches = g_slist_reverse (pending_dispatches); g_main_dispatch (¤t_time); retval = TRUE; } G_UNLOCK (main_loop); return retval; }