2017-02-22 22 views
1

我已经搜索堆栈溢出找到与我的问题相关的答案。但我没有找到任何答案。GLib GMainContext在一个线程中?

我有一个主线程(我的main()函数)启动一个线程。新线程运行GMainLoop。在我的主要功能中,我通过在某些文件描述符上调用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; 

} 

回答

2

如果要从线程运行主循环,则需要使用GMainContext。从油嘴的main loop documentation

为了允许的源的多个组独立于 不同的线程来处理,每个源与GMainContext相关联。 A GMainContext只能在单个线程中运行,但源可以将 添加到其中并从其他线程中删除。

当你创建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()变异函数指定一个主背景下,你必须从手动创建GSourceGIOChannelp_hci_io,并通过g_source_attach()连接到您的上下文。请注意,g_io_add_watch_full()也适用于默认的主要上下文。

你的第二个代码工作的原因是,你在主线程中创建了你的主循环,它有你的源代码。

+0

我编辑了我的答案。请看编辑部分 – abhiarora

+0

“你的第二个代码工作的原因是你用默认主环境中的循环覆盖了全局变量循环,它有你的源代码。” - 我的第二个版本不覆盖全局循环变量。我在main()函数中调用了init()函数调用。 – abhiarora

+0

感谢您的回答。我已经将主线程的GMainContext传递给新创建的线程。在新创建的线程中,我使用主线程的GMainContext创建主循环。我正在向全局GMainContext添加源代码,以便在发生事件时,新线程将分派它们。我错过了什么吗?你可以在你的答案中包含任何代码吗? – abhiarora