2014-10-16 137 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; 
}