运行多个并发GMainLoops

时间:2014-01-31 16:55:29

标签: c multithreading glib

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

但是,我可以同时运行两个GMainLoop个实例而没有明显的问题。我的测试代码非常简单:

  1. GMainLoop
  2. 中创建main()
  3. 使用g_timeout_add
  4. 为默认上下文和主循环创建超时源
  5. 在main()
  6. 中创建一个GThread
  7. 使用g_main_loop_run
  8. 运行主循环
  9. [THREAD CONTEXT]:使用g_main_context_new
  10. 创建上下文
  11. [THREAD CONTEXT]:使用g_main_context_push_thread_default
  12. 将该上下文设置为线程默认值
  13. [THREAD CONTEXT]:使用g_main_loop_new创建循环并为其提供新的上下文
  14. [THREAD CONTEXT]:创建超时源,并通过g_source_attach将其附加到新上下文。
  15. [THREAD_CONTEXT]:让线程调用g_main_loop_run
  16. 这样做,我看到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);
    }
    

1 个答案:

答案 0 :(得分:12)

“GTK +发展的​​基础”一书指出:

  

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

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

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