From 01402277db54d9fddaa12878f6db7f02c8d8e7ef Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Sun, 22 Apr 2018 17:23:01 +0200
Subject: Ensured all tasks are completed before exiting batch mode.

---
 src/analysis/project.c |  8 ++++---
 src/glibext/delayed.c  | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++
 src/glibext/delayed.h  |  3 +++
 src/main.c             |  2 +-
 4 files changed, 73 insertions(+), 4 deletions(-)

diff --git a/src/analysis/project.c b/src/analysis/project.c
index 88b468a..b4108ff 100644
--- a/src/analysis/project.c
+++ b/src/analysis/project.c
@@ -999,14 +999,16 @@ static void on_loaded_content_analyzed(GLoadedContent *content, gboolean success
 {
     const char *desc;                       /* Description du contenu      */
 
+    desc = g_loaded_content_describe(content, true);
+
     if (success)
+    {
         g_study_project_attach_content(project, content);
+        log_variadic_message(LMT_INFO, _("Content from '%s' has been analyzed successfully!"), desc);
+    }
 
     else
-    {
-        desc = g_loaded_content_describe(content, true);
         log_variadic_message(LMT_ERROR, _("Failed to load '%s'"), desc);
-    }
 
     g_object_ref(G_OBJECT(content));
 
diff --git a/src/glibext/delayed.c b/src/glibext/delayed.c
index 78c8a10..d05b67a 100644
--- a/src/glibext/delayed.c
+++ b/src/glibext/delayed.c
@@ -150,6 +150,7 @@ struct _GWorkQueue
     GWorkGroup **groups;                    /* Files de traitement         */
     size_t groups_count;                    /* Nombre de files internes    */
     GMutex mutex;                           /* Verrou pour l'accès         */
+    GCond wait_all;                         /* Réveil d'attente globale    */
 
 };
 
@@ -787,6 +788,7 @@ static void g_work_queue_init(GWorkQueue *queue)
     queue->groups = NULL;
     queue->groups_count = 0;
     g_mutex_init(&queue->mutex);
+    g_cond_init(&queue->wait_all);
 
 }
 
@@ -815,6 +817,7 @@ static void g_work_queue_dispose(GWorkQueue *queue)
     g_mutex_unlock(&queue->mutex);
 
     g_mutex_clear(&queue->mutex);
+    g_cond_clear(&queue->wait_all);
 
     G_OBJECT_CLASS(g_work_queue_parent_class)->dispose(G_OBJECT(queue));
 
@@ -984,6 +987,8 @@ void g_work_queue_delete_work_group(GWorkQueue *queue, wgroup_id_t id)
 
     assert(found);
 
+    g_cond_broadcast(&queue->wait_all);
+
     g_mutex_unlock(&queue->mutex);
 
 }
@@ -1123,6 +1128,65 @@ void g_work_queue_wait_for_completion(GWorkQueue *queue, wgroup_id_t id)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : queue = gestionnaire de l'ensemble des groupes de travail.   *
+*                                                                             *
+*  Description : Attend que toutes les tâches de tout groupe soient traitées. *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_work_queue_wait_for_all_completions(GWorkQueue *queue)
+{
+    GWorkGroup *def_group;                  /* Groupe de travail par défaut*/
+
+    g_mutex_lock(&queue->mutex);
+
+    /**
+     * Récupération du groupe par défaut.
+     */
+
+    def_group = g_work_queue_ensure_group_exists(queue, DEFAULT_WORK_GROUP);
+
+    g_object_ref(G_OBJECT(def_group));
+
+ wait_again:
+
+    /**
+     * Attente d'éventuels groupes isolés.
+     */
+
+    while (queue->groups_count > 1)
+        g_cond_wait(&queue->wait_all, &queue->mutex);
+
+    g_mutex_unlock(&queue->mutex);
+
+    /**
+     * Attente du groupe principal.
+     */
+
+    g_work_queue_wait_for_completion(queue, DEFAULT_WORK_GROUP);
+
+    /**
+     * Si le groupe par défaut a généré de nouveaux groupes, on recommence !
+     */
+
+    g_mutex_lock(&queue->mutex);
+
+    if (queue->groups_count > 1)
+        goto wait_again;
+
+    g_mutex_unlock(&queue->mutex);
+
+    g_object_unref(G_OBJECT(def_group));
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : queue    = gestionnaire de l'ensemble des groupes de travail.*
 *                id       = identifiant d'un groupe de travail.               *
 *                callback = éventuelle fonction à appeler ou NULL.            *
diff --git a/src/glibext/delayed.h b/src/glibext/delayed.h
index ab43640..340a298 100644
--- a/src/glibext/delayed.h
+++ b/src/glibext/delayed.h
@@ -107,6 +107,9 @@ bool g_work_queue_is_empty(GWorkQueue *, wgroup_id_t);
 /* Attend que toutes les tâches d'un groupe soient traitées. */
 void g_work_queue_wait_for_completion(GWorkQueue *, wgroup_id_t);
 
+/* Attend que toutes les tâches de tout groupe soient traitées. */
+void g_work_queue_wait_for_all_completions(GWorkQueue *);
+
 
 /* Etudie le besoin d'attendre d'avantage de prochaines tâches. */
 typedef bool (* wait_for_incoming_works_cb) (GWorkQueue *, wgroup_id_t, void *);
diff --git a/src/main.c b/src/main.c
index 626cae8..0abc29f 100644
--- a/src/main.c
+++ b/src/main.c
@@ -340,7 +340,7 @@ int main(int argc, char **argv)
     result = open_binaries(argv + optind, argc - optind);
 
     if (batch_mode)
-        g_work_queue_wait_for_completion(get_work_queue(), DEFAULT_WORK_GROUP);
+        g_work_queue_wait_for_all_completions(get_work_queue());
 
     else
         gtk_main();
-- 
cgit v0.11.2-87-g4458