From f05f6772f12c3cdfa38096da08084a01f986d7b5 Mon Sep 17 00:00:00 2001 From: Christian Thaeter Date: Tue, 14 Oct 2008 23:06:43 +0200 Subject: [PATCH] Interface system refactoring * lumiera_interface are now static structures, never wrritten * introduced a lumiera_interfacenode which manages the dynamic data of interfaces. The interfaceregistry now holds this nodes. --- src/backend/interface.c | 159 +++++++++++++++++--------------- src/backend/interfaceregistry.c | 84 ++++++++++++----- src/backend/interfaceregistry.h | 32 +++++++ src/lib/interface.h | 25 ----- 4 files changed, 177 insertions(+), 123 deletions(-) diff --git a/src/backend/interface.c b/src/backend/interface.c index a93088213..0150e403e 100644 --- a/src/backend/interface.c +++ b/src/backend/interface.c @@ -36,18 +36,22 @@ */ -extern LumieraInterface lumiera_interface_stack; +static LumieraInterfacenode +lumiera_interface_open_interfacenode (LumieraInterfacenode self); + +static void +lumiera_interfacenode_close (LumieraInterfacenode self); LumieraInterface lumiera_interface_open (const char* interface, unsigned version, size_t minminorversion, const char* name) { - LumieraInterface self = NULL; + LumieraInterfacenode self = NULL; TRACE (interface, "%s", name); LUMIERA_RECMUTEX_SECTION (interfaceregistry, &lumiera_interface_mutex) { - self = lumiera_interfaceregistry_interface_find (interface, version, name); + self = lumiera_interfaceregistry_interfacenode_find (interface, version, name); if (!self) { @@ -56,33 +60,33 @@ lumiera_interface_open (const char* interface, unsigned version, size_t minminor if (self) { - if (minminorversion > self->size) + if (minminorversion > self->interface->size) { UNIMPLEMENTED ("set error"); self = NULL; } else { - self = lumiera_interface_open_interface (self); + self = lumiera_interface_open_interfacenode (self); } } } - return self; + return self->interface; } static void -push_dependency (LumieraInterface parent, LumieraInterface child) +push_dependency (LumieraInterfacenode parent, LumieraInterfacenode child) { /* push a dependency on the dependency array, allcoate or resize it on demand */ - TRACE (interface, "%s %s", parent->name, child->name); + TRACE (interface, "%s %s", parent->interface->name, child->interface->name); /* no dependencies recorded yet, alloc a first block for 4 pointers */ - if (!parent->ndeps) - parent->deps = lumiera_calloc (parent->ndeps = 4, sizeof (LumieraInterface)); + if (!parent->deps_size) + parent->deps = lumiera_calloc (parent->deps_size = 4, sizeof (LumieraInterfacenode)); - size_t sz = parent->ndeps; - LumieraInterface* itr = parent->deps; + size_t sz = parent->deps_size; + LumieraInterfacenode* itr = parent->deps; while (*itr) { @@ -91,33 +95,31 @@ push_dependency (LumieraInterface parent, LumieraInterface child) if (sz == 1) { /* block to small, realloc it with twice its size, we keep the block NULL terminated */ - sz = parent->ndeps + 1; - parent->ndeps *= 2; - parent->deps = lumiera_realloc (parent->deps, parent->ndeps * sizeof (LumieraInterface)); + sz = parent->deps_size + 1; + parent->deps_size *= 2; + parent->deps = lumiera_realloc (parent->deps, parent->deps_size * sizeof (LumieraInterface)); itr = parent->deps + sz - 2; memset (itr, 0, sz * sizeof (LumieraInterface)); } } - TODO ("free the deps when unregistering the interface"); - /* found free element, store self in dependencies */ *itr = child; } static void -depwalk (LumieraInterface self, LumieraInterface* stack) +depwalk (LumieraInterfacenode self, LumieraInterfacenode* stack) { /* increment refcount for all non-cyclic dependencies recursively */ if (self->deps) { - TRACE (interface, "%s %d", self->name, self->refcnt); - for (LumieraInterface* dep = self->deps; *dep; ++dep) + TRACE (interface, "%s %d", self->interface->name, self->refcnt); + for (LumieraInterfacenode* dep = self->deps; *dep; ++dep) { - TRACE (interface, "loop %s", (*dep)->name); + TRACE (interface, "loop %s", (*dep)->interface->name); int cycle = 0; - for (LumieraInterface itr = *stack; itr; itr = itr->lnk) + for (LumieraInterfacenode itr = *stack; itr; itr = itr->lnk) { if (itr == *dep) { @@ -144,11 +146,11 @@ depwalk (LumieraInterface self, LumieraInterface* stack) } -LumieraInterface -lumiera_interface_open_interface (LumieraInterface self) +static LumieraInterfacenode +lumiera_interface_open_interfacenode (LumieraInterfacenode self) { static unsigned collect_dependencies = 0; - static LumieraInterface stack = NULL; + static LumieraInterfacenode stack = NULL; /* Ok, this got little more complicated than it should be, @@ -157,14 +159,14 @@ lumiera_interface_open_interface (LumieraInterface self) if (self) { - TRACE (interface, "%s %d (%s)", self->name, self->refcnt, stack?stack->name:""); + TRACE (interface, "%s %d (%s)", self->interface->name, self->refcnt, stack?stack->interface->name:""); LUMIERA_RECMUTEX_SECTION (interfaceregistry, &lumiera_interface_mutex) { /* discover cycles, cycles don't refcount! */ int cycle = 0; - for (LumieraInterface itr = stack; itr; itr = itr->lnk) + for (LumieraInterfacenode itr = stack; itr; itr = itr->lnk) { if (itr == self) { @@ -188,11 +190,11 @@ lumiera_interface_open_interface (LumieraInterface self) if (self->refcnt == 1) { /* first opening, run acquire, recursive opening shall record its dependencies here */ - if (self->acquire) + if (self->interface->acquire) { - TRACE (interface, "Acquire %s", self->name); + TRACE (interface, "Acquire %s", self->interface->name); collect_dependencies = self->deps?0:1; - self = self->acquire (self); + self->interface = self->interface->acquire (self->interface); } } else @@ -216,60 +218,69 @@ lumiera_interface_open_interface (LumieraInterface self) void lumiera_interface_close (LumieraInterface self) { - static LumieraInterface stack = NULL; + TRACE (interface); + + LUMIERA_RECMUTEX_SECTION (interfaceregistry, &lumiera_interface_mutex) + { + lumiera_interfacenode_close ((LumieraInterfacenode)psplay_find (lumiera_interfaceregistry, self, 100)); + } +} + + +/* internal function, does no locking! */ +static void +lumiera_interfacenode_close (LumieraInterfacenode self) +{ + static LumieraInterfacenode stack = NULL; if (!self) return; - TRACE (interface, "%s %d (%s)", self->name, self->refcnt, stack?stack->name:""); + TRACE (interface, "%s %d (%s)", self->interface->name, self->refcnt, stack?stack->interface->name:""); - LUMIERA_RECMUTEX_SECTION (interfaceregistry, &lumiera_interface_mutex) + REQUIRE (self->refcnt); + + int cycle = 0; + + for (LumieraInterfacenode itr = stack; itr; itr = itr->lnk) { - REQUIRE (self->refcnt); - - int cycle = 0; - - for (LumieraInterface itr = stack; itr; itr = itr->lnk) + if (itr == self) { - if (itr == self) - { - TRACE (interface, "CYCLE"); - cycle = 1; - break; - } - } - - if (!cycle) - { - self->lnk = stack; - stack = self; - - if (self->refcnt == 1) - { - if (self->release) - { - TRACE (interface, "Release %s", self->name); - self->release (self); - } - } - else - { - if (self->deps) - { - TRACE (interface, "Recurse %s %d", self->name, self->refcnt); - - for (LumieraInterface* dep = self->deps; *dep; ++dep) - lumiera_interface_close (*dep); - } - } - - stack = self->lnk; - self->lnk = NULL; - --self->refcnt; + TRACE (interface, "CYCLE"); + cycle = 1; + break; } } -} + if (!cycle) + { + self->lnk = stack; + stack = self; + + if (self->refcnt == 1) + { + if (self->interface->release) + { + TRACE (interface, "Release %s", self->interface->name); + self->interface->release (self->interface); + } + } + else + { + if (self->deps) + { + TRACE (interface, "Recurse %s %d", self->interface->name, self->refcnt); + + for (LumieraInterfacenode* dep = self->deps; *dep; ++dep) + lumiera_interfacenode_close (*dep); + } + } + + stack = self->lnk; + self->lnk = NULL; + --self->refcnt; + } +} /* diff --git a/src/backend/interfaceregistry.c b/src/backend/interfaceregistry.c index 799f84b70..f31755f35 100644 --- a/src/backend/interfaceregistry.c +++ b/src/backend/interfaceregistry.c @@ -22,6 +22,7 @@ #include "lib/mutex.h" #include "lib/error.h" #include "lib/psplay.h" +#include "lib/safeclib.h" #include @@ -41,10 +42,9 @@ NOBUG_DEFINE_FLAG_PARENT (interface_all, backend); NOBUG_DEFINE_FLAG_PARENT (interfaceregistry, interface_all); NOBUG_DEFINE_FLAG_PARENT (interface, interface_all); -static PSplay interfaceregistry; +PSplay lumiera_interfaceregistry; lumiera_mutex lumiera_interface_mutex; - static int cmp_fn (const void* keya, const void* keyb); @@ -52,6 +52,34 @@ static const void* key_fn (const PSplaynode node); +static LumieraInterfacenode +lumiera_interfacenode_new (LumieraInterface iface) +{ + LumieraInterfacenode self = lumiera_malloc (sizeof (*self)); + + psplaynode_init (&self->node); + self->interface = iface; + self->refcnt = 0; + self->lnk = NULL; + self->deps_size = 0; + self->deps = NULL; + + return self; +} + + +static void +lumiera_interfacenode_delete (LumieraInterfacenode self) +{ + if (self) + { + REQUIRE (self->refcnt == 0); + lumiera_free (self->deps); + lumiera_free (self); + } +} + + /** * Initialize the interface registry @@ -63,28 +91,27 @@ lumiera_interfaceregistry_init (void) NOBUG_INIT_FLAG (interfaceregistry); NOBUG_INIT_FLAG (interface); TRACE (interfaceregistry); - REQUIRE (!interfaceregistry); + REQUIRE (!lumiera_interfaceregistry); - TODO ("introduce a registrynode structure, place all dynamic interface stuff there, make interface_struct const"); - - interfaceregistry = psplay_new (cmp_fn, key_fn, NULL); - if (!interfaceregistry) + lumiera_interfaceregistry = psplay_new (cmp_fn, key_fn, NULL); + if (!lumiera_interfaceregistry) LUMIERA_DIE (ERRNO); lumiera_recmutex_init (&lumiera_interface_mutex, "interfaceregistry", &NOBUG_FLAG(interfaceregistry)); } + void lumiera_interfaceregistry_destroy (void) { TRACE (interfaceregistry); - REQUIRE (!psplay_nelements (interfaceregistry)); + REQUIRE (!psplay_nelements (lumiera_interfaceregistry)); lumiera_mutex_destroy (&lumiera_interface_mutex, &NOBUG_FLAG(interfaceregistry)); - if (interfaceregistry) - psplay_destroy (interfaceregistry); - interfaceregistry = NULL; + if (lumiera_interfaceregistry) + psplay_destroy (lumiera_interfaceregistry); + lumiera_interfaceregistry = NULL; } @@ -97,7 +124,7 @@ lumiera_interfaceregistry_register_interface (LumieraInterface self) LUMIERA_RECMUTEX_SECTION (interfaceregistry, &lumiera_interface_mutex) { TRACE (interfaceregistry, "interface %s, version %d, instance %s", self->interface, self->version, self->name); - psplay_insert (interfaceregistry, &self->node, 100); + psplay_insert (lumiera_interfaceregistry, &lumiera_interfacenode_new (self)->node, 100); } } @@ -113,7 +140,7 @@ lumiera_interfaceregistry_bulkregister_interfaces (LumieraInterface* self) while (*self) { TRACE (interfaceregistry, "interface %s, version %d, instance %s", (*self)->interface, (*self)->version, (*self)->name); - psplay_insert (interfaceregistry, &(*self)->node, 100); + psplay_insert (lumiera_interfaceregistry, &lumiera_interfacenode_new (*self)->node, 100); ++self; } } @@ -128,10 +155,10 @@ lumiera_interfaceregistry_remove_interface (LumieraInterface self) LUMIERA_RECMUTEX_SECTION (interfaceregistry, &lumiera_interface_mutex) { - REQUIRE (self->refcnt == 0); - psplay_remove (interfaceregistry, &self->node); + LumieraInterfacenode node = (LumieraInterfacenode) psplay_find (lumiera_interfaceregistry, self, 0); + REQUIRE (node->refcnt == 0, "but is %d", node->refcnt); - FIXME ("free deps"); + lumiera_interfacenode_delete ((LumieraInterfacenode)psplay_remove (lumiera_interfaceregistry, &node->node)); } } @@ -147,18 +174,20 @@ lumiera_interfaceregistry_bulkremove_interfaces (LumieraInterface* self) while (*self) { TRACE (interfaceregistry, "interface %s, version %d, instance %s", (*self)->interface, (*self)->version, (*self)->name); - REQUIRE ((*self)->refcnt == 0, "but is %d", (*self)->refcnt); - psplay_remove (interfaceregistry, &(*self)->node); + LumieraInterfacenode node = (LumieraInterfacenode) psplay_find (lumiera_interfaceregistry, *self, 0); + REQUIRE (node->refcnt == 0, "but is %d", node->refcnt); + + lumiera_interfacenode_delete ((LumieraInterfacenode) psplay_remove (lumiera_interfaceregistry, &node->node)); + ++self; - FIXME ("free deps"); } } } -LumieraInterface -lumiera_interfaceregistry_interface_find (const char* interface, unsigned version, const char* name) +LumieraInterfacenode +lumiera_interfaceregistry_interfacenode_find (const char* interface, unsigned version, const char* name) { TRACE (interfaceregistry); struct lumiera_interface_struct cmp; @@ -166,17 +195,24 @@ lumiera_interfaceregistry_interface_find (const char* interface, unsigned versio cmp.version = version; cmp.name = name; - LumieraInterface ret = NULL; + LumieraInterfacenode ret = NULL; LUMIERA_RECMUTEX_SECTION (interfaceregistry, &lumiera_interface_mutex) { - ret = (LumieraInterface)psplay_find (interfaceregistry, &cmp, 100); + ret = (LumieraInterfacenode)psplay_find (lumiera_interfaceregistry, &cmp, 100); } return ret; } +LumieraInterface +lumiera_interfaceregistry_interface_find (const char* interface, unsigned version, const char* name) +{ + return lumiera_interfaceregistry_interfacenode_find (interface, version, name)->interface; +} + + static int cmp_fn (const void* keya, const void* keyb) { @@ -207,7 +243,7 @@ cmp_fn (const void* keya, const void* keyb) static const void* key_fn (const PSplaynode node) { - return node; + return ((LumieraInterfacenode)node)->interface; } diff --git a/src/backend/interfaceregistry.h b/src/backend/interfaceregistry.h index c6bf4a2e5..0af95c9be 100644 --- a/src/backend/interfaceregistry.h +++ b/src/backend/interfaceregistry.h @@ -22,6 +22,7 @@ #define LUMIERA_INTERFACEREGISTRY_H #include "lib/mutex.h" +#include "lib/psplay.h" #include "lib/interface.h" #include @@ -38,9 +39,37 @@ NOBUG_DECLARE_FLAG (interface_all); NOBUG_DECLARE_FLAG (interfaceregistry); NOBUG_DECLARE_FLAG (interface); +extern PSplay lumiera_interfaceregistry; extern lumiera_mutex lumiera_interface_mutex; +/** + * Interface management node. + * All active interfaces managed through this node which contains the dynamic data for + * dependency tracking and reference counting. + */ +typedef struct lumiera_interfacenode_struct lumiera_interfacenode; +typedef lumiera_interfacenode* LumieraInterfacenode; + +struct lumiera_interfacenode_struct +{ + /** all known interfaces are registered in a tree */ + psplaynode node; + + /** the interface itself */ + LumieraInterface interface; + + /** reference counters and link used for internal reference management */ + unsigned refcnt; + /** temporary used to stack interfaces when recursively opening/closing them */ + LumieraInterfacenode lnk; + /** allocated size of the following deps table */ + size_t deps_size; + /** NULL terminated table of all dependenncies (interfaces opened on initialization) */ + LumieraInterfacenode* deps; +}; + + /** * Initialize the interface registry */ @@ -63,6 +92,9 @@ lumiera_interfaceregistry_remove_interface (LumieraInterface self); void lumiera_interfaceregistry_bulkremove_interfaces (LumieraInterface* self); +LumieraInterfacenode +lumiera_interfaceregistry_interfacenode_find (const char* interface, unsigned version, const char* name); + LumieraInterface lumiera_interfaceregistry_interface_find (const char* interface, unsigned version, const char* name); diff --git a/src/lib/interface.h b/src/lib/interface.h index 16319c244..ef13e40e1 100644 --- a/src/lib/interface.h +++ b/src/lib/interface.h @@ -182,15 +182,10 @@ PPMPL_FOREACH(_P1_, __VA_ARGS__) LUMIERA_INTERFACE_TYPE(iname, version) LUMIERA_INTERFACE_DNAME(iname, version, name) = \ { \ { \ - PSPLAYNODE_INITIALIZER, \ #iname, \ version, \ #name, \ sizeof (LUMIERA_INTERFACE_TYPE(iname, version)), \ - 0, \ - NULL, \ - 0, \ - NULL, \ descriptor, \ acquire, \ release \ @@ -342,9 +337,6 @@ struct lumiera_interfaceslot_struct */ struct lumiera_interface_struct { - /** all known interfaces are registered in a tree */ - psplaynode node; - /** name of the interface (type) */ const char* interface; @@ -357,12 +349,6 @@ struct lumiera_interface_struct /** size of the whole interface structure (minor version) */ size_t size; - /** reference counters and link used for internal reference management */ - unsigned refcnt; - LumieraInterface lnk; - size_t ndeps; - LumieraInterface* deps; - /** metadata descriptor, itself a interface (or NULL) */ LumieraInterface descriptor; @@ -391,17 +377,6 @@ struct lumiera_interface_struct */ -/** - * Open an interface by handle. - * This is faster because it needs no lookup, one must be sure to have a valid handle - * which mets the requirements (version) - * @param self pointer to the interface to be opened - * @return self on success or NULL on error - * @internal This function is mostly for internal purposes - */ -LumieraInterface -lumiera_interface_open_interface (LumieraInterface self); - /** * Open an interface by version and name. * Looks up the requested interface, possibly loading it from a plugin.