Lumiera  0.pre.03
»edit your freedom«
interfaceregistry.c
Go to the documentation of this file.
1 /*
2  InterfaceRegistry - registry for extension points
3 
4  Copyright (C)
5  2008, Christian Thaeter <ct@pipapo.org>
6 
7   **Lumiera** is free software; you can redistribute it and/or modify it
8   under the terms of the GNU General Public License as published by the
9   Free Software Foundation; either version 2 of the License, or (at your
10   option) any later version. See the file COPYING for further details.
11 
12 * *****************************************************************/
13 
14 
21 #include "include/logging.h"
22 #include "lib/error.h"
23 #include "lib/psplay.h"
24 #include "lib/safeclib.h"
25 
26 #include <nobug.h>
27 
28 #include "common/plugin.h"
30 
31 
32 
33 PSplay lumiera_interfaceregistry;
34 PSplay lumiera_pluginregistry;
35 lumiera_recmutex lumiera_interface_mutex;
36 
37 static int
38 lumiera_interface_cmp_fn (const void* keya, const void* keyb);
39 
40 static const void*
41 lumiera_interface_key_fn (const PSplaynode node);
42 
43 
44 
45 static LumieraInterfacenode
46 lumiera_interfacenode_new (LumieraInterface iface, LumieraPlugin plugin)
47 {
48  LumieraInterfacenode self = lumiera_malloc (sizeof (*self));
49 
50  psplaynode_init (&self->node);
51  self->interface = iface;
52  self->refcnt = 0;
53  self->plugin = plugin;
54  self->lnk = NULL;
55  self->deps_size = 0;
56  self->deps = NULL;
57 
58  return self;
59 }
60 
61 
62 static void
63 lumiera_interfacenode_delete (LumieraInterfacenode self)
64 {
65  if (self)
66  {
67  REQUIRE (self->refcnt == 0);
68  lumiera_free (self->deps);
69  lumiera_free (self);
70  }
71 }
72 
73 
75 void
77 {
78 
79  TRACE (interfaceregistry_dbg);
80  REQUIRE (!lumiera_interfaceregistry);
81  REQUIRE (!lumiera_pluginregistry);
82 
83  lumiera_interfaceregistry = psplay_new (lumiera_interface_cmp_fn, lumiera_interface_key_fn, NULL);
84  if (!lumiera_interfaceregistry)
85  LUMIERA_DIE (ERRNO);
86 
87  lumiera_pluginregistry = psplay_new (lumiera_plugin_cmp_fn, lumiera_plugin_key_fn, lumiera_plugin_delete_fn);
88  if (!lumiera_pluginregistry)
89  LUMIERA_DIE (ERRNO);
90 
91  lumiera_recmutex_init (&lumiera_interface_mutex, "interfaceregistry", &NOBUG_FLAG(interfaceregistry), NOBUG_CONTEXT);
92 
94 }
95 
96 
97 void
98 lumiera_interfaceregistry_destroy (void)
99 {
100  TRACE (interfaceregistry_dbg);
101 
103 
104  if (lumiera_pluginregistry)
105  psplay_delete (lumiera_pluginregistry);
106  lumiera_pluginregistry = NULL;
107 
108  lumiera_recmutex_destroy (&lumiera_interface_mutex, &NOBUG_FLAG(mutex_dbg), NOBUG_CONTEXT);
109 
110  REQUIRE (!psplay_nelements (lumiera_interfaceregistry), "some interfaces still registered at shutdown");
111 
112  if (lumiera_interfaceregistry)
113  psplay_destroy (lumiera_interfaceregistry);
114  lumiera_interfaceregistry = NULL;
115 }
116 
117 
118 void
119 lumiera_interfaceregistry_register_interface (LumieraInterface self, LumieraPlugin plugin)
120 {
121  TRACE (interfaceregistry_dbg);
122  REQUIRE (self);
123 
124  LUMIERA_RECMUTEX_SECTION (mutex_sync, &lumiera_interface_mutex)
125  {
126  TRACE (interfaceregistry, "interface %s, version %d, instance %s", self->interface, self->version, self->name);
127  psplay_insert (lumiera_interfaceregistry, &lumiera_interfacenode_new (self, plugin)->node, 100);
128  }
129 }
130 
131 
132 void
133 lumiera_interfaceregistry_bulkregister_interfaces (LumieraInterface* self, LumieraPlugin plugin)
134 {
135  TRACE (interfaceregistry_dbg);
136  REQUIRE (self);
137 
138  LUMIERA_RECMUTEX_SECTION (mutex_sync, &lumiera_interface_mutex)
139  {
140  while (*self)
141  {
142  TRACE (interfaceregistry, "interface %s, version %d, instance %s", (*self)->interface, (*self)->version, (*self)->name);
143  psplay_insert (lumiera_interfaceregistry, &lumiera_interfacenode_new (*self, plugin)->node, 100);
144  ++self;
145  }
146  }
147 }
148 
149 
150 void
151 lumiera_interfaceregistry_remove_interface (LumieraInterface self)
152 {
153  TRACE (interfaceregistry_dbg);
154  REQUIRE (self);
155 
156  LUMIERA_RECMUTEX_SECTION (mutex_sync, &lumiera_interface_mutex)
157  {
158  TRACE (interfaceregistry, "interface %s, version %d, instance %s", self->interface, self->version, self->name);
159  LumieraInterfacenode node = (LumieraInterfacenode) psplay_find (lumiera_interfaceregistry, self, 0);
160  REQUIRE (node->refcnt == 0, "but is %d", node->refcnt);
161 
162  lumiera_interfacenode_delete ((LumieraInterfacenode)psplay_remove (lumiera_interfaceregistry, &node->node));
163  }
164 }
165 
166 
167 void
168 lumiera_interfaceregistry_bulkremove_interfaces (LumieraInterface* self)
169 {
170  TRACE (interfaceregistry_dbg);
171  REQUIRE (self);
172 
173  LUMIERA_RECMUTEX_SECTION (mutex_sync, &lumiera_interface_mutex)
174  {
175  while (*self)
176  {
177  TRACE (interfaceregistry, "interface %s, version %d, instance %s", (*self)->interface, (*self)->version, (*self)->name);
178 
179  LumieraInterfacenode node = (LumieraInterfacenode) psplay_find (lumiera_interfaceregistry, *self, 0);
180  if (node)
181  {
182  REQUIRE (node->refcnt == 0, "but is %d", node->refcnt);
183  lumiera_interfacenode_delete ((LumieraInterfacenode) psplay_remove (lumiera_interfaceregistry, &node->node));
184  }
185  else
186  {
189 
190  WARN (interfaceregistry, "ENTRY NOT FOUND in interfaceregistry at clean-up of interface %s, instance %s"
191  , (*self)->interface
192  , (*self)->name);
193  }
194 
195  ++self;
196  }
197  }
198 }
199 
200 
201 LumieraInterfacenode
202 lumiera_interfaceregistry_interfacenode_find (const char* interface, unsigned version, const char* name)
203 {
204  TRACE (interfaceregistry_dbg);
205  struct lumiera_interface_struct cmp;
206  cmp.interface = interface;
207  cmp.version = version;
208  cmp.name = name;
209 
210  LumieraInterfacenode ret = NULL;
211 
212  LUMIERA_RECMUTEX_SECTION (mutex_sync, &lumiera_interface_mutex)
213  {
214  ret = (LumieraInterfacenode)psplay_find (lumiera_interfaceregistry, &cmp, 100);
215  }
216 
217  return ret;
218 }
219 
220 
221 LumieraInterface
222 lumiera_interfaceregistry_interface_find (const char* interface, unsigned version, const char* name)
223 {
224  return lumiera_interfaceregistry_interfacenode_find (interface, version, name)->interface;
225 }
226 
227 
228 static int
229 lumiera_interface_cmp_fn (const void* keya, const void* keyb)
230 {
231  const LumieraInterface a = (const LumieraInterface)keya;
232  const LumieraInterface b = (const LumieraInterface)keyb;
233 
234  int r = strcmp (a->interface, b->interface);
235  if (r<0)
236  return -1;
237  else if (r>0)
238  return 1;
239 
240  if (a->version < b->version)
241  return -1;
242  else if (a->version > b->version)
243  return 1;
244 
245  r = strcmp (a->name, b->name);
246  if (r<0)
247  return -1;
248  else if (r>0)
249  return 1;
250 
251  return 0;
252 }
253 
254 
255 static const void*
256 lumiera_interface_key_fn (const PSplaynode node)
257 {
258  return ((LumieraInterfacenode)node)->interface;
259 }
260 
261 /*
262 // Local Variables:
263 // mode: C
264 // c-file-style: "gnu"
265 // indent-tabs-mode: nil
266 // End:
267 */
Portable and safe wrappers around some C-Lib functions.
#define LUMIERA_RECMUTEX_SECTION(nobugflag, mtx)
Recursive Mutual exclusive section.
Definition: recmutex.h:32
PSplay psplay_destroy(PSplay self)
Destroy a splay tree Frees all elements and associated resources of a splay tree. ...
Definition: psplay.c:101
void lumiera_interface_destroy(void)
deregistering implementations of the above interface
Definition: interface.c:334
LumieraRecmutex lumiera_recmutex_destroy(LumieraRecmutex self, struct nobug_flag *flag, const struct nobug_context ctx)
Destroy a recursive mutex variable.
Definition: recmutex.c:53
Header for an interface, just the absolute necessary metadata.
Definition: interface.h:371
void lumiera_interface_init(void)
registering implementations of the above interface
Lumiera plugins define &#39;interfaces&#39; as shown in interface.h, the plugin system handles the loading of...
const char * name
name of this instance
Definition: interface.h:380
This header is for including and configuring NoBug.
unsigned version
major version, 0 means experimental
Definition: interface.h:377
static void lumiera_free(void *mem)
Free previously allocated memory.
Definition: safeclib.h:73
Lumiera error handling (C interface).
PSplaynode psplay_find(PSplay self, const void *key, int splayfactor)
Find a element in a splay tree.
Definition: psplay.c:300
LumieraRecmutex lumiera_recmutex_init(LumieraRecmutex self, const char *purpose, struct nobug_flag *flag, const struct nobug_context ctx)
Initialise a recursive mutex variable Initialises a &#39;recursive&#39; mutex which might be locked by the sa...
Definition: recmutex.c:32
PSplaynode psplay_insert(PSplay self, PSplaynode node, int splayfactor)
Insert a element into a splay tree.
Definition: psplay.c:246
void psplay_delete(PSplay self)
Delete a splay tree Frees all elements and associated resources of a splay tree and then itseld...
Definition: psplay.c:115
static size_t psplay_nelements(PSplay self)
Number of elements in tree.
Definition: psplay.h:103
#define LUMIERA_DIE(err)
Abort unconditionally with a &#39;Fatal Error!&#39; message.
Definition: error.h:54
PSplay psplay_new(psplay_cmp_fn cmp, psplay_key_fn key, psplay_delete_fn del)
Allocate a splay tree.
Definition: psplay.c:88
Probabilistic splay tree.
void * lumiera_malloc(size_t size)
Allocate memory.
Definition: safeclib.c:113
const char * interface
name of the interface (type)
Definition: interface.h:374
void lumiera_interfaceregistry_init(void)
Initialise the interface registry.
Global registry for interfaces (extension points).
PSplaynode psplay_remove(PSplay self, PSplaynode node)
Remove a node from a splay tree.
Definition: psplay.c:340
PSplaynode psplaynode_init(PSplaynode self)
Initialise a splay tree node The user has to place this nodes within his datastructure and must Initi...
Definition: psplay.c:122
ElementBoxWidget::Config::Qualifier name(string id)
define the name-ID displayed in the caption