Client example: main loop handling fixes 07/276607/2
authorMichal Bloch <m.bloch@samsung.com>
Tue, 21 Jun 2022 16:09:04 +0000 (18:09 +0200)
committerMichal Bloch <m.bloch@samsung.com>
Wed, 22 Jun 2022 13:05:37 +0000 (15:05 +0200)
 * use a GThread instead of std::thread since everything
   else uses glib facilities instead of C++ ones

 * extract the wait at the end into its own function

 * fix the main loop not being unref'd

Change-Id: I4fd8c938ad793dd27e53f2def5a0dece2699551b
Signed-off-by: Michal Bloch <m.bloch@samsung.com>
clientExample/app/main.cpp

index 88b75c5..adbee9c 100644 (file)
@@ -1,6 +1,5 @@
 #include <iostream>
 #include <gio/gio.h>
-#include <thread>
 #include <cassert>
 #include <unistd.h>
 #include "sessiond.h"
@@ -62,8 +61,10 @@ gboolean callback_pending(gpointer data)
 
        // N.B. There are `noOfUsers` add and remove operations. Each add/remove
        // increments the value of the `callback_pending_reference` variable.
-       if (ctrl_value >= noOfUsers * 2)
+       if (ctrl_value >= noOfUsers * 2) {
                g_main_loop_quit(loop);
+               g_main_loop_unref(loop);
+       }
 
        return TRUE;
 }
@@ -117,11 +118,28 @@ int switch_user_test(int user_id)
        return new_user;
 }
 
+void wait_for_all_pending_callbacks(GMainLoop *loop, GThread *loop_thread)
+{
+       /* Create a new idle source, add a message idle function that ultimately terminates
+        * the message loop, making sure in advance that all callbacks have finished their actions. */
+       GSource *idle_source = g_idle_source_new();
+       g_source_set_callback(idle_source, (GSourceFunc) callback_pending, loop, NULL);
+       g_source_attach(idle_source, NULL);
+       g_source_unref(idle_source);
+
+       /* At some point the main loop thread will run all pending
+        * callbacks and then the above idle handler, terminating it.
+        *
+        * Join implicitly unrefs. */
+       g_thread_join(loop_thread);
+}
+
 int main(int argc, char *argv[])
 {
-       GMainLoop *loop = g_main_loop_new(NULL, FALSE);
        g_mutex_init(&mutex);
-       std::thread g_main_loop_thread(g_main_loop_run, loop);
+
+       GMainLoop *loop = g_main_loop_new(NULL, FALSE);
+       GThread *loop_thread = g_thread_new("mainloop thread", (GThreadFunc) g_main_loop_run, loop);
 
        ///===================================///
        printf("Test program start\nCreating test users...");
@@ -236,15 +254,7 @@ int main(int argc, char *argv[])
        }
        green_print("done");
 
-       // Create a new idle source, add a message idle function that ultimately terminates
-       // the message loop, making sure in advance that all callbacks have finished their actions.
-       GSource *idle_source = g_idle_source_new();
-       g_source_set_callback(idle_source, (GSourceFunc)callback_pending, loop, NULL);
-       g_source_attach(idle_source, NULL);
-       g_source_unref(idle_source);
-
-       // Wait for the message loop thread
-       g_main_loop_thread.join();
+       wait_for_all_pending_callbacks(loop, loop_thread);
 
        g_mutex_unlock(&mutex);
        g_mutex_clear(&mutex);