Beispiel #1
0
/**
 * 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);
    }
}
Beispiel #2
0
/**
 * 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);
    }
}
Beispiel #3
0
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);
    }
}
Beispiel #4
0
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);
    }
}
Beispiel #5
0
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);
    }
}
Beispiel #6
0
/**
 * g_hook_first_valid:
 * @hook_list: a #GHookList
 * @may_be_in_call: %TRUE if hooks which are currently running
 *     (e.g. in another thread) are considered valid. If set to %FALSE,
 *     these are skipped
 *
 * Returns the first #GHook in a #GHookList which has not been destroyed.
 * The reference count for the #GHook is incremented, so you must call
 * g_hook_unref() to restore it when no longer needed. (Or call
 * g_hook_next_valid() if you are stepping through the #GHookList.)
 *
 * Returns: the first valid #GHook, or %NULL if none are valid
 */
GHook*
g_hook_first_valid (GHookList *hook_list,
		    gboolean   may_be_in_call)
{
  g_return_val_if_fail (hook_list != NULL, NULL);
  
  if (hook_list->is_setup)
    {
      GHook *hook;
      
      hook = hook_list->hooks;
      if (hook)
	{
	  g_hook_ref (hook_list, hook);
	  if (G_HOOK_IS_VALID (hook) && (may_be_in_call || !G_HOOK_IN_CALL (hook)))
	    return hook;
	  else
	    return g_hook_next_valid (hook_list, hook, may_be_in_call);
	}
    }
  
  return NULL;
}
Beispiel #7
0
/* 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 (&current_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 (&current_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, &current_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 (&current_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, &current_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 (&current_time);
      retval = TRUE;
    }

  G_UNLOCK (main_loop);

  return retval;
}