diff options
Diffstat (limited to 'src/arch/sharing')
-rw-r--r-- | src/arch/sharing/instance-int.h | 12 | ||||
-rw-r--r-- | src/arch/sharing/instance.c | 55 | ||||
-rw-r--r-- | src/arch/sharing/instance.h | 9 | ||||
-rw-r--r-- | src/arch/sharing/manager.c | 100 | ||||
-rw-r--r-- | src/arch/sharing/manager.h | 4 |
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 *); |