一个线程中的GLib GMainContext?
我搜索了堆栈溢出来找到与我的问题相关的答案。 但我没有找到任何答案。
我有一个主线程(我的main()函数),它启动一个线程。 新线程运行GMainLoop。 在我的主要function中,我通过在某些文件描述符上调用g_io_watch
来继续添加源代码。 但是,如果发送了事件,我会收到垃圾数据。
以下是我正在尝试的代码的一小部分:
GMainLoop *loop; gpointer event_loop_thread(gpointer arg) { g_main_loop_run(loop); g_main_loop_unref(loop); return NULL; } int init() { loop = g_main_loop_new(NULL, FALSE); g_thread_new(NULL, event_loop_thread, NULL); return 0; } gboolean __hci_service(GIOChannel *source, GIOCondition condition, gpointer data) { // Doing something return FALSE; } int main() { init(); int _adapter_id = hci_devid("hci0"); int hci_dev = hci_open_dev(_adapter_id); GIOChannel *p_hci_io = g_io_channel_unix_new(dev_id); GIOCondition cond = (GIOCondition)(G_IO_IN); g_io_add_watch(p_hci_io, cond, __hci_service, NULL); while (true); // I will close file descriptor return 0; }
但是,如果我尝试此代码,那么一切都按预期工作:
GMainLoop *loop; gpointer event_loop_thread(gpointer arg) { g_main_loop_run(loop); g_main_loop_unref(loop); return NULL; } int init() { loop = g_main_loop_new(NULL, FALSE); g_thread_new(NULL, event_loop_thread, NULL); return 0; } gboolean __hci_service(GIOChannel *source, GIOCondition condition, gpointer data) { // Doing something return FALSE; } int main() { // init(); int _adapter_id = hci_devid("hci0"); int hci_dev = hci_open_dev(_adapter_id); GIOChannel *p_hci_io = g_io_channel_unix_new(dev_id); GIOCondition cond = (GIOCondition)(G_IO_IN); g_io_add_watch(p_hci_io, cond, __hci_service, NULL); loop = g_main_loop_new(NULL, FALSE); g_main_loop_run(loop); g_main_loop_unref(loop); while (true); // I will close file descriptor return 0; }
编辑:
我已经尝试将主线程的默认GMainContext传递给新创建的线程。 看一看。 告诉我,我的方法是否正确。
GMainLoop *loop; gpointer event_loop_thread(gpointer arg) { GMainContext *context = (GMainContext *)arg; loop = g_main_loop_new(context, FALSE); g_main_context_push_thread_default(context); g_main_loop_run(loop); g_main_loop_unref(loop); return NULL; } int init() { g_thread_new(NULL, event_loop_thread, (gpointer)g_main_context_default()); return 0; } gboolean __hci_service(GIOChannel *source, GIOCondition condition, gpointer data) { // Doing something return FALSE; } int main() { init(); int _adapter_id = hci_devid("hci0"); int hci_dev = hci_open_dev(_adapter_id); GIOChannel *p_hci_io = g_io_channel_unix_new(dev_id); GIOCondition cond = (GIOCondition)(G_IO_IN); g_io_add_watch(p_hci_io, cond, __hci_service, NULL); //loop = g_main_loop_new(NULL, FALSE); //g_main_loop_run(loop); //g_main_loop_unref(loop); while (true); // I will close file descriptor return 0; }
如果要从线程运行主循环,则需要使用GMainContext
。 从Glib的主循环文档 :
为了允许在不同的线程中处理多个独立的源集,每个源与GMainContext相关联。 GMainContext只能在单个线程中运行,但可以将源添加到其中并从其他线程中删除。
使用g_main_loop_new(NULL, FALSE);
创建主循环时g_main_loop_new(NULL, FALSE);
虽然没有指定任何GMainContext很方便,但是如果你想在不同的线程中运行循环,你需要传递一个你想要你的循环的GMainContext。 您可以使用g_main_context_new()
创建GMainContext
并将其传递给g_main_loop_new()
,或使用g_main_context_get_thread_default()
获取正在运行的线程的默认主要上下文。
g_io_add_watch()
是该函数的另一个方便版本
使用默认优先级将GIOChannel添加到默认主循环上下文中。
遗憾的是,没有g_io_add_watch()
变量函数来指定主上下文,您必须从GIOChannel
手动创建GSource
, p_hci_io
,并通过g_source_attach()
附加到您的上下文。 请注意, g_io_add_watch_full()
也适用于默认主上下文。
您的第二个代码工作的原因是您在主线程中创建了主循环,其中包含您的源代码。