From 7f973e015eb59b626edc584a19a1ad3ffddf4867 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard 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