Beispiel #1
0
void svc_accessor::stop()
{
    // stop main loop
    if (main_loop_)
    {
        GMainLoop* loop = main_loop_.get();
        if (loop && g_main_loop_is_running(loop))
        {
            g_main_loop_quit(loop);
            loop_thread_->join();

            // wait for exit thread
            loop_thread_.reset();
        }

        // wait for clear context
        GMainContext* main_context = g_main_loop_get_context(loop);
        while(!g_main_context_acquire(main_context))
                sched_yield();

        g_main_context_release(main_context_.get());
        main_context_.reset();
        main_loop_.reset();
        // unregister service
        if (svc_)
            svc_.reset();
    }
}
Beispiel #2
0
void
ags_gui_task_thread_run(AgsThread *thread)
{
  AgsGuiThread *gui_thread;
  GMainContext *main_context;

  gui_thread = AGS_AUDIO_LOOP(AGS_MAIN(AGS_DEVOUT(thread->devout)->ags_main)->main_loop)->gui_thread;
  main_context = g_main_context_default();

  if(!g_main_context_acquire(main_context)){
    gboolean got_ownership = FALSE;

    while(!got_ownership){
      got_ownership = g_main_context_wait(main_context,
					  &(gui_thread->cond),
					  &(gui_thread->mutex));
    }
  }

  gdk_threads_enter();
  gdk_threads_leave();

  g_main_context_iteration(main_context, FALSE);

  AGS_THREAD_CLASS(ags_gui_task_thread_parent_class)->run(thread);

  g_main_context_release(main_context);
}
Beispiel #3
0
static void
main_loop_dispatch (void)
{
  GMainContext *context = g_main_loop_get_context (loop);
  if (!g_main_context_acquire (context))
    abort ();

  g_main_context_dispatch (context);
  g_main_context_release (context);
}
Beispiel #4
0
CAMLprim value lwt_glib_iter(value may_block)
{
  GMainContext *gc;
  gint max_priority, timeout;
  GPollFD *pollfds = NULL;
  gint pollfds_size = 0;
  gint nfds;
  gint i;

  /* Get the main context. */
  gc = g_main_context_default();

  /* Try to acquire it. */
  if (!g_main_context_acquire(gc))
    caml_failwith("Lwt_glib.iter");

  /* Dispatch pending events. */
  g_main_context_dispatch(gc);

  /* Prepare the context for polling. */
  g_main_context_prepare(gc, &max_priority);

  /* Get all file descriptors to poll. */
  while (pollfds_size < (nfds = g_main_context_query(gc, max_priority, &timeout, pollfds, pollfds_size))) {
    free(pollfds);
    pollfds_size = nfds;
    pollfds = lwt_unix_malloc(pollfds_size * sizeof (GPollFD));
  }

  /* Clear all revents fields. */
  for (i = 0; i < nfds; i++) pollfds[i].revents = 0;

  /* Set the timeout to 0 if we do not want to block. */
  if (!Bool_val(may_block)) timeout = 0;

  /* Do the blocking call. */
  caml_enter_blocking_section();
  g_main_context_get_poll_func(gc)(pollfds, nfds, timeout);
  caml_leave_blocking_section();

  /* Let glib parse the result. */
  g_main_context_check(gc, max_priority, pollfds, nfds);

  /* Release the context. */
  g_main_context_release(gc);

  free(pollfds);

  return Val_unit;
}
static void
soup_proxy_resolver_gnome_init (SoupProxyResolverGNOME *resolver_gnome)
{
	GMainContext *default_context;

	G_LOCK (resolver_gnome);
	if (!gconf_client) {
		/* GConf is not thread-safe, and we might be running
		 * in some random thread right now while other
		 * GConf-related activity is going on in the main
		 * thread. To prevent badness, we try to claim the
		 * default GMainContext; if we succeed, then either
		 * we're in the thread of the default GMainContext, or
		 * else there isn't currently any thread running the
		 * default GMainContext (meaning either the main loop
		 * hasn't been started yet, or else there is no main
		 * loop). Either way, it's safe to use GConf.
		 *
		 * If we can't manage to acquire the default
		 * GMainContext, then that means another thread
		 * already has it, so we use g_idle_add() to ask that
		 * thread to do the GConf initialization, and wait
		 * for that thread to finish.
		 */
		default_context = g_main_context_default ();
		if (g_main_context_acquire (default_context)) {
			init_gconf (NULL);
			g_main_context_release (default_context);
		} else {
			SoupProxyResolverGNOMEInitData id;

			id.lock = g_mutex_new ();
			id.cond = g_cond_new ();

			g_mutex_lock (id.lock);
			g_idle_add (init_gconf, &id);
			g_cond_wait (id.cond, id.lock);
			g_mutex_unlock (id.lock);

			g_cond_free (id.cond);
			g_mutex_free (id.lock);
		}
	}
	G_UNLOCK(resolver_gnome);
}
Beispiel #6
0
/** @internal Run the main loop.
 *
 * The main loop runs until su_source_break() is called from a callback.
 *
 * @param self     pointer to port object
 * */
static
void su_source_run(su_port_t *self)
{
  GMainContext *gmc;
  GMainLoop *gml;

  enter;

  gmc = g_source_get_context(self->sup_source);
  if (gmc && g_main_context_acquire(gmc)) {
    gml = g_main_loop_new(gmc, TRUE);
    self->sup_main_loop = gml;
    g_main_loop_run(gml);
    g_main_loop_unref(gml);
    self->sup_main_loop = NULL;
    g_main_context_release(gmc);
  }
}
Beispiel #7
0
void
grustna_main_loop_run_thread_local (GMainLoop *loop)
{
  GMainContext *context;
  gboolean context_acquired;

  context = g_main_loop_get_context (loop);

  context_acquired = g_main_context_acquire (context);
  while (!context_acquired)
    context_acquired = g_main_context_wait (context,
                                            &rust_context_released_cond,
                                            &rust_context_mutex);

  g_main_context_push_thread_default (context);
  g_main_loop_run (loop);
  g_main_context_pop_thread_default (context);

  g_main_context_release (context);
}
Beispiel #8
0
/** Set up the main context the session will be executing in.
 *
 * Must be called just before the session starts, by the thread which
 * will execute the session main loop. Once acquired, the main context
 * pointer is immutable for the duration of the session run.
 */
static int set_main_context(struct sr_session *session)
{
	GMainContext *def_context;

	/* May happen if sr_session_start() is called again after
	 * sr_session_run(), but the session hasn't been stopped yet.
	 */
	if (session->main_loop) {
		sr_err("Cannot set main context; main loop already created.");
		return SR_ERR;
	}

	g_mutex_lock(&session->main_mutex);

	def_context = g_main_context_get_thread_default();

	if (!def_context)
		def_context = g_main_context_default();
	/*
	 * Try to use an existing main context if possible, but only if we
	 * can make it owned by the current thread. Otherwise, create our
	 * own main context so that event source callbacks can execute in
	 * the session thread.
	 */
	if (g_main_context_acquire(def_context)) {
		g_main_context_release(def_context);

		sr_dbg("Using thread-default main context.");

		session->main_context = def_context;
		session->main_context_is_default = TRUE;
	} else {
		sr_dbg("Creating our own main context.");

		session->main_context = g_main_context_new();
		session->main_context_is_default = FALSE;
	}
	g_mutex_unlock(&session->main_mutex);

	return SR_OK;
}
Beispiel #9
0
/** @internal Block until wait object is signaled or timeout.
 *
 * This function waits for wait objects and the timers associated with
 * the root object.  When any wait object is signaled or timer is
 * expired, it invokes the callbacks.
 *
 *   This function returns when a callback has been invoked or @c tout
 *   milliseconds is elapsed.
 *
 * @param self     pointer to port
 * @param tout     timeout in milliseconds
 *
 * @Return
 *   Milliseconds to the next invocation of timer, or @c SU_WAIT_FOREVER if
 *   there are no active timers.
 */
su_duration_t su_source_step(su_port_t *self, su_duration_t tout)
{
  GMainContext *gmc;

  enter;

  gmc = g_source_get_context(self->sup_source);

  if (gmc && g_main_context_acquire(gmc)) {
    GPollFD *fds = NULL;
    gint fds_size = 0;
    gint fds_wait;
    gint priority = G_MAXINT;
    gint src_tout = -1;

    g_main_context_prepare(gmc, &priority);

    fds_wait = g_main_context_query(gmc, priority, &src_tout, NULL, 0);
    while (fds_wait > fds_size) {
      fds = g_alloca(fds_wait * sizeof(fds[0]));
      fds_size = fds_wait;
      fds_wait = g_main_context_query(gmc, priority, &src_tout, fds, fds_size);
    }

    if (src_tout >= 0 && tout > (su_duration_t)src_tout)
      tout = src_tout;

    su_wait((su_wait_t *)fds, fds_wait, tout);

    g_main_context_check(gmc, priority, fds, fds_wait);

    g_main_context_dispatch(gmc);

    g_main_context_release(gmc);
  }

  return 0;
}
Beispiel #10
0
/** Set up the main context the session will be executing in.
 *
 * Must be called just before the session starts, by the thread which
 * will execute the session main loop. Once acquired, the main context
 * pointer is immutable for the duration of the session run.
 */
static int set_main_context(struct sr_session *session)
{
	GMainContext *main_context;

	g_mutex_lock(&session->main_mutex);

	/* May happen if sr_session_start() is called a second time
	 * while the session is still running.
	 */
	if (session->main_context) {
		sr_err("Main context already set.");

		g_mutex_unlock(&session->main_mutex);
		return SR_ERR;
	}
	main_context = g_main_context_ref_thread_default();
	/*
	 * Try to use an existing main context if possible, but only if we
	 * can make it owned by the current thread. Otherwise, create our
	 * own main context so that event source callbacks can execute in
	 * the session thread.
	 */
	if (g_main_context_acquire(main_context)) {
		g_main_context_release(main_context);

		sr_dbg("Using thread-default main context.");
	} else {
		g_main_context_unref(main_context);

		sr_dbg("Creating our own main context.");
		main_context = g_main_context_new();
	}
	session->main_context = main_context;

	g_mutex_unlock(&session->main_mutex);

	return SR_OK;
}
Beispiel #11
0
static int os_host_main_loop_wait(int64_t timeout)
{
    GMainContext *context = g_main_context_default();
    int ret;

    g_main_context_acquire(context);

    glib_pollfds_fill(&timeout);

    qemu_mutex_unlock_iothread();
    replay_mutex_unlock();

    ret = qemu_poll_ns((GPollFD *)gpollfds->data, gpollfds->len, timeout);

    replay_mutex_lock();
    qemu_mutex_lock_iothread();

    glib_pollfds_poll();

    g_main_context_release(context);

    return ret;
}
Beispiel #12
0
static mst_Boolean
main_loop_poll (int ms)
{
  GMainContext *context;
  int timeout;

  if (!loop || !g_main_loop_is_running (loop))
    return FALSE;

  if (!fds)
    {
      fds = g_new (GPollFD, 20);
      allocated_nfds = 20;
    }

  context = g_main_loop_get_context (loop);
  if (!g_main_context_acquire (context))
    abort ();

  timeout = -1;
  g_main_context_prepare (context, &maxprio);
  while ((nfds = g_main_context_query (context, maxprio,
                                       &timeout, fds, allocated_nfds))
         > allocated_nfds)
    {
      g_free (fds);
      fds = g_new (GPollFD, nfds);
      allocated_nfds = nfds;
    }

  if (ms != -1 && (timeout == -1 || timeout > ms))
    timeout = ms;

  g_main_context_release (context);
  g_poll (fds, nfds, timeout);
  return g_main_context_check (context, maxprio, fds, nfds);
}
Beispiel #13
0
static gpointer
loop_thread_init (gpointer data)
{
  KmsLoop *self = KMS_LOOP (data);
  GMainLoop *loop;
  GMainContext *context;

  KMS_LOOP_LOCK (self);
  self->priv->context = g_main_context_new ();
  context = g_main_context_ref (self->priv->context);
  self->priv->loop = g_main_loop_new (context, FALSE);
  loop = g_main_loop_ref (self->priv->loop);
  KMS_LOOP_UNLOCK (self);

  /* unlock main process because context is already initialized */
  g_mutex_lock (&self->priv->mutex);
  self->priv->initialized = TRUE;
  g_cond_signal (&self->priv->cond);
  g_mutex_unlock (&self->priv->mutex);

  if (!g_main_context_acquire (context)) {
    GST_ERROR ("Can not acquire context");
    goto end;
  }

  GST_DEBUG ("Running main loop");
  g_main_loop_run (loop);
  g_main_context_release (context);

end:
  GST_DEBUG ("Thread finished");
  g_main_loop_unref (loop);
  g_main_context_unref (context);

  return NULL;
}
Beispiel #14
0
static void
call_minder (gpointer data, G_GNUC_UNUSED gpointer pool_data)
{
  RustCallData *call_data = data;
  GMainContext *context = call_data->context;
  RustCallStatus status = RUST_CALL_PENDING;
  gint64 end_time;

  end_time = g_get_monotonic_time() + CALL_MINDER_TIMEOUT;

  do
    {
      if (g_main_context_acquire (context))
        {
          status = call_data->status;  /* No locking needed */

          if (status == RUST_CALL_PENDING)
            {
              /* Nothing has been there to drive our call, let's do it now */

              g_source_destroy (call_data->source);

              g_main_context_push_thread_default (context);

              call_data->func (call_data->param, context);

              g_main_context_pop_thread_default (context);

              g_mutex_lock (&call_mutex);
              status = RUST_CALL_RETURNED;
              call_data->status = status;
              g_cond_signal (&call_data->return_cond);
              g_mutex_unlock (&call_mutex);
            }

          g_main_context_release (context);

          /* Unblock a potentially waiting
           * grustna_main_loop_run_thread_local() */
          g_cond_broadcast (&rust_context_released_cond);
        }
      else
        {
          gint64 wakeup_time;

          g_mutex_lock (&call_mutex);

          wakeup_time = g_get_monotonic_time () + call_data->minder_backoff;
          if (wakeup_time > end_time)
            {
              g_critical ("call timed out waiting on context %p", call_data->context);
              status = RUST_CALL_TIMED_OUT;
              call_data->status = status;
              g_cond_signal (&call_data->return_cond);
            }
          else
            {
              if (!g_cond_wait_until (&call_data->return_cond, &call_mutex,
                                         wakeup_time))
                call_data->minder_backoff *= 2;
              status = call_data->status;
            }

          g_mutex_unlock (&call_mutex);
        }
    }
  while (status == RUST_CALL_PENDING);

  call_data_unref (call_data);
}
Beispiel #15
0
static int os_host_main_loop_wait(int64_t timeout)
{
    GMainContext *context = g_main_context_default();
    GPollFD poll_fds[1024 * 2]; /* this is probably overkill */
    int select_ret = 0;
    int g_poll_ret, ret, i, n_poll_fds;
    PollingEntry *pe;
    WaitObjects *w = &wait_objects;
    gint poll_timeout;
    int64_t poll_timeout_ns;
    static struct timeval tv0;
    fd_set rfds, wfds, xfds;
    int nfds;

    g_main_context_acquire(context);

    /* XXX: need to suppress polling by better using win32 events */
    ret = 0;
    for (pe = first_polling_entry; pe != NULL; pe = pe->next) {
        ret |= pe->func(pe->opaque);
    }
    if (ret != 0) {
        g_main_context_release(context);
        return ret;
    }

    FD_ZERO(&rfds);
    FD_ZERO(&wfds);
    FD_ZERO(&xfds);
    nfds = pollfds_fill(gpollfds, &rfds, &wfds, &xfds);
    if (nfds >= 0) {
        select_ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv0);
        if (select_ret != 0) {
            timeout = 0;
        }
        if (select_ret > 0) {
            pollfds_poll(gpollfds, nfds, &rfds, &wfds, &xfds);
        }
    }

    g_main_context_prepare(context, &max_priority);
    n_poll_fds = g_main_context_query(context, max_priority, &poll_timeout,
                                      poll_fds, ARRAY_SIZE(poll_fds));
    g_assert(n_poll_fds <= ARRAY_SIZE(poll_fds));

    for (i = 0; i < w->num; i++) {
        poll_fds[n_poll_fds + i].fd = (DWORD_PTR)w->events[i];
        poll_fds[n_poll_fds + i].events = G_IO_IN;
    }

    if (poll_timeout < 0) {
        poll_timeout_ns = -1;
    } else {
        poll_timeout_ns = (int64_t)poll_timeout * (int64_t)SCALE_MS;
    }

    poll_timeout_ns = qemu_soonest_timeout(poll_timeout_ns, timeout);

    qemu_mutex_unlock_iothread();

    replay_mutex_unlock();

    g_poll_ret = qemu_poll_ns(poll_fds, n_poll_fds + w->num, poll_timeout_ns);

    replay_mutex_lock();

    qemu_mutex_lock_iothread();
    if (g_poll_ret > 0) {
        for (i = 0; i < w->num; i++) {
            w->revents[i] = poll_fds[n_poll_fds + i].revents;
        }
        for (i = 0; i < w->num; i++) {
            if (w->revents[i] && w->func[i]) {
                w->func[i](w->opaque[i]);
            }
        }
    }

    if (g_main_context_check(context, max_priority, poll_fds, n_poll_fds)) {
        g_main_context_dispatch(context);
    }

    g_main_context_release(context);

    return select_ret || g_poll_ret;
}
/**
 * g_tls_interaction_invoke_ask_password:
 * @interaction: a #GTlsInteraction object
 * @password: a #GTlsPassword object
 * @cancellable: an optional #GCancellable cancellation object
 * @error: an optional location to place an error on failure
 *
 * Invoke the interaction to ask the user for a password. It invokes this
 * interaction in the main loop, specifically the #GMainContext returned by
 * g_main_context_get_thread_default() when the interaction is created. This
 * is called by called by #GTlsConnection or #GTlsDatabase to ask the user
 * for a password.
 *
 * Derived subclasses usually implement a password prompt, although they may
 * also choose to provide a password from elsewhere. The @password value will
 * be filled in and then @callback will be called. Alternatively the user may
 * abort this password request, which will usually abort the TLS connection.
 *
 * The implementation can either be a synchronous (eg: modal dialog) or an
 * asynchronous one (eg: modeless dialog). This function will take care of
 * calling which ever one correctly.
 *
 * If the interaction is cancelled by the cancellation object, or by the
 * user then %G_TLS_INTERACTION_FAILED will be returned with an error that
 * contains a %G_IO_ERROR_CANCELLED error code. Certain implementations may
 * not support immediate cancellation.
 *
 * Returns: The status of the ask password interaction.
 *
 * Since: 2.30
 */
GTlsInteractionResult
g_tls_interaction_invoke_ask_password (GTlsInteraction    *interaction,
                                       GTlsPassword       *password,
                                       GCancellable       *cancellable,
                                       GError            **error)
{
  GTlsInteractionResult result;
  InvokeClosure *closure;
  GTlsInteractionClass *klass;

  g_return_val_if_fail (G_IS_TLS_INTERACTION (interaction), G_TLS_INTERACTION_UNHANDLED);
  g_return_val_if_fail (G_IS_TLS_PASSWORD (password), G_TLS_INTERACTION_UNHANDLED);
  g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), G_TLS_INTERACTION_UNHANDLED);

  closure = invoke_closure_new (interaction, G_OBJECT (password), cancellable);

  klass = G_TLS_INTERACTION_GET_CLASS (interaction);
  if (klass->ask_password)
    {
      g_main_context_invoke (interaction->priv->context,
                             on_invoke_ask_password_sync, closure);
      result = invoke_closure_wait_and_free (closure, error);
    }
  else if (klass->ask_password_async)
    {
      g_return_val_if_fail (klass->ask_password_finish, G_TLS_INTERACTION_UNHANDLED);
      g_main_context_invoke (interaction->priv->context,
                             on_invoke_ask_password_async_as_sync, closure);

      /*
       * Handle the case where we've been called from within the main context
       * or in the case where the main context is not running. This approximates
       * the behavior of a modal dialog.
       */
      if (g_main_context_acquire (interaction->priv->context))
        {
          while (!closure->complete)
            {
              g_mutex_unlock (closure->mutex);
              g_main_context_iteration (interaction->priv->context, TRUE);
              g_mutex_lock (closure->mutex);
            }
          g_main_context_release (interaction->priv->context);

          if (closure->error)
            {
              g_propagate_error (error, closure->error);
              closure->error = NULL;
            }

          result = closure->result;
          invoke_closure_free (closure);
        }

      /*
       * Handle the case where we're in a different thread than the main
       * context and a main loop is running.
       */
      else
        {
          result = invoke_closure_wait_and_free (closure, error);
        }
    }
  else
    {
      result = G_TLS_INTERACTION_UNHANDLED;
      invoke_closure_free (closure);
    }

  return result;
}
Beispiel #17
0
static void glib_release(glib_glue_t *glue)
{
    g_main_context_release(glue->mc);
}
Beispiel #18
0
int
xg_select (int fds_lim, fd_set *rfds, fd_set *wfds, fd_set *efds,
	   struct timespec *timeout, sigset_t *sigmask)
{
  fd_set all_rfds, all_wfds;
  struct timespec tmo;
  struct timespec *tmop = timeout;

  GMainContext *context;
  bool have_wfds = wfds != NULL;
  GPollFD gfds_buf[128];
  GPollFD *gfds = gfds_buf;
  int gfds_size = ARRAYELTS (gfds_buf);
  int n_gfds, retval = 0, our_fds = 0, max_fds = fds_lim - 1;
  bool context_acquired = false;
  int i, nfds, tmo_in_millisec, must_free = 0;
  bool need_to_dispatch;

  context = g_main_context_default ();
  context_acquired = g_main_context_acquire (context);
  /* FIXME: If we couldn't acquire the context, we just silently proceed
     because this function handles more than just glib file descriptors.
     Note that, as implemented, this failure is completely silent: there is
     no feedback to the caller.  */

  if (rfds) all_rfds = *rfds;
  else FD_ZERO (&all_rfds);
  if (wfds) all_wfds = *wfds;
  else FD_ZERO (&all_wfds);

  n_gfds = (context_acquired
	    ? g_main_context_query (context, G_PRIORITY_LOW, &tmo_in_millisec,
				    gfds, gfds_size)
	    : -1);

  if (gfds_size < n_gfds)
    {
      /* Avoid using SAFE_NALLOCA, as that implicitly refers to the
	 current thread.  Using xnmalloc avoids thread-switching
	 problems here.  */
      gfds = xnmalloc (n_gfds, sizeof *gfds);
      must_free = 1;
      gfds_size = n_gfds;
      n_gfds = g_main_context_query (context, G_PRIORITY_LOW, &tmo_in_millisec,
				     gfds, gfds_size);
    }

  for (i = 0; i < n_gfds; ++i)
    {
      if (gfds[i].events & G_IO_IN)
        {
          FD_SET (gfds[i].fd, &all_rfds);
          if (gfds[i].fd > max_fds) max_fds = gfds[i].fd;
        }
      if (gfds[i].events & G_IO_OUT)
        {
          FD_SET (gfds[i].fd, &all_wfds);
          if (gfds[i].fd > max_fds) max_fds = gfds[i].fd;
          have_wfds = true;
        }
    }

  if (must_free)
    xfree (gfds);

  if (n_gfds >= 0 && tmo_in_millisec >= 0)
    {
      tmo = make_timespec (tmo_in_millisec / 1000,
			   1000 * 1000 * (tmo_in_millisec % 1000));
      if (!timeout || timespec_cmp (tmo, *timeout) < 0)
	tmop = &tmo;
    }

  fds_lim = max_fds + 1;
  nfds = thread_select (pselect, fds_lim,
			&all_rfds, have_wfds ? &all_wfds : NULL, efds,
			tmop, sigmask);
  if (nfds < 0)
    retval = nfds;
  else if (nfds > 0)
    {
      for (i = 0; i < fds_lim; ++i)
        {
          if (FD_ISSET (i, &all_rfds))
            {
              if (rfds && FD_ISSET (i, rfds)) ++retval;
              else ++our_fds;
            }
          else if (rfds)
            FD_CLR (i, rfds);

          if (have_wfds && FD_ISSET (i, &all_wfds))
            {
              if (wfds && FD_ISSET (i, wfds)) ++retval;
              else ++our_fds;
            }
          else if (wfds)
            FD_CLR (i, wfds);

          if (efds && FD_ISSET (i, efds))
            ++retval;
        }
    }

  /* If Gtk+ is in use eventually gtk_main_iteration will be called,
     unless retval is zero.  */
#ifdef USE_GTK
  need_to_dispatch = retval == 0;
#else
  need_to_dispatch = true;
#endif
  if (need_to_dispatch && context_acquired)
    {
      int pselect_errno = errno;
      /* Prevent g_main_dispatch recursion, that would occur without
         block_input wrapper, because event handlers call
         unblock_input.  Event loop recursion was causing Bug#15801.  */
      block_input ();
      while (g_main_context_pending (context))
        g_main_context_dispatch (context);
      unblock_input ();
      errno = pselect_errno;
    }

  if (context_acquired)
    g_main_context_release (context);

  /* To not have to recalculate timeout, return like this.  */
  if ((our_fds > 0 || (nfds == 0 && tmop == &tmo)) && (retval == 0))
    {
      retval = -1;
      errno = EINTR;
    }

  return retval;
}
Beispiel #19
0
/**
 * gcr_importer_import:
 * @importer: the importer
 * @cancellable: a #GCancellable, or %NULL
 * @error: the location to place an error on failure, or %NULL
 *
 * Import the queued items in the importer. This call will block
 * until the operation completes.
 *
 * Returns: whether the items were imported successfully or not
 */
gboolean
gcr_importer_import (GcrImporter *importer,
                     GCancellable *cancellable,
                     GError **error)
{
	gboolean result;
	ImportClosure *closure;
	GcrImporterIface *iface;

	g_return_val_if_fail (GCR_IS_IMPORTER (importer), FALSE);
	g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);

	iface = GCR_IMPORTER_GET_INTERFACE (importer);
	if (iface->import_sync)
		return (iface->import_sync) (importer, cancellable, error);

	g_return_val_if_fail (iface->import_async != NULL, FALSE);
	g_return_val_if_fail (iface->import_finish != NULL, FALSE);

	closure = g_new0 (ImportClosure, 1);
	closure->cond = g_new (GCond, 1);
	g_cond_init (closure->cond);
	closure->mutex = g_new (GMutex, 1);
	g_mutex_init (closure->mutex);
	closure->context = g_main_context_get_thread_default ();
	g_mutex_lock (closure->mutex);

	(iface->import_async) (importer, cancellable, on_import_async_complete, closure);

	/*
	 * Handle the case where we've been called from within the main context
	 * or in the case where the main context is not running. This approximates
	 * the behavior of a modal dialog.
	 */
	if (g_main_context_acquire (closure->context)) {
		while (!closure->complete) {
			g_mutex_unlock (closure->mutex);
			g_main_context_iteration (closure->context, TRUE);
			g_mutex_lock (closure->mutex);
		}

		g_main_context_release (closure->context);

	/*
	 * Handle the case where we're in a different thread than the main
	 * context and a main loop is running.
	 */
	} else {
		while (!closure->complete)
			g_cond_wait (closure->cond, closure->mutex);
	}

	g_mutex_unlock (closure->mutex);

	result = (closure->error == NULL);
	if (closure->error)
		g_propagate_error (error, closure->error);

	g_cond_clear (closure->cond);
	g_free (closure->cond);
	g_mutex_clear (closure->mutex);
	g_free (closure->mutex);
	g_free (closure);

	return result;
}
Beispiel #20
0
gboolean
grustna_call (RustFunc func, gpointer data, GMainContext *context)
{
  gboolean thread_default_context = FALSE;

  g_return_val_if_fail (func != NULL, FALSE);

  if (context == NULL)
    {
      context = g_main_context_get_thread_default ();
      if (context == NULL)
        context = get_rust_thread_context ();
      else
        thread_default_context = TRUE;
    }

  /* This code is based on g_main_context_invoke_full() */

  if (g_main_context_is_owner (context))
    {
      /* Fastest path: the caller is in the same thread where some code
       * is supposedly driving the loop context affine to this call. */
      func (data, context);
      return TRUE;
    }

  if (g_main_context_acquire (context))
    {
      /* Here, we get to exclusively use the desired loop context
       * that is not (yet) driven by an event loop.
       * This is perfectly OK for non-async functions on objects affine
       * to this context, and matches the behavior of GIO-style async calls
       * that rely on the thread-default context to be eventually driven
       * in order to complete. */

      if (!thread_default_context)
        g_main_context_push_thread_default (context);

      func (data, context);

      if (!thread_default_context)
        g_main_context_pop_thread_default (context);

      g_main_context_release (context);

      /* Unblock a potentially waiting
       * grustna_main_loop_run_thread_local() */
      g_cond_broadcast (&rust_context_released_cond);

      return TRUE;
    }
  else
    {
      /* Shunt the call to the loop thread
       * and wait for it to complete. */

      RustCallData *call_data;
      RustCallStatus status;
      GSource *idle;

      call_data = g_slice_new0 (RustCallData);
      call_data->func = func;
      call_data->param = data;
      call_data->context = g_main_context_ref (context);
      call_data->ref_count = 3;
      call_data->minder_backoff = 1 * G_TIME_SPAN_MILLISECOND;
      call_data->status = RUST_CALL_PENDING;

      idle = g_idle_source_new ();
      g_source_set_priority (idle, G_PRIORITY_DEFAULT);
      g_source_set_callback (idle, loop_callback, call_data, NULL);
      g_source_attach (idle, context);
      call_data->source = idle;

      g_cond_init (&call_data->return_cond);

      add_call_minder (call_data);

      g_mutex_lock (&call_mutex);
      while ((status = call_data->status) == RUST_CALL_PENDING)
        g_cond_wait (&call_data->return_cond, &call_mutex);
      g_mutex_unlock (&call_mutex);

      call_data_unref (call_data);

      return status == RUST_CALL_RETURNED;
    }
}