Exemple #1
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);
    }
}
Exemple #2
0
/**
 * g_hook_next_valid:
 * @hook_list: a #GHookList
 * @hook: the current #GHook
 * @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 next #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 continue to call
 * g_hook_next_valid() until %NULL is returned.)
 *
 * Returns: the next valid #GHook, or %NULL if none are valid
 */
GHook*
g_hook_next_valid (GHookList *hook_list,
		   GHook     *hook,
		   gboolean   may_be_in_call)
{
  GHook *ohook = hook;

  g_return_val_if_fail (hook_list != NULL, NULL);

  if (!hook)
    return NULL;
  
  hook = hook->next;
  while (hook)
    {
      if (G_HOOK_IS_VALID (hook) && (may_be_in_call || !G_HOOK_IN_CALL (hook)))
	{
	  g_hook_ref (hook_list, hook);
	  g_hook_unref (hook_list, ohook);
	  
	  return hook;
	}
      hook = hook->next;
    }
  g_hook_unref (hook_list, ohook);

  return NULL;
}
Exemple #3
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);
    }
}
Exemple #4
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);
    }
}
Exemple #5
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);
    }
}
Exemple #6
0
void
g_hook_free (GHookList *hook_list,
	     GHook     *hook)
{
  g_return_if_fail (hook_list != NULL);
  g_return_if_fail (hook_list->is_setup);
  g_return_if_fail (hook != NULL);
  g_return_if_fail (G_HOOK_IS_UNLINKED (hook));
  g_return_if_fail (!G_HOOK_IN_CALL (hook));

  hook_list->finalize_hook (hook_list, hook);
  g_chunk_free (hook, hook_list->hook_memchunk);
}
Exemple #7
0
/**
 * g_hook_free:
 * @hook_list: a #GHookList
 * @hook: the #GHook to free
 *
 * Calls the #GHookList @finalize_hook function if it exists,
 * and frees the memory allocated for the #GHook.
 */
void
g_hook_free (GHookList *hook_list,
	     GHook     *hook)
{
  g_return_if_fail (hook_list != NULL);
  g_return_if_fail (hook_list->is_setup);
  g_return_if_fail (hook != NULL);
  g_return_if_fail (G_HOOK_IS_UNLINKED (hook));
  g_return_if_fail (!G_HOOK_IN_CALL (hook));

  if(hook_list->finalize_hook != NULL)
      hook_list->finalize_hook (hook_list, hook);
  g_slice_free1 (hook_list->hook_size, hook);
}
/* HOLDS: main_loop_lock */
static void
g_main_dispatch (GTimeVal *dispatch_time)
{
  while (pending_dispatches != NULL)
    {
      gboolean need_destroy;
      GSource *source = pending_dispatches->data;
      GSList *tmp_list;

      tmp_list = pending_dispatches;
      pending_dispatches = g_slist_remove_link (pending_dispatches, pending_dispatches);
      g_slist_free_1 (tmp_list);

      if (G_HOOK_IS_VALID (source))
	{
	  gboolean was_in_call;
	  gpointer hook_data = source->hook.data;
	  gpointer source_data = source->source_data;
	  gboolean (*dispatch) (gpointer,
				GTimeVal *,
				gpointer);

	  dispatch = ((GSourceFuncs *) source->hook.func)->dispatch;
	  
	  was_in_call = G_HOOK_IN_CALL (source);
	  source->hook.flags |= G_HOOK_FLAG_IN_CALL;

	  G_UNLOCK (main_loop);
	  need_destroy = ! dispatch (source_data,
				     dispatch_time,
				     hook_data);
	  G_LOCK (main_loop);

	  if (!was_in_call)
	    source->hook.flags &= ~G_HOOK_FLAG_IN_CALL;
	  
	  if (need_destroy && G_HOOK_IS_VALID (source))
	    g_hook_destroy_link (&source_list, (GHook *) source);
	}

      g_hook_unref (&source_list, (GHook*) source);
    }
}
Exemple #9
0
void
g_hook_unref (GHookList *hook_list,
	      GHook	*hook)
{
  g_return_if_fail (hook_list != NULL);
  g_return_if_fail (hook_list->hook_memchunk != NULL);
  g_return_if_fail (hook != NULL);
  g_return_if_fail (hook->ref_count > 0);
  
  hook->ref_count--;
  if (!hook->ref_count)
    {
      g_return_if_fail (hook->hook_id == 0);
      g_return_if_fail (!G_HOOK_IN_CALL (hook));

      if (hook->prev)
	hook->prev->next = hook->next;
      else
	hook_list->hooks = hook->next;
      if (hook->next)
	{
	  hook->next->prev = hook->prev;
	  hook->next = NULL;
	}
      hook->prev = NULL;

      if (!hook_list->is_setup)
	{
	  hook_list->is_setup = TRUE;
	  g_hook_free (hook_list, hook);
	  hook_list->is_setup = FALSE;
      
	  if (!hook_list->hooks)
	    {
	      g_mem_chunk_destroy (hook_list->hook_memchunk);
	      hook_list->hook_memchunk = NULL;
	    }
	}
      else
	g_hook_free (hook_list, hook);
    }
}
Exemple #10
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;
}
/* 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;
}