diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2009-09-20 13:22:53 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2009-09-20 13:22:53 (GMT) |
commit | f7c1c34cb54b239586bf431b1749759baee9493e (patch) | |
tree | 24b2954e45202bcc36f60166112a23acf931be1f /src/glibext | |
parent | 859bdb6b51d76058eb1a8bfa619a15978f50b251 (diff) |
Rewritten the work queue and fixed thread concurrency.
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@117 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
Diffstat (limited to 'src/glibext')
-rw-r--r-- | src/glibext/delayed-int.h | 41 | ||||
-rw-r--r-- | src/glibext/delayed.c | 319 | ||||
-rw-r--r-- | src/glibext/delayed.h | 12 |
3 files changed, 317 insertions, 55 deletions
diff --git a/src/glibext/delayed-int.h b/src/glibext/delayed-int.h index 7fb8f3a..b2e2b23 100644 --- a/src/glibext/delayed-int.h +++ b/src/glibext/delayed-int.h @@ -25,12 +25,17 @@ #include "../common/dllist.h" +#include "../gtkext/gtkextstatusbar.h" /* -------------------------- TACHE DIFFEREE DANS LE TEMPS -------------------------- */ +/* Traite un travail programmé. */ +typedef void (* run_task_fc) (GDelayedWork *, GtkExtStatusBar *); + + /* Travail différé (instance) */ struct _GDelayedWork { @@ -38,6 +43,8 @@ struct _GDelayedWork DL_LIST_ITEM(link); /* Lien vers les maillons */ + run_task_fc run; /* Traitement externalisé */ + }; /* Travail différé (classe) */ @@ -45,38 +52,12 @@ struct _GDelayedWorkClass { GObjectClass parent; /* A laisser en premier */ -}; - - -#define delayed_work_list_add_tail(new, head) dl_list_add_tail(new, head, GDelayedWork, link) -#define delayed_work_list_del(item, head) dl_list_del(item, head, GDelayedWork, link) - - - -/* ------------------------- TRAITEMENT DE TACHES DIFFEREES ------------------------- */ - + /* Signaux */ -/* Effectue le traitement d'une tâche donnée. */ -typedef void (* process_work_fc) (GWorkQueue *, GDelayedWork *); - - -/* Gestionnaire des travaux différés (instance) */ -struct _GWorkQueue -{ - GObject parent; /* A laisser en premier */ - - GDelayedWork *works; /* Tâches à mener à bien */ - GMutex *mutex; /* Verrou pour l'accès */ - GCond *cond; /* Réveil pour un traitement */ - - GThread *thread; /* Procédure de traitement */ - process_work_fc process; /* Coeur du traitement */ + void (* work_completed) (GDelayedWork *); }; -/* Gestionnaire des travaux différés (classe) */ -struct _GWorkQueueClass -{ - GObjectClass parent; /* A laisser en premier */ -}; +#define delayed_work_list_add_tail(new, head) dl_list_add_tail(new, head, GDelayedWork, link) +#define delayed_work_list_del(item, head) dl_list_del(item, head, GDelayedWork, link) diff --git a/src/glibext/delayed.c b/src/glibext/delayed.c index 4388b2c..8f23538 100644 --- a/src/glibext/delayed.c +++ b/src/glibext/delayed.c @@ -24,6 +24,9 @@ #include "delayed.h" +#include <malloc.h> + + #include "delayed-int.h" @@ -37,20 +40,96 @@ static void g_delayed_work_class_init(GDelayedWorkClass *); /* Initialise une instance de travail différé. */ static void g_delayed_work_init(GDelayedWork *); +/* Mène l'opération programmée. */ +static void g_delayed_work_process(GDelayedWork *, GtkExtStatusBar *); + + + +/* -------------------------- THREAD DE TRAITEMENTS DEDIES -------------------------- */ + + +#define G_TYPE_TYPED_QUEUE g_typed_queue_get_type() +#define G_TYPED_QUEUE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_typed_queue_get_type(), GTypedQueue)) +#define G_IS_TYPED_QUEUE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_typed_queue_get_type())) +#define G_TYPED_QUEUE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_TYPED_QUEUE, GTypedQueueClass)) +#define G_IS_TYPED_QUEUE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_TYPED_QUEUE)) +#define G_TYPED_QUEUE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_TYPED_QUEUE, GTypedQueueClass)) + + +/* File de traitement pour un type donné (instance) */ +typedef struct _GTypedQueue +{ + GObject parent; /* A laisser en premier */ + + GType type; /* Type de travaux menés */ + + GtkExtStatusBar *statusbar; /* Barre de statut principale */ + + GDelayedWork *works; /* Tâches à mener à bien */ + GMutex *mutex; /* Verrou pour l'accès */ + GCond *cond; /* Réveil pour un traitement */ + + GThread *thread; /* Procédure de traitement */ + +} GTypedQueue; + +/* File de traitement pour un type donné (classe) */ +typedef struct _GTypedQueueClass +{ + GObjectClass parent; /* A laisser en premier */ + +} GTypedQueueClass; + + +/* Indique le type défini pour les travaux typés. */ +static GType g_typed_queue_get_type(void); + +/* Initialise la classe des travaux typés. */ +static void g_typed_queue_class_init(GTypedQueueClass *); + +/* Initialise une instance de gestionnaire de travaux typés. */ +static void g_typed_queue_init(GTypedQueue *); + +/* Crée un nouveau thread dédié à un type de travaux donné. */ +static GTypedQueue *g_typed_queue_new(GType, GtkExtStatusBar *); + +/* Place une nouvelle tâche en attente dans une file dédiée. */ +static void g_typed_queue_schedule(GTypedQueue *, GDelayedWork *); + +/* Assure le traitement en différé. */ +static void *g_typed_queue_process(GTypedQueue *); + /* ------------------------- TRAITEMENT DE TACHES DIFFEREES ------------------------- */ +/* Gestionnaire des travaux différés (instance) */ +struct _GWorkQueue +{ + GObject parent; /* A laisser en premier */ + + GtkExtStatusBar *statusbar; /* Barre de statut principale */ + + GTypedQueue **threads; /* Files de traitement */ + size_t threads_count; /* Nombre de files internes */ + +}; + +/* Gestionnaire des travaux différés (classe) */ +struct _GWorkQueueClass +{ + GObjectClass parent; /* A laisser en premier */ + +}; + + /* Initialise la classe des travaux différés. */ static void g_work_queue_class_init(GWorkQueueClass *); /* Initialise une instance de gestionnaire de travaux différés. */ static void g_work_queue_init(GWorkQueue *); -/* Assure le traitement en différé. */ -static void *g_work_queue_process(GWorkQueue *); - /* ---------------------------------------------------------------------------------- */ @@ -76,6 +155,13 @@ G_DEFINE_TYPE(GDelayedWork, g_delayed_work, G_TYPE_OBJECT); static void g_delayed_work_class_init(GDelayedWorkClass *klass) { + g_signal_new("work-completed", + G_TYPE_DELAYED_WORK, + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(GDelayedWorkClass, work_completed), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); } @@ -98,21 +184,43 @@ static void g_delayed_work_init(GDelayedWork *work) } +/****************************************************************************** +* * +* Paramètres : work = travail à effectuer. * +* statusbar = barre de statut à tenir informée. * +* * +* Description : Mène l'opération programmée. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_delayed_work_process(GDelayedWork *work, GtkExtStatusBar *statusbar) +{ + work->run(work, statusbar); + + g_signal_emit_by_name(work, "work-completed"); + +} + + /* ---------------------------------------------------------------------------------- */ -/* TRAITEMENT DE TACHES DIFFEREES */ +/* THREAD DE TRAITEMENTS DEDIES */ /* ---------------------------------------------------------------------------------- */ -/* Indique le type défini pour le gestionnaire des travaux différés. */ -G_DEFINE_TYPE(GWorkQueue, g_work_queue, G_TYPE_OBJECT); +/* Indique le type défini pour les travaux typés. */ +G_DEFINE_TYPE(GTypedQueue, g_typed_queue, G_TYPE_OBJECT); /****************************************************************************** * * * Paramètres : klass = classe à initialiser. * * * -* Description : Initialise la classe des travaux différés. * +* Description : Initialise la classe des travaux typés. * * * * Retour : - * * * @@ -120,7 +228,7 @@ G_DEFINE_TYPE(GWorkQueue, g_work_queue, G_TYPE_OBJECT); * * ******************************************************************************/ -static void g_work_queue_class_init(GWorkQueueClass *klass) +static void g_typed_queue_class_init(GTypedQueueClass *klass) { } @@ -130,7 +238,7 @@ static void g_work_queue_class_init(GWorkQueueClass *klass) * * * Paramètres : queue = instance à initialiser. * * * -* Description : Initialise une instance de gestionnaire de travaux différés. * +* Description : Initialise une instance de gestionnaire de travaux typés. * * * * Retour : - * * * @@ -138,23 +246,23 @@ static void g_work_queue_class_init(GWorkQueueClass *klass) * * ******************************************************************************/ -static void g_work_queue_init(GWorkQueue *queue) +static void g_typed_queue_init(GTypedQueue *queue) { GError *error; /* Bilan de création de thread */ queue->mutex = g_mutex_new(); if (queue->mutex == NULL) - goto gwqi_error; + goto gtqi_error; queue->cond = g_cond_new(); if (queue->cond == NULL) - goto gwqi_error; + goto gtqi_error; - queue->thread = g_thread_create((GThreadFunc)g_work_queue_process, queue, FALSE, &error); + queue->thread = g_thread_create((GThreadFunc)g_typed_queue_process, queue, FALSE, &error); if (!queue->thread) - goto gwqi_error; + goto gtqi_error; - gwqi_error: + gtqi_error: /* TODO */ return; @@ -163,6 +271,59 @@ static void g_work_queue_init(GWorkQueue *queue) /****************************************************************************** * * +* Paramètres : type = type dont seront marqués tous les travaux donnés.* +* statusbar = barre de statut à tenir informée. * +* * +* Description : Crée un nouveau thread dédié à un type de travaux donné. * +* * +* Retour : Structure associée au thread mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GTypedQueue *g_typed_queue_new(GType type, GtkExtStatusBar *statusbar) +{ + GTypedQueue *result; /* Traiteur à retourner */ + + result = g_object_new(G_TYPE_TYPED_QUEUE, NULL); + + result->type = type; + result->statusbar = statusbar; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : queue = gestionnaire des actions à mener. * +* work = nouvelle tâche à programmer, puis effectuer. * +* * +* Description : Place une nouvelle tâche en attente dans une file dédiée. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_typed_queue_schedule(GTypedQueue *queue, GDelayedWork *work) +{ + g_mutex_lock(queue->mutex); + + delayed_work_list_add_tail(work, &queue->works); + + g_cond_signal(queue->cond); + + g_mutex_unlock(queue->mutex); + +} + + +/****************************************************************************** +* * * Paramètres : queue = gestionnaire des actions à mener. * * * * Description : Assure le traitement en différé. * @@ -173,7 +334,7 @@ static void g_work_queue_init(GWorkQueue *queue) * * ******************************************************************************/ -static void *g_work_queue_process(GWorkQueue *queue) +static void *g_typed_queue_process(GTypedQueue *queue) { GDelayedWork *work; /* Traitement à mener */ @@ -189,7 +350,7 @@ static void *g_work_queue_process(GWorkQueue *queue) g_mutex_unlock(queue->mutex); - queue->process(queue, work); + g_delayed_work_process(work, queue->statusbar); /* TODO : delete work */ @@ -200,10 +361,108 @@ static void *g_work_queue_process(GWorkQueue *queue) } + +/* ---------------------------------------------------------------------------------- */ +/* TRAITEMENT DE TACHES DIFFEREES */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour le gestionnaire des travaux différés. */ +G_DEFINE_TYPE(GWorkQueue, g_work_queue, G_TYPE_OBJECT); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des travaux différés. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_work_queue_class_init(GWorkQueueClass *klass) +{ + +} + + /****************************************************************************** * * -* Paramètres : queu = gestionnaire des actions à mener. * -* work = nouvelle tâche à programmer, puis effectuer. * +* Paramètres : queue = instance à initialiser. * +* * +* Description : Initialise une instance de gestionnaire de travaux différés. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_work_queue_init(GWorkQueue *queue) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : ref = espace de référencements global. * +* * +* Description : Procède au chargement du gestionnaire d'analyse différées. * +* * +* Retour : true pour indiquer un chargement réussi, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool init_work_queue(GObject *ref) +{ + GWorkQueue *queue; /* Singleton à mettre en place */ + + queue = g_object_new(G_TYPE_WORK_QUEUE, NULL); + + queue->statusbar = g_object_get_data(ref, "statusbar"); + + if (queue != NULL) + _get_work_queue(queue); + + return (queue != NULL); + +} + + +/****************************************************************************** +* * +* Paramètres : queue = nouveau gestionnaire à mémoriser ou NULL. * +* * +* Description : Fournit le gestionnaire de traitements parallèles courant. * +* * +* Retour : Gestionnaire de traitements parallèles courant. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GWorkQueue *_get_work_queue(GWorkQueue *queue) +{ + static GWorkQueue *result = NULL; /* Singleton à retourner */ + + if (queue != NULL) + result = queue; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : queue = gestionnaire des actions à mener. * +* work = nouvelle tâche à programmer, puis effectuer. * * * * Description : Place une nouvelle tâche en attente. * * * @@ -213,14 +472,26 @@ static void *g_work_queue_process(GWorkQueue *queue) * * ******************************************************************************/ -void g_delayed_queue_schedule_work(GWorkQueue *queue, GDelayedWork *work) +void g_work_queue_schedule_work(GWorkQueue *queue, GDelayedWork *work) { - g_mutex_lock(queue->mutex); + GType target; /* Type de travail à ajouter */ + size_t i; /* Boucle de traitement */ - delayed_work_list_add_tail(work, &queue->works); + target = G_TYPE_FROM_INSTANCE(work); - g_cond_signal(queue->cond); + for (i = 0; i < queue->threads_count; i++) + if (queue->threads[i]->type == target) break; - g_mutex_unlock(queue->mutex); + if (i == queue->threads_count) + { + queue->threads_count++; + queue->threads = (GTypedQueue **)realloc(queue->threads, + queue->threads_count * sizeof(GTypedQueue *)); + + queue->threads[i] = g_typed_queue_new(target, queue->statusbar); + + } + + g_typed_queue_schedule(queue->threads[i], work); } diff --git a/src/glibext/delayed.h b/src/glibext/delayed.h index d1e3967..501bb7f 100644 --- a/src/glibext/delayed.h +++ b/src/glibext/delayed.h @@ -26,6 +26,7 @@ #include <glib-object.h> +#include <stdbool.h> @@ -70,11 +71,20 @@ typedef struct _GWorkQueue GWorkQueue; typedef struct _GWorkQueueClass GWorkQueueClass; +#define get_work_queue() _get_work_queue(NULL) + + /* Indique le type défini pour le gestionnaire des travaux différés. */ GType g_work_queue_get_type(void); +/* Procède au chargement du gestionnaire d'analyse différées. */ +bool init_work_queue(GObject *); + +/* Fournit le gestionnaire de traitements parallèles courant. */ +GWorkQueue *_get_work_queue(GWorkQueue *); + /* Place une nouvelle tâche en attente. */ -void g_delayed_queue_schedule_work(GWorkQueue *, GDelayedWork *); +void g_work_queue_schedule_work(GWorkQueue *, GDelayedWork *); |