summaryrefslogtreecommitdiff
path: root/src/arch/sharing
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch/sharing')
-rw-r--r--src/arch/sharing/instance-int.h12
-rw-r--r--src/arch/sharing/instance.c55
-rw-r--r--src/arch/sharing/instance.h9
-rw-r--r--src/arch/sharing/manager.c100
-rw-r--r--src/arch/sharing/manager.h4
5 files changed, 71 insertions, 109 deletions
diff --git a/src/arch/sharing/instance-int.h b/src/arch/sharing/instance-int.h
index 0b57cc4..0117e05 100644
--- a/src/arch/sharing/instance-int.h
+++ b/src/arch/sharing/instance-int.h
@@ -30,7 +30,7 @@
/* Initialise un nouvel objet partagé avec des informations. */
-typedef bool (* init_shared_fc) (GSharedInstance *, const void *);
+typedef bool (* init_shared_fc) (GSharedInstance *, const GSharedInstance *);
/* Fournit la valeur du compteur de partage. */
typedef unsigned int (* get_shared_ref_fc) (const GSharedInstance *);
@@ -41,11 +41,8 @@ typedef void (* inc_shared_ref_fc) (GSharedInstance *);
/* Décrémente le compteur de partage. */
typedef void (* dec_shared_ref_fc) (GSharedInstance *);
-/* Indique l'objet partagé correspond à une description donnée. */
-typedef bool (* compare_shared_info_fc) (const GSharedInstance *, const void *);
-
-/* Détermine si deux instances partagées sont identiques. */
-typedef gboolean (* is_shared_equal_fc) (const GSharedInstance *, const GSharedInstance *);
+/* Procède à l'initialisation de l'interface de partage. */
+typedef int (* qck_compare_shared_fc) (const GSharedInstance **, const GSharedInstance **);
/* Règles de partage d'une instance GObject (interface) */
@@ -59,8 +56,7 @@ struct _GSharedInstanceIface
inc_shared_ref_fc inc_ref; /* Incrémentation du compteur */
dec_shared_ref_fc dec_ref; /* Décrémentation du compteur */
- compare_shared_info_fc cmp_info; /* Comparaison des détails */
- is_shared_equal_fc is_equal; /* Comparaison d'instance */
+ qck_compare_shared_fc qck_cmp; /* Comparaison des détails */
};
diff --git a/src/arch/sharing/instance.c b/src/arch/sharing/instance.c
index 956a4c7..a4cfcad 100644
--- a/src/arch/sharing/instance.c
+++ b/src/arch/sharing/instance.c
@@ -61,7 +61,7 @@ static void g_shared_instance_default_init(GSharedInstanceInterface *iface)
/******************************************************************************
* *
* Paramètres : instance = objet partagé à initialiser. *
-* info = information à utiliser pour la mise en place. *
+* template = informations à retrouver intégralement. *
* *
* Description : Initialise un nouvel objet partagé avec des informations. *
* *
@@ -71,14 +71,14 @@ static void g_shared_instance_default_init(GSharedInstanceInterface *iface)
* *
******************************************************************************/
-bool g_shared_instance_init(GSharedInstance *instance, const void *info)
+bool g_shared_instance_init(GSharedInstance *instance, const GSharedInstance *template)
{
bool result; /* Bilan à retourner */
GSharedInstanceIface *iface; /* Interface utilisée */
iface = G_SHARED_INSTANCE_GET_IFACE(instance);
- result = iface->init(instance, info);
+ result = iface->init(instance, template);
return result;
@@ -156,54 +156,31 @@ void g_shared_instance_dec_references(GSharedInstance *instance)
/******************************************************************************
* *
-* Paramètres : instance = objet partagé à consulter. *
-* info = compilation de d'information à analyser. *
-* *
-* Description : Indique l'objet partagé correspond à une description donnée. *
-* *
-* Retour : true si les détails centraux sont partagés, false sinon. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-gboolean g_shared_instance_compare_info(const GSharedInstance *instance, const void *info)
-{
- bool result; /* Bilan à retourner */
- GSharedInstanceIface *iface; /* Interface utilisée */
-
- iface = G_SHARED_INSTANCE_GET_IFACE(instance);
-
- result = iface->cmp_info(instance, info);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : a = première instance d'objet partagé à comparer. *
-* b = second instance d'objet partagé à comparer. *
+* Paramètres : a = premier objet partagé à consulter. *
+* b = second objet partagé à consulter. *
* *
-* Description : Détermine si deux instances partagées sont identiques. *
+* Description : Compare de façon accélérée un object partagé avec un autre. *
* *
-* Retour : TRUE si les deux éléments partagés sont identiques, ou FALSE.*
+* Retour : Bilan de la comparaison. *
* *
* Remarques : - *
* *
******************************************************************************/
-gboolean g_shared_instance_is_equal(const GSharedInstance *a, const GSharedInstance *b)
+int g_shared_instance_quickly_compare(const GSharedInstance **a, const GSharedInstance **b)
{
- gboolean result; /* Bilan à retourner */
+ int result; /* Bilan à faire remonter */
GSharedInstanceIface *iface; /* Interface utilisée */
- assert(G_OBJECT_TYPE(a) == G_OBJECT_TYPE(b));
+ /**
+ * Comme les insertions dans les tableaux triés à l'aide de qinsert()
+ * font passer la clef en premier argument et que celle ci n'est pas un
+ * objet valide, on inverse les arguments, puis on inverse le résultat obtenu.
+ */
- iface = G_SHARED_INSTANCE_GET_IFACE(a);
+ iface = G_SHARED_INSTANCE_GET_IFACE(*b);
- result = iface->is_equal(a, b);
+ result = iface->qck_cmp(b, a) * -1;
return result;
diff --git a/src/arch/sharing/instance.h b/src/arch/sharing/instance.h
index 8cf8385..81c56ef 100644
--- a/src/arch/sharing/instance.h
+++ b/src/arch/sharing/instance.h
@@ -49,7 +49,7 @@ typedef struct _GSharedInstanceIface GSharedInstanceIface;
GType g_shared_instance_get_type(void) G_GNUC_CONST;
/* Initialise un nouvel objet partagé avec des informations. */
-bool g_shared_instance_init(GSharedInstance *, const void *);
+bool g_shared_instance_init(GSharedInstance *, const GSharedInstance *);
/* Fournit la valeur du compteur de partage. */
unsigned int g_shared_instance_get_references(const GSharedInstance *);
@@ -60,11 +60,8 @@ void g_shared_instance_inc_references(GSharedInstance *);
/* Décrémente le compteur de partage. */
void g_shared_instance_dec_references(GSharedInstance *);
-/* Indique l'objet partagé correspond à une description donnée. */
-gboolean g_shared_instance_compare_info(const GSharedInstance *, const void *);
-
-/* Détermine si deux instances partagées sont identiques. */
-gboolean g_shared_instance_is_equal(const GSharedInstance *, const GSharedInstance *);
+/* Compare de façon accélérée un object partagé avec un autre. */
+int g_shared_instance_quickly_compare(const GSharedInstance **, const GSharedInstance **);
diff --git a/src/arch/sharing/manager.c b/src/arch/sharing/manager.c
index 2e92766..4c60e72 100644
--- a/src/arch/sharing/manager.c
+++ b/src/arch/sharing/manager.c
@@ -25,9 +25,14 @@
#include <assert.h>
+#include <malloc.h>
#ifdef DEBUG_DUMP_STATS
# include <stdio.h>
#endif
+#include <string.h>
+
+
+#include "../../common/sort.h"
@@ -36,7 +41,8 @@ struct _GShareManager
{
GObject parent; /* A laisser en premier */
- GHashTable *table; /* Collection de partages */
+ GSharedInstance **instances; /* Instances partagées */
+ size_t count; /* Quantité de ces instances */
GMutex access; /* Accès à la table */
GType managed; /* Type d'instances gérées */
@@ -107,6 +113,9 @@ static void g_share_manager_class_init(GShareManagerClass *class)
static void g_share_manager_init(GShareManager *manager)
{
+ manager->instances = NULL;
+ manager->count = 0;
+
g_mutex_init(&manager->access);
}
@@ -126,7 +135,11 @@ static void g_share_manager_init(GShareManager *manager)
static void g_share_manager_dispose(GShareManager *manager)
{
- g_hash_table_unref(manager->table);
+ size_t i; /* Boucle de parcours */
+
+ for (i = 0; i < manager->count; i++)
+ g_object_unref(G_OBJECT(manager->instances[i]));
+
g_mutex_clear(&manager->access);
G_OBJECT_CLASS(g_share_manager_parent_class)->dispose(G_OBJECT(manager));
@@ -148,6 +161,9 @@ static void g_share_manager_dispose(GShareManager *manager)
static void g_share_manager_finalize(GShareManager *manager)
{
+ if (manager->instances != NULL)
+ free(manager->instances);
+
G_OBJECT_CLASS(g_share_manager_parent_class)->finalize(G_OBJECT(manager));
}
@@ -171,11 +187,6 @@ GShareManager *g_share_manager_new(GType type)
result = g_object_new(G_TYPE_SHARE_MANAGER, NULL);
- result->table = g_hash_table_new_full((GHashFunc)g_direct_hash,
- (GEqualFunc)g_shared_instance_is_equal,
- (GDestroyNotify)g_object_unref,
- (GDestroyNotify)NULL);
-
result->managed = type;
return result;
@@ -185,8 +196,8 @@ GShareManager *g_share_manager_new(GType type)
/******************************************************************************
* *
-* Paramètres : manager = gestionnaire d'instance à consulter. *
-* info = informations à retrouver intégralement. *
+* Paramètres : manager = gestionnaire d'instance à consulter. *
+* template = informations à retrouver intégralement. *
* *
* Description : Retrouve ou crée une instance partagée. *
* *
@@ -196,29 +207,23 @@ GShareManager *g_share_manager_new(GType type)
* *
******************************************************************************/
-GSharedInstance *g_share_manager_get(GShareManager *manager, const void *info)
+GSharedInstance *g_share_manager_get(GShareManager *manager, GSharedInstance *template)
{
GSharedInstance *result; /* Trouvaille à retourner */
- gpointer found; /* Elément correspondant ? */
+ size_t index; /* Indice d'une instance idéale*/
+ bool found; /* Existence de cette instance */
bool status; /* Conclusion d'initialisation */
-#ifndef NDEBUG
- gboolean new; /* Présence de partage existant*/
-#endif
-
- gboolean find_shared_matching_info(const GSharedInstance *key, gpointer unused, const void *nfo)
- {
- return g_shared_instance_compare_info(key, nfo);
- }
g_mutex_lock(&manager->access);
- found = g_hash_table_find(manager->table, (GHRFunc)find_shared_matching_info, (void *)info);
+ found = bsearch_index(&template, manager->instances, manager->count, sizeof(GSharedInstance *),
+ (__compar_fn_t)g_shared_instance_quickly_compare, &index);
- if (found == NULL)
+ if (!found)
{
result = g_object_new(manager->managed, NULL);
- status = g_shared_instance_init(result, info);
+ status = g_shared_instance_init(result, template);
if (!status)
{
@@ -230,19 +235,15 @@ GSharedInstance *g_share_manager_get(GShareManager *manager, const void *info)
{
g_shared_instance_inc_references(result);
-#ifndef NDEBUG
- new = g_hash_table_add(manager->table, result);
- assert(new);
-#else
- g_hash_table_add(manager->table, result);
-#endif
+ manager->instances = (GSharedInstance **)_qinsert(manager->instances, &manager->count,
+ sizeof(GSharedInstance *), &result, index);
}
}
else
- result = G_SHARED_INSTANCE(found);
+ result = manager->instances[index];
if (result != NULL)
{
@@ -261,7 +262,7 @@ GSharedInstance *g_share_manager_get(GShareManager *manager, const void *info)
* *
* Paramètres : manager = gestionnaire d'instance à consulter. *
* old = ancienne instance partagée à faire évoluer. *
-* info = informations à retrouver intégralement. *
+* template = informations à retrouver intégralement. *
* container = propriétaire de l'ancienne version à contacter. *
* *
* Description : Met à jour une instance partagée. *
@@ -272,11 +273,11 @@ GSharedInstance *g_share_manager_get(GShareManager *manager, const void *info)
* *
******************************************************************************/
-GSharedInstance *g_share_manager_update(GShareManager *manager, GSharedInstance *old, const void *info, GShareContainer *container)
+GSharedInstance *g_share_manager_update(GShareManager *manager, GSharedInstance *old, GSharedInstance *template, GShareContainer *container)
{
GSharedInstance *result; /* Nouvelle instance à renvoyer*/
- result = g_share_manager_get(manager, info);
+ result = g_share_manager_get(manager, template);
if (container != NULL)
g_share_container_replace(container, old, result);
@@ -303,22 +304,19 @@ GSharedInstance *g_share_manager_update(GShareManager *manager, GSharedInstance
void g_share_manager_put(GShareManager *manager, GSharedInstance *shared)
{
-#ifndef NDEBUG
- gboolean found; /* Présence de partage existant*/
-#endif
-
g_mutex_lock(&manager->access);
g_shared_instance_dec_references(shared);
if (g_shared_instance_get_references(shared) == 1)
{
-#ifndef NDEBUG
- found = g_hash_table_remove(manager->table, shared);
- assert(found);
-#else
- g_hash_table_remove(manager->table, shared);
-#endif
+ g_object_unref(G_OBJECT(shared));
+
+ manager->instances = (GSharedInstance **)qdelete(manager->instances, &manager->count,
+ sizeof(GSharedInstance *),
+ (__compar_fn_t)g_shared_instance_quickly_compare,
+ &shared);
+
}
g_mutex_unlock(&manager->access);
@@ -341,32 +339,26 @@ void g_share_manager_put(GShareManager *manager, GSharedInstance *shared)
void g_share_manager_dump_stats(GShareManager *manager)
{
unsigned int counter; /* Quantité nécessaire */
+ size_t i; /* Boucle de parcours */
GTypeQuery query; /* Informations sur un type */
- guint size; /* Taille de la table */
-
- void count_shared_instances(const GSharedInstance *key, gpointer unused, unsigned int *c)
- {
- *c += g_shared_instance_get_references(key);
- }
counter = 0;
g_mutex_lock(&manager->access);
- g_hash_table_foreach(manager->table, (GHFunc)count_shared_instances, &counter);
-
- size = g_hash_table_size(manager->table);
+ for (i = 0; i < manager->count; i++)
+ counter += g_shared_instance_get_references(manager->instances[i]);
g_mutex_unlock(&manager->access);
g_type_query(manager->managed, &query);
- printf("%s: current = %u / %u - needed = %u / %u (size=%u, saved=%u)\n",
+ printf("%s: current = %zu / %zu - needed = %u / %u (size=%u, saved=%zu)\n",
query.type_name,
- size, size * query.instance_size,
+ manager->count, manager->count * query.instance_size,
counter, counter * query.instance_size,
query.instance_size,
- (counter - size) * query.instance_size);
+ (counter - manager->count) * query.instance_size);
}
#endif
diff --git a/src/arch/sharing/manager.h b/src/arch/sharing/manager.h
index 0a44214..2748134 100644
--- a/src/arch/sharing/manager.h
+++ b/src/arch/sharing/manager.h
@@ -60,10 +60,10 @@ GType g_share_manager_get_type(void);
GShareManager *g_share_manager_new(GType);
/* Retrouve ou crée une instance partagée. */
-GSharedInstance *g_share_manager_get(GShareManager *, const void *);
+GSharedInstance *g_share_manager_get(GShareManager *, GSharedInstance *);
/* Met à jour une instance partagée. */
-GSharedInstance *g_share_manager_update(GShareManager *, GSharedInstance *, const void *, GShareContainer *);
+GSharedInstance *g_share_manager_update(GShareManager *, GSharedInstance *, GSharedInstance *, GShareContainer *);
/* Abandonne un usage d'une instance partagée. */
void g_share_manager_put(GShareManager *, GSharedInstance *);