2014-01-31 2 views
7

Пользователям GLib разрешено запускать несколько экземпляров GMainLoop одновременно в нескольких потоках, причем каждый поток запускает свой собственный экземпляр? Я нашел ответы «да» и «нет» повсюду. Я понимаю, что этот вопрос задавался ранее на этом форуме (December 2011).Выполнение нескольких одновременных GMainLoops

Тем не менее, я могу запустить два экземпляра GMainLoop в то же время без видимой проблемы. Мой тестовый код очень прост:

  1. Создать GMainLoop в main()
  2. Создание источника тайм-аута для контекста по умолчанию и основной цикл, используя g_timeout_add
  3. Создать GThread в основной()
  4. Запускаем основной цикл использования g_main_loop_run
  5. [нИТИ кОНТЕКСТ]: Создать контекст, используя g_main_context_new
  6. [рЕЗЬБЫ кОНТЕКСТ]: Установите этот контекст как нить опр Олт использованием g_main_context_push_thread_default
  7. [НИТИ КОНТЕКСТ]: Создать петлю с помощью g_main_loop_new и придать ему новый контекст
  8. [РЕЗЬБЫ КОНТЕКСТ]: Создание источника тайм-аута, и прикрепить его к новому контексту через g_source_attach.
  9. [THREAD_CONTEXT]: Есть нить вызвать g_main_loop_run

Делая это, я вижу, как экземпляры GMainLoop работают нормально. Вызов обратного вызова таймаута вызывается правильно, а затем вызывает g_main_loop_quit, как и следовало ожидать.

Таким образом, похоже, что не так много экземпляров, которые одновременно работают с несколькими GMainLoop экземплярами. Но, возможно, я просто не использовал API достаточно, чтобы полностью понять ситуацию. Есть ли окончательный ответ на этот вопрос?

Кроме того, вот фактический тестовый код, если кто-нибудь захочет выглядеть:

#define THREAD_TIMEOUTS (20) 
#define MAIN_TIMEOUS (1) 

typedef struct timeout_struct 
{ 
    int i; 
    int max; 
    GMainLoop *loop; 
    char *name; 

} TIMEOUT_STRUCT; 

gboolean timeout_callback(gpointer data) 
{ 
    TIMEOUT_STRUCT *psTimeout = (TIMEOUT_STRUCT *)data; 

    psTimeout->i++; 

    if (psTimeout->i == psTimeout->max) 
    { 
     if (psTimeout->max == THREAD_TIMEOUTS) 
     { 
      g_main_loop_quit((GMainLoop*)psTimeout->loop); 
     } 
     return FALSE; 
    } 

    return TRUE; 
} 
void* thread_function(void *data) 
{ 
    GMainContext *ps_context; 
    GMainLoop *ps_loop; 
    GSource *ps_timer; 
    TIMEOUT_STRUCT sTimeout; 

    ps_context = g_main_context_new(); 
    g_main_context_push_thread_default(ps_context); 

    ps_loop = g_main_loop_new(ps_context, FALSE); 

    sTimeout.i = 0; 
    sTimeout.max = THREAD_TIMEOUTS; 
    sTimeout.loop = ps_loop; 
    sTimeout.name = "thread"; 
    ps_timer = g_timeout_source_new_seconds(1); 
    g_source_set_callback(ps_timer, timeout_callback, &sTimeout, NULL); 
    g_source_attach(ps_timer, ps_context); 

    g_main_loop_run(ps_loop); 

    g_main_loop_quit((GMainLoop*)data); 

    return NULL; 

} 
/* 
* This main boots a thread, then starts up a GMainLoop. Then the thread runs 
* a GMainLoop. The thread sets a timer that fires ten times and the main sets a 
* timer that fires two times. The thread quits and 
* and then the other main l 
* 
* 
* */ 
int main() 
{ 
    GThread *ps_thread; 
    GMainLoop *loop; 
    TIMEOUT_STRUCT sTimeout; 

    loop = g_main_loop_new (NULL , FALSE); 

    sTimeout.i = 0; 
    sTimeout.max = MAIN_TIMEOUS; 
    sTimeout.loop = loop; 
    sTimeout.name = "main"; 

    // add source to default context 
    g_timeout_add (1 , timeout_callback, &sTimeout); 

    ps_thread = g_thread_new("thread", thread_function, loop); 

    g_main_loop_run (loop); 
    g_main_loop_unref(loop); 
} 
+0

Я только что нашел [это] (http://stackoverflow.com/questions/11286284/g-timeout-add-inside-a-gthread), который, похоже, согласен с тем, что это приемлемое использование API GLib. Итак, еще одна запись в столбце «да, это штраф», я думаю. – pkurby

ответ

9

Книга «Основы GTK + развития» заявляет об этом:

краснобайствующим основной цикл реализуется в виде ряда структур, которые позволяют запускать несколько экземпляров одновременно.

Итак, учитывая это, мой тестовый код и link Я опубликовал в комментарии выше, мы имеем окончательный ответ на этот вопрос.

А именно: несколько потоков могут иметь свой собственный GMainContext & GMainLoop и могут самостоятельно управлять этими циклами одновременно.

Смежные вопросы