线程中的 GLib GMainContext?

abh*_*ora 4 c glib

我在堆栈溢出上搜索以找到与我的问题相关的答案。但我没有找到任何答案。

我有一个启动线程的主线程(我的 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;

}
Run Code Online (Sandbox Code Playgroud)

但是,如果我尝试这段代码,那么一切都会按预期工作:

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;

} 
Run Code Online (Sandbox Code Playgroud)

编辑:

我尝试将主线程的默认 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;

} 
Run Code Online (Sandbox Code Playgroud)

Yas*_*oji 5

GMainContext如果您想从线程运行主循环,则需要使用。来自 Glib 的主循环文档

为了允许在不同线程中处理多个独立的源集,每个源都与一个 GMainContext 关联。GMainContext 只能在单个线程中运行,但可以在其他线程中向其中添加源或从中删除源。

当您使用 创建主循环时,虽然g_main_loop_new(NULL, FALSE);指定任何 GMainContext很方便,但如果您想在不同的线程中运行循环,则需要传递您想要循环的 GMainContext。您可以创建一个with并将其传递给, 或使用来获取正在运行的线程的默认主上下文。GMainContextg_main_context_new()g_main_loop_new()g_main_context_get_thread_default()

g_io_add_watch()是该函数的另一个方便版本,

将 GIOChannel 添加到具有默认优先级的默认主循环上下文中。

不幸的是,没有变体函数来指定主上下文,您必须从,g_io_add_watch()手动创建, 并通过 附加到您的上下文。请注意,这也适用于默认的主上下文。GSourceGIOChannelp_hci_iog_source_attach()g_io_add_watch_full()

您的第二个代码起作用的原因是您在附加了源代码的主线程中创建了主循环。