summaryrefslogtreecommitdiff
path: root/src/glibext/singleton.c
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2025-01-26 14:25:51 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2025-01-26 14:25:51 (GMT)
commit56c148de74ed8c78ce54ed24daa83ec2f641e054 (patch)
treed4e43da9d6c729146c77fb30de8fa3767b257afb /src/glibext/singleton.c
parentb1227a2779c9a72cab1295a1419a9c990df6488e (diff)
Define new interfaces for arch operands.
Diffstat (limited to 'src/glibext/singleton.c')
-rw-r--r--src/glibext/singleton.c179
1 files changed, 92 insertions, 87 deletions
diff --git a/src/glibext/singleton.c b/src/glibext/singleton.c
index 65b83e7..4930323 100644
--- a/src/glibext/singleton.c
+++ b/src/glibext/singleton.c
@@ -26,9 +26,10 @@
#include <assert.h>
#include <malloc.h>
-#include <stdbool.h>
+#include "comparable.h"
+#include "hashable.h"
#include "singleton-int.h"
@@ -39,11 +40,14 @@
/* Procède à l'initialisation de l'interface de rassemblement. */
static void g_singleton_candidate_default_init(GSingletonCandidateInterface *);
+/* Fournit une liste de candidats embarqués par un candidat. */
+static GSingletonCandidate **g_singleton_candidate_list_inner_instances(const GSingletonCandidate *, size_t *);
+
/* Met à jour une liste de candidats embarqués par un candidat. */
static void g_singleton_candidate_update_inner_instances(GSingletonCandidate *, GSingletonCandidate **, size_t);
-/* Détermine si deux candidats à l'unicité sont identiques. */
-static gboolean _g_singleton_candidate_is_equal(GSingletonCandidate *, GSingletonCandidate *, GList **);
+/* Marque un candidat comme figé. */
+static void g_singleton_candidate_mark_as_read_only(GSingletonCandidate *);
@@ -70,7 +74,9 @@ static void g_singleton_factory_finalize(GSingletonFactory *);
/* Détermine le type d'une interface pour la constitution d'objets uniques. */
-G_DEFINE_INTERFACE(GSingletonCandidate, g_singleton_candidate, G_TYPE_OBJECT)
+G_DEFINE_INTERFACE_WITH_CODE(GSingletonCandidate, g_singleton_candidate, G_TYPE_OBJECT,
+ g_type_interface_add_prerequisite(g_define_type_id, G_TYPE_HASHABLE_OBJECT);
+ g_type_interface_add_prerequisite(g_define_type_id, G_TYPE_COMPARABLE_OBJECT))
/******************************************************************************
@@ -87,6 +93,13 @@ G_DEFINE_INTERFACE(GSingletonCandidate, g_singleton_candidate, G_TYPE_OBJECT)
static void g_singleton_candidate_default_init(GSingletonCandidateInterface *iface)
{
+ iface->list_inner = NULL;
+ iface->update_inner = NULL;
+
+ iface->mark_as_ro = NULL;
+ iface->is_ro = NULL;
+
+ iface->dup = NULL;
}
@@ -113,8 +126,11 @@ GSingletonCandidate **g_singleton_candidate_list_inner_instances(const GSingleto
if (iface->list_inner == NULL)
{
+ assert(iface->update_inner == NULL);
+
*count = 0;
result = NULL;
+
}
else
@@ -161,17 +177,16 @@ static void g_singleton_candidate_update_inner_instances(GSingletonCandidate *ca
* *
* Paramètres : candidate = objet dont l'instance se veut unique. *
* *
-* Description : Fournit l'empreinte d'un candidat à une centralisation. *
+* Description : Marque un candidat comme figé. *
* *
-* Retour : Empreinte de l'élément représenté. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-guint g_singleton_candidate_hash(GSingletonCandidate *candidate)
+static void g_singleton_candidate_mark_as_read_only(GSingletonCandidate *candidate)
{
- guint result; /* Valeur à retourner */
GSingletonCandidateInterface *iface; /* Interface utilisée */
GSingletonCandidate **children; /* Instances internes */
size_t count; /* Quantité de ces instances */
@@ -179,103 +194,62 @@ guint g_singleton_candidate_hash(GSingletonCandidate *candidate)
iface = G_SINGLETON_CANDIDATE_GET_IFACE(candidate);
- result = iface->hash(candidate);
+ iface->mark_as_ro(candidate);
children = g_singleton_candidate_list_inner_instances(candidate, &count);
for (i = 0; i < count; i++)
{
- result ^= g_singleton_candidate_hash(children[i]);
- unref_object(children[i]);
+ g_singleton_candidate_mark_as_read_only(children[i]);
+ unref_object(G_OBJECT(children[i]));
}
if (children != NULL)
free(children);
- return result;
-
}
/******************************************************************************
* *
* Paramètres : candidate = objet dont l'instance se veut unique. *
-* other = second élément à analyser. *
-* processed = liste de candidats déjà traités. *
* *
-* Description : Détermine si deux candidats à l'unicité sont identiques. *
+* Description : Indique si le candidat est figé. *
* *
-* Retour : Bilan de la comparaison. *
+* Retour : true si le contenu du candidat ne peut plus être modifié. *
* *
* Remarques : - *
* *
******************************************************************************/
-static gboolean _g_singleton_candidate_is_equal(GSingletonCandidate *candidate, GSingletonCandidate *other, GList **processed)
+bool g_singleton_candidate_is_read_only(const GSingletonCandidate *candidate)
{
- gboolean result; /* Bilan à renvoyer */
- GList *skip; /* Détection de boucle */
+ bool result; /* Etat à retourner */
GSingletonCandidateInterface *iface; /* Interface utilisée */
- GSingletonCandidate **children[2]; /* Instances internes */
- size_t count[2]; /* Quantité de ces instances */
+#ifndef NDEBUG
+ GSingletonCandidate **children; /* Instances internes */
+ size_t count; /* Quantité de ces instances */
size_t i; /* Boucle de parcours */
+#endif
- skip = g_list_find(processed[0], candidate);
-
- if (skip != NULL)
- result = (g_list_find(processed[1], other) != NULL);
-
- else
- {
- iface = G_SINGLETON_CANDIDATE_GET_IFACE(candidate);
-
- result = iface->is_equal(candidate, other);
-
- processed[0] = g_list_append(processed[0], candidate);
- processed[1] = g_list_append(processed[1], other);
-
- if (!result)
- goto done;
-
- children[0] = g_singleton_candidate_list_inner_instances(candidate, &count[0]);
- children[1] = g_singleton_candidate_list_inner_instances(other, &count[1]);
-
- if (count[0] != count[1])
- {
- for (i = 0; i < count[0]; i++)
- g_object_unref(G_OBJECT(children[0][i]));
-
- for (i = 0; i < count[1]; i++)
- g_object_unref(G_OBJECT(children[1][i]));
-
- }
-
- else
- {
- for (i = 0; i < count[0] && result; i++)
- {
- result = _g_singleton_candidate_is_equal(children[0][i], children[1][i], processed);
- g_object_unref(G_OBJECT(children[0][i]));
- g_object_unref(G_OBJECT(children[1][i]));
- }
-
- for (; i < count[0]; i++)
- {
- g_object_unref(G_OBJECT(children[0][i]));
- g_object_unref(G_OBJECT(children[1][i]));
- }
+ iface = G_SINGLETON_CANDIDATE_GET_IFACE(candidate);
- if (children[0] != NULL)
- free(children[0]);
+ result = iface->is_ro(candidate);
- if (children[1] != NULL)
- free(children[1]);
+#ifndef NDEBUG
- }
+ children = g_singleton_candidate_list_inner_instances(candidate, &count);
+ for (i = 0; i < count; i++)
+ {
+ assert(result == g_singleton_candidate_is_read_only(children[i]));
+ unref_object(G_OBJECT(children[i]));
}
- done:
+ if (children != NULL)
+ free(children);
+
+#endif
return result;
@@ -285,31 +259,60 @@ static gboolean _g_singleton_candidate_is_equal(GSingletonCandidate *candidate,
/******************************************************************************
* *
* Paramètres : candidate = objet dont l'instance se veut unique. *
-* other = second élément à analyser. *
* *
-* Description : Détermine si deux candidats à l'unicité sont identiques. *
+* Description : Crée une copie modifiable d'un object unique. *
* *
-* Retour : Bilan de la comparaison. *
+* Retour : Nouvelle instance mise en place. *
* *
* Remarques : - *
* *
******************************************************************************/
-gboolean g_singleton_candidate_is_equal(GSingletonCandidate *candidate, GSingletonCandidate *other)
+GSingletonCandidate *g_singleton_candidate_dup(const GSingletonCandidate *candidate)
{
- gboolean result; /* Bilan à renvoyer */
- GList *processed[2]; /* Suivi des traitements */
+ GSingletonCandidate *result; /* Instance à retourner */
+ GSingletonCandidateInterface *iface; /* Interface utilisée */
+ size_t count; /* Quantité d'objets internes */
+ GSingletonCandidate **children; /* Liste d'instances internes */
+ size_t i; /* Boucle de parcours */
+ GSingletonCandidate **new_children; /* Nouvelle liste d'instances */
+
+ iface = G_SINGLETON_CANDIDATE_GET_IFACE(candidate);
+
+ result = iface->dup(candidate);
+
+ assert(!g_singleton_candidate_is_read_only(result));
+
+ children = g_singleton_candidate_list_inner_instances(candidate, &count);
+
+ if (count > 0)
+ {
+ new_children = malloc(count * sizeof(GSingletonCandidate *));
+
+ for (i = 0; i < count; i++)
+ {
+ new_children[i] = g_singleton_candidate_dup(children[i]);
+
+ assert(!g_singleton_candidate_is_read_only(new_children[i]));
+
+ }
+
+ g_singleton_candidate_update_inner_instances(result, new_children, count);
- processed[0] = NULL;
- processed[1] = NULL;
+ for (i = 0; i < count; i++)
+ {
+ unref_object(G_OBJECT(new_children[i]));
+ unref_object(G_OBJECT(children[i]));
+ }
+
+ free(new_children);
- result = _g_singleton_candidate_is_equal(candidate, other, processed);
+ }
- assert(processed[0] != NULL);
- assert(processed[1] != NULL);
+ if (children != NULL)
+ free(children);
- g_list_free(processed[0]);
- g_list_free(processed[1]);
+ assert(G_OBJECT_TYPE(result) == G_OBJECT_TYPE(candidate));
return result;
@@ -364,8 +367,8 @@ static void g_singleton_factory_class_init(GSingletonFactoryClass *klass)
static void g_singleton_factory_init(GSingletonFactory *factory)
{
- factory->table = g_hash_table_new_full((GHashFunc)g_singleton_candidate_hash,
- (GEqualFunc)g_singleton_candidate_is_equal,
+ factory->table = g_hash_table_new_full((GHashFunc)g_hashable_object_hash,
+ (GEqualFunc)g_comparable_object_is_equal,
g_object_unref, NULL);
g_mutex_init(&factory->access);
@@ -524,6 +527,8 @@ GSingletonCandidate *g_singleton_factory_get_instance(GSingletonFactory *factory
g_hash_table_add(factory->table, candidate);
#endif
+ g_singleton_candidate_mark_as_read_only(candidate);
+
result = candidate;
}