From 7f973e015eb59b626edc584a19a1ad3ffddf4867 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Mon, 19 Aug 2019 23:48:34 +0200
Subject: Fixed some concurrency issues with segment reference counters.

---
 src/glibext/linesegment.c | 34 ++++++++++++++++++----------------
 1 file changed, 18 insertions(+), 16 deletions(-)

diff --git a/src/glibext/linesegment.c b/src/glibext/linesegment.c
index 15fde78..bd11afc 100644
--- a/src/glibext/linesegment.c
+++ b/src/glibext/linesegment.c
@@ -111,7 +111,7 @@ static segment_rendering _seg_params;
 /* Fragment de caractères aux propriétés potentiellement partagées */
 struct _line_segment
 {
-    unsigned int ref_count;                 /* Compteur de références      */
+    gint ref_count;                         /* Compteur de références      */
 
     rendering_pattern_t *pattern;           /* Propriétés du rendu         */
 
@@ -123,6 +123,7 @@ struct _line_segment
 
 /* Conservation de toutes les créations partagées */
 static GHashTable *_segcnt_htable;
+G_LOCK_DEFINE_STATIC(_segcnt_mutex);
 
 
 /* Fournit l'empreinte d'un contenu pour segments. */
@@ -309,9 +310,11 @@ static bool is_line_segment_equal(const line_segment *content, const line_segmen
 
     result = (content->pattern == other->pattern);
 
-    result &= (cmp_fnv_64a(content->hash, other->hash) == 0);
+    if (result)
+        result = (cmp_fnv_64a(content->hash, other->hash) == 0);
 
-    result &= (strcmp(content->text, other->text) == 0);
+    if (result)
+        result = (strcmp(content->text, other->text) == 0);
 
     return result;
 
@@ -340,10 +343,7 @@ static line_segment *get_shared_segment_content(const line_segment *content)
     gboolean created;                       /* Validation de mise en place */
 #endif
 
-    /**
-     * On considère qu'il n'y a pas besoin de mutex ici, puisque toutes les
-     * opérations se réalisent à priori dans le seul thread principal pour l'affichage.
-     */
+    G_LOCK(_segcnt_mutex);
 
     found = g_hash_table_lookup_extended(_segcnt_htable, content, (gpointer *)&result, NULL);
 
@@ -355,7 +355,7 @@ static line_segment *get_shared_segment_content(const line_segment *content)
 
         memcpy(result, content, allocated);
 
-        result->ref_count = 1;
+        g_atomic_int_set(&result->ref_count, 1);
 
 #ifndef NDEBUG
         created = g_hash_table_insert(_segcnt_htable, result, result);
@@ -370,10 +370,12 @@ static line_segment *get_shared_segment_content(const line_segment *content)
     {
         assert(result->ref_count < UINT_MAX);
 
-        result->ref_count++;
+        g_atomic_int_inc(&result->ref_count);
 
     }
 
+    G_UNLOCK(_segcnt_mutex);
+
     return result;
 
 }
@@ -397,19 +399,19 @@ static void release_shared_segment_content(line_segment *content)
     gboolean deleted;                       /* Validation de suppression   */
 #endif
 
-    /**
-     * On considère qu'il n'y a pas besoin de mutex ici, puisque toutes les
-     * opérations se réalisent à priori dans le seul thread principal pour l'affichage.
-     */
-
-    if (--content->ref_count == 0)
+    if (g_atomic_int_dec_and_test(&content->ref_count))
     {
+        G_LOCK(_segcnt_mutex);
+
 #ifndef NDEBUG
         deleted = g_hash_table_remove(_segcnt_htable, content);
         assert(deleted);
 #else
         g_hash_table_remove(_segcnt_htable, content);
 #endif
+
+        G_UNLOCK(_segcnt_mutex);
+
     }
 
 }
@@ -480,7 +482,7 @@ line_segment *get_new_line_segment(RenderingTagType type, const char *text, size
 
 void ref_line_segment(line_segment *segment)
 {
-    segment->ref_count++;
+    g_atomic_int_inc(&segment->ref_count);
 
 }
 
-- 
cgit v0.11.2-87-g4458