2014-10-16 101 views
4

我對GMainLoop如何工作有些誤解。 主要的東西 - 將一些回調添加到g_main_loop(如g_timeout_add_seconds())的API不會將指針指向要添加該回調的循環。爲單獨添加回調g_main_loop

它看起來像你爲所有g_main_loop實例添加回調。 即使你還沒有創建。對於這個簡單的例子:

#include <glib.h> 

gboolean callback(gpointer data) 
{ 
    static guint16 i=0; 
    g_print("Iter=%"G_GUINT16_FORMAT"\n",i++); 
    if(i%5==0){ 
    g_print("try to stop loop1\n"); 
    g_main_loop_quit((GMainLoop*)data); 
    } 
    return TRUE; 
} 

int main() 
{ 
    GMainLoop* loop1 = NULL; 
    GMainLoop* loop2 = NULL; 
    loop1 = g_main_loop_new (NULL, FALSE); 

    g_timeout_add_seconds(1, callback,loop1); 

    loop2 = g_main_loop_new (NULL, FALSE); 
    g_print("run loop1\n"); 
    g_main_loop_run(loop1); 
    g_free(loop1); 
    g_print("run loop2\n"); 
    g_main_loop_run(loop2); 
    g_free(loop2); 
    return 0; 
} 

結果是:

run loop1 
Iter=0 
Iter=1 
Iter=2 
Iter=3 
Iter=4 
try to stop loop1 
run loop2 
Iter=5 
Iter=6 
Iter=7 
Iter=8 
Iter=9 
try to stop loop1 
Segmentation fault (core dumped) 

是否有可能加入到callback()loop1,不要將它添加到loop2

回答

10

快速查看的文檔g_idle_add()g_idle_add_full()g_timeout_add(),或g_timeout_add_full()會告訴你:

這在內部創建使用g_timeout_source_new()主循環源並將其附加到使用g_source_attach()主循環環境。如果您需要更好的控制,您可以手動執行這些步驟。

注意,它說,它非常重視源頭到主循環方面 - ,一個GMainContext,而不是GMainLoop。當您創建GMainLoop實例時,您將傳遞NULL作爲第一個參數。根據the g_main_loop_new() documentation,這樣的說法是

一個GMainContext(如果NULL,默認上下文將被使用)。

所以,你正在創建兩個主循環,都使用相同的上下文(這是默認的上下文)。

要得到的結果我想你期待,你應該這樣做:

#include <glib.h> 

gboolean callback(gpointer data) 
{ 
    static guint16 i=0; 
    g_print("Iter=%"G_GUINT16_FORMAT"\n",i++); 
    if(i%5==0){ 
    g_print("try to stop loop1\n", data); 
    g_main_loop_quit((GMainLoop*)data); 
    } 
    return TRUE; 
} 

int main() 
{ 
    GMainContext* con1 = NULL; 
    GMainContext* con2 = NULL; 
    GMainLoop* loop1 = NULL; 
    GMainLoop* loop2 = NULL; 
    GSource* source1 = NULL; 

    con1 = g_main_context_new(); 
    con2 = g_main_context_new(); 

    loop1 = g_main_loop_new (con1, FALSE); 
    loop2 = g_main_loop_new (con2, FALSE); 

    source1 = g_timeout_source_new_seconds (1); 
    g_source_set_callback (source1, callback, loop1, NULL); 
    g_source_attach (source1, con1); 

    // We don't need the GMainContext anymore—the loop has an internal 
    // reference so we'll drop ours. 
    g_main_context_unref (con1); 
    con1 = NULL; 

    // Ditto for the GSource 
    g_source_unref (source1); 
    source1 = NULL; 

    g_main_context_unref (con2); 
    con2 = NULL; 

    g_print("run loop1\n"); 
    g_main_loop_run(loop1); 
    // Use g_main_loop_unref, not g_free 
    g_main_loop_unref(loop1); 
    loop1 = NULL; 

    g_print("run loop2\n"); 
    // Note that there is no longer a callback attached here, so it will 
    // run forever. 
    g_main_loop_run(loop2); 
    g_main_loop_unref(loop2); 
    loop2 = NULL; 

    return 0; 
}