From 5d99d1bb648d757724662b0b0b56366e60ed3693 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Mon, 23 Apr 2018 21:27:40 +0200 Subject: Adopted a predictable scheduling behavior when broadcasting threads. --- src/glibext/delayed.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/src/glibext/delayed.c b/src/glibext/delayed.c index d05b67a..9d67a7c 100644 --- a/src/glibext/delayed.c +++ b/src/glibext/delayed.c @@ -442,8 +442,17 @@ static void g_work_group_dispose(GWorkGroup *group) group->force_exit = true; + /** + * Concernant la pose du verrou, se référer aux commentaires de la + * fonction g_work_group_process(). + */ + + g_mutex_lock(&group->mutex); + g_cond_broadcast(&group->cond); + g_mutex_unlock(&group->mutex); + for (i = 0; i < group->threads_count; i++) g_thread_join(group->threads[i]); @@ -599,9 +608,51 @@ static void *g_work_group_process(GWorkGroup *group) g_object_unref(G_OBJECT(work)); + /** + * Verrou ou pas verrou ? + * + * La documentation de la GLib indique que ce n'est pas nécessaire : + * + * ''' + * It is good practice to lock the same mutex as the waiting threads + * while calling this function, though not required. + * ''' + * + * Ce conseil se trouve verbatim à l'adresse : + * + * https://developer.gnome.org/glib/stable/glib-Threads.html#g-cond-broadcast + * + * Dans la pratique, il peut arriver que l'attente de la fonction + * g_work_group_wait_for_completion() ne soit jamais interrompue. + * + * La documentation POSIX est un peu plus orientée : + * + * ''' + * The pthread_cond_broadcast() functions may be called by a thread + * whether or not it currently owns the mutex that threads calling + * pthread_cond_wait() have associated with the condition variable + * during their waits; however, if predictable scheduling behavior is + * required, then that mutex shall be locked by the thread calling + * pthread_cond_broadcast(). + * ''' + * + * Ce passage complet est consultable à l'adresse : + * + * http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_cond_broadcast.html + * + * La page de manuel pthread_cond_broadcast(3) est quant à elle plus + * directrice : aucun complément d'information sur le sujet n'est fourni + * et les exemples associés utilisent implicement un verrou pendant + * sont appel. + */ + + g_mutex_lock(&group->mutex); + if (g_atomic_int_dec_and_test(&group->pending)) g_cond_broadcast(&group->wait_cond); + g_mutex_unlock(&group->mutex); + } return NULL; @@ -730,8 +781,17 @@ static void g_work_group_set_extra_wait_callback(GWorkGroup *group, wait_for_inc static void g_work_group_wake_up_waiters(GWorkGroup *group) { + /** + * Concernant la pose du verrou, se référer aux commentaires de la + * fonction g_work_group_process(). + */ + + g_mutex_lock(&group->mutex); + g_cond_broadcast(&group->wait_cond); + g_mutex_unlock(&group->mutex); + } -- cgit v0.11.2-87-g4458