добавить обратный вызов для отдельного g_main_loop

Я немного не понимаю, как работает GMainLoop. Главное - API, который добавляет некоторые обратные вызовы в g_main_loop (например, g_timeout_add_seconds()), не принимает указатель на какой цикл вы хотите добавить этот обратный вызов.

Похоже, вы добавляете обратные вызовы для всех g_main_loop экземпляров. Даже если вы еще не создали. Простой пример для этого:

#include <glib.h>

gboolean callback(gpointer data)
{
  static guint16 i=0; 
  g_print("Iter=%"G_GUINT16_FORMAT"\n",i++);
  if(i%5==0){
    g_print("try to stop loop1\n");
    g_main_loop_quit((GMainLoop*)data);
  }
  return TRUE;
}

int main()
{
  GMainLoop* loop1 = NULL;
  GMainLoop* loop2 = NULL;
  loop1 = g_main_loop_new (NULL, FALSE);

  g_timeout_add_seconds(1, callback,loop1);

  loop2 = g_main_loop_new (NULL, FALSE);
  g_print("run loop1\n");
  g_main_loop_run(loop1);
  g_free(loop1);
  g_print("run loop2\n");
  g_main_loop_run(loop2);
  g_free(loop2);
  return 0;
}

Результат:

run loop1
Iter=0
Iter=1
Iter=2
Iter=3
Iter=4
try to stop loop1
run loop2
Iter=5
Iter=6
Iter=7
Iter=8
Iter=9
try to stop loop1
Segmentation fault (core dumped)

Можно ли добавить callback() к loop1 и не добавлять к loop2?


person Stepan Loginov    schedule 16.10.2014    source источник


Ответы (1)


Краткий обзор документации для g_idle_add() , g_idle_add_full(), g_timeout_add() или g_timeout_add_full() сообщит вам:

Это внутренне создает источник основного цикла, используя g_timeout_source_new()< /a> и присоединяет его к контексту основного цикла, используя g_source_attach(). Вы можете выполнить эти шаги вручную, если вам нужен больший контроль.

Обратите внимание, что он говорит, что прикрепляет источник к контексту основного цикла — т.е., GMainContext, а не GMainLoop. Когда вы создаете экземпляры GMainLoop, вы передаете NULL в качестве первого аргумента. Согласно the g_main_loop_new() documentation, это аргумент

a GMainContext (если NULL, будет использоваться контекст по умолчанию ).

Итак, вы создаете два основных цикла, оба используют один и тот же контекст (который является контекстом по умолчанию).

Чтобы получить результат, который, я думаю, вы ожидаете, вы должны сделать что-то вроде:

#include <glib.h>

gboolean callback(gpointer data)
{
  static guint16 i=0; 
  g_print("Iter=%"G_GUINT16_FORMAT"\n",i++);
  if(i%5==0){
    g_print("try to stop loop1\n", data);
    g_main_loop_quit((GMainLoop*)data);
  }
  return TRUE;
}

int main()
{
  GMainContext* con1 = NULL;
  GMainContext* con2 = NULL;
  GMainLoop* loop1 = NULL;
  GMainLoop* loop2 = NULL;
  GSource* source1 = NULL;

  con1 = g_main_context_new ();
  con2 = g_main_context_new ();

  loop1 = g_main_loop_new (con1, FALSE);
  loop2 = g_main_loop_new (con2, FALSE);

  source1 = g_timeout_source_new_seconds (1);
  g_source_set_callback (source1, callback, loop1, NULL);
  g_source_attach (source1, con1);

  // We don't need the GMainContext anymore—the loop has an internal
  // reference so we'll drop ours.
  g_main_context_unref (con1);
  con1 = NULL;

  // Ditto for the GSource
  g_source_unref (source1);
  source1 = NULL;

  g_main_context_unref (con2);
  con2 = NULL;

  g_print("run loop1\n");
  g_main_loop_run(loop1);
  // Use g_main_loop_unref, not g_free
  g_main_loop_unref(loop1);
  loop1 = NULL;

  g_print("run loop2\n");
  // Note that there is no longer a callback attached here, so it will
  // run forever.
  g_main_loop_run(loop2);
  g_main_loop_unref(loop2);
  loop2 = NULL;

  return 0;
}
person nemequ    schedule 16.10.2014