Пользователям GLib разрешено запускать несколько экземпляров GMainLoop
одновременно в нескольких потоках, причем каждый поток запускает свой собственный экземпляр? Я нашел ответы «да» и «нет» повсюду. Я понимаю, что этот вопрос задавался ранее на этом форуме (December 2011).Выполнение нескольких одновременных GMainLoops
Тем не менее, я могу запустить два экземпляра GMainLoop
в то же время без видимой проблемы. Мой тестовый код очень прост:
- Создать
GMainLoop
вmain()
- Создание источника тайм-аута для контекста по умолчанию и основной цикл, используя
g_timeout_add
- Создать GThread в основной()
- Запускаем основной цикл использования
g_main_loop_run
- [нИТИ кОНТЕКСТ]: Создать контекст, используя
g_main_context_new
- [рЕЗЬБЫ кОНТЕКСТ]: Установите этот контекст как нить опр Олт использованием
g_main_context_push_thread_default
- [НИТИ КОНТЕКСТ]: Создать петлю с помощью
g_main_loop_new
и придать ему новый контекст - [РЕЗЬБЫ КОНТЕКСТ]: Создание источника тайм-аута, и прикрепить его к новому контексту через
g_source_attach
. - [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);
}
Я только что нашел [это] (http://stackoverflow.com/questions/11286284/g-timeout-add-inside-a-gthread), который, похоже, согласен с тем, что это приемлемое использование API GLib. Итак, еще одна запись в столбце «да, это штраф», я думаю. – pkurby