summaryrefslogtreecommitdiff
path: root/src/glibext/delayed.c
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2009-09-20 13:22:53 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2009-09-20 13:22:53 (GMT)
commitf7c1c34cb54b239586bf431b1749759baee9493e (patch)
tree24b2954e45202bcc36f60166112a23acf931be1f /src/glibext/delayed.c
parent859bdb6b51d76058eb1a8bfa619a15978f50b251 (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/delayed.c')
-rw-r--r--src/glibext/delayed.c319
1 files changed, 295 insertions, 24 deletions
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);
}