【问题标题】:Running multiple concurrent GMainLoops运行多个并发 GMainLoops
【发布时间】:2014-01-31 16:55:29
【问题描述】:

是否允许 GLib 的用户在多个线程中同时运行多个 GMainLoop 实例,每个线程运行自己的实例?我到处都找到了“是”和“否”的答案。我意识到这个问题之前已经在这个论坛(December 2011) 上提出过。

但是,我可以同时运行两个 GMainLoop 实例而不会出现明显问题。我的测试代码很简单:

  1. 在main() 中创建一个GMainLoop
  2. 使用g_timeout_add为默认上下文和主循环创建超时源
  3. 在 main() 中创建一个 GThread
  4. 使用g_main_loop_run运行主循环
  5. [线程上下文]:使用g_main_context_new创建上下文
  6. [线程上下文]:使用g_main_context_push_thread_default将该上下文设置为线程默认值
  7. [THREAD CONTEXT]:使用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);
}

【问题讨论】:

  • 我刚刚发现this 似乎同意这是可接受的 GLib API 用法。所以,我猜“是的,这很好”列中的另一个条目。

标签: c multithreading glib


【解决方案1】:

《GTK+ 开发基础》一书指出:

GLib 主循环被实现为多个结构,允许多个实例 同时运行。

因此,鉴于此,我的测试代码,以及我在上面的评论中发布的link,我们对这个问题有了明确的答案。

即:多个线程可能有自己的 GMainContext 和 GMainLoop,并且能够以并发的方式独立运行这些循环。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多