我意识到这可能是一个新手GLib问题,但我很难找到解决我的问题的代码示例。所以在我走错了路之前,我想要你的建议。
我的代码侦听D-Bus消息。一个D-Bus消息是“退出”消息,旨在指示主循环关闭。如果主循环中没有其他任务,一个简单的解决方案可能是简单地在下面的代码中调用g_main_loop_run()
并让D-Bus消息处理代码(此处未显示)执行g_main_loop_quit()
时收到“退出”消息。
但是,我更喜欢由主循环决定退出,主循环除了监听D-Bus消息外,还可以执行各种其他任务。设置工作D-Bus服务器后,以下代码按预期执行此操作:
GMainLoop *glib_mainloop = g_main_loop_new( NULL, false );
/* Set up the D-Bus connection to work in the GLib event loop. */
dbus_connection_setup_with_g_main( dbus_connection, NULL );
/* Run the GLib event loop. */
GMainContext *glib_context = g_main_context_default( );
while( quit_indicator == false )
{
g_main_context_iteration( glib_context, /*allow blocking=*/false );
/* Do a variety of other tasks. */
}
g_main_loop_quit( glib_mainloop );
注意:以上是用于说明我的问题的最低代码,我知道主循环中的“其他任务”可以通过线程,GSource
或其他方式更好地处理。例如,如果按原样使用上述代码,则会出现明显的繁忙等待或计时问题。
我的问题是:上面的代码示例是实现我想要的正确方法还是有更“真实”的GLib方式呢?
答案 0 :(得分:2)
您的方法基本上是正确的。很多例子都说使用g_main_loop_run()
和g_main_loop_quit()
来控制主要的上下文,但是你可以手动迭代主上下文。
应该对代码进行一处更改是告诉g_main_context_iteration()
允许阻塞,否则主循环本质上是一个繁忙的循环,并且您的进程在等待I / O时不会休眠。如果您手动迭代GMainLoop
,也根本不需要使用GMainContext
。
另一个必要的变化是,当您更改终止条件的值时,调用g_main_context_wakeup()
将主要上下文从g_main_context_iteration()
中阻止。
第三,使用GMainLoop
/ g_main_loop_new()
创建和退出g_main_loop_quit()
不会在您的代码中执行任何操作,因为GMainLoop
永远不会与g_main_loop_run()
一起运行。放弃这些电话。
这是更新版本:
GMainContext *context = g_main_context_default ();
gboolean quit = FALSE;
/* Set up the D-Bus connection to work in the GLib event loop. */
dbus_connection_setup_with_g_main (dbus_connection, context);
/* Run the GLib event loop. */
while (!quit)
g_main_context_iteration (context, TRUE);
/* To exit the main loop (from a callback implementing your D-Bus Quit() function): */
quit = TRUE;
g_main_context_wakeup (NULL /* global default main context */);
其他几点:
GMainContext
g_autoptr(GMainContext) context = g_main_context_new (); g_main_context_push_thread_default (context);
。您不应在多个线程之间共享GMainContext
。虽然这样做是安全的,但它不具备性能。以下是使用这些技术的基于GLib的现代守护程序中主循环的MPL许可示例:https://git.apertis.org/cgit/rhosydd.git/tree/libcroesor/service.c#n569