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) Lumiera.org
5  2008, Christian Thaeter <ct@pipapo.org>
6 
7  This program is free software; you can redistribute it and/or
8  modify it under the terms of the GNU General Public License as
9  published by the Free Software Foundation; either version 2 of
10  the License, or (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 
21 * *****************************************************/
22 
23 
30 #include "include/logging.h"
31 #include "lib/error.h"
32 #include "lib/psplay.h"
33 #include "lib/safeclib.h"
34 
35 #include <nobug.h>
36 
37 #include "common/plugin.h"
39 
40 
41 
42 PSplay lumiera_interfaceregistry;
43 PSplay lumiera_pluginregistry;
44 lumiera_recmutex lumiera_interface_mutex;
45 
46 static int
47 lumiera_interface_cmp_fn (const void* keya, const void* keyb);
48 
49 static const void*
50 lumiera_interface_key_fn (const PSplaynode node);
51 
52 
53 
54 static LumieraInterfacenode
55 lumiera_interfacenode_new (LumieraInterface iface, LumieraPlugin plugin)
56 {
57  LumieraInterfacenode self = lumiera_malloc (sizeof (*self));
58 
59  psplaynode_init (&self->node);
60  self->interface = iface;
61  self->refcnt = 0;
62  self->plugin = plugin;
63  self->lnk = NULL;
64  self->deps_size = 0;
65  self->deps = NULL;
66 
67  return self;
68 }
69 
70 
71 static void
72 lumiera_interfacenode_delete (LumieraInterfacenode self)
73 {
74  if (self)
75  {
76  REQUIRE (self->refcnt == 0);
77  lumiera_free (self->deps);
78  lumiera_free (self);
79  }
80 }
81 
82 
84 void
86 {
87 
88  TRACE (interfaceregistry_dbg);
89  REQUIRE (!lumiera_interfaceregistry);
90  REQUIRE (!lumiera_pluginregistry);
91 
92  lumiera_interfaceregistry = psplay_new (lumiera_interface_cmp_fn, lumiera_interface_key_fn, NULL);
93  if (!lumiera_interfaceregistry)
94  LUMIERA_DIE (ERRNO);
95 
96  lumiera_pluginregistry = psplay_new (lumiera_plugin_cmp_fn, lumiera_plugin_key_fn, lumiera_plugin_delete_fn);
97  if (!lumiera_pluginregistry)
98  LUMIERA_DIE (ERRNO);
99 
100  lumiera_recmutex_init (&lumiera_interface_mutex, "interfaceregistry", &NOBUG_FLAG(interfaceregistry), NOBUG_CONTEXT);
101 
103 }
104 
105 
106 void
107 lumiera_interfaceregistry_destroy (void)
108 {
109  TRACE (interfaceregistry_dbg);
110 
112 
113  if (lumiera_pluginregistry)
114  psplay_delete (lumiera_pluginregistry);
115  lumiera_pluginregistry = NULL;
116 
117  lumiera_recmutex_destroy (&lumiera_interface_mutex, &NOBUG_FLAG(mutex_dbg), NOBUG_CONTEXT);
118 
119  REQUIRE (!psplay_nelements (lumiera_interfaceregistry), "some interfaces still registered at shutdown");
120 
121  if (lumiera_interfaceregistry)
122  psplay_destroy (lumiera_interfaceregistry);
123  lumiera_interfaceregistry = NULL;
124 }
125 
126 
127 void
128 lumiera_interfaceregistry_register_interface (LumieraInterface self, LumieraPlugin plugin)
129 {
130  TRACE (interfaceregistry_dbg);
131  REQUIRE (self);
132 
133  LUMIERA_RECMUTEX_SECTION (mutex_sync, &lumiera_interface_mutex)
134  {
135  TRACE (interfaceregistry, "interface %s, version %d, instance %s", self->interface, self->version, self->name);
136  psplay_insert (lumiera_interfaceregistry, &lumiera_interfacenode_new (self, plugin)->node, 100);
137  }
138 }
139 
140 
141 void
142 lumiera_interfaceregistry_bulkregister_interfaces (LumieraInterface* self, LumieraPlugin plugin)
143 {
144  TRACE (interfaceregistry_dbg);
145  REQUIRE (self);
146 
147  LUMIERA_RECMUTEX_SECTION (mutex_sync, &lumiera_interface_mutex)
148  {
149  while (*self)
150  {
151  TRACE (interfaceregistry, "interface %s, version %d, instance %s", (*self)->interface, (*self)->version, (*self)->name);
152  psplay_insert (lumiera_interfaceregistry, &lumiera_interfacenode_new (*self, plugin)->node, 100);
153  ++self;
154  }
155  }
156 }
157 
158 
159 void
160 lumiera_interfaceregistry_remove_interface (LumieraInterface self)
161 {
162  TRACE (interfaceregistry_dbg);
163  REQUIRE (self);
164 
165  LUMIERA_RECMUTEX_SECTION (mutex_sync, &lumiera_interface_mutex)
166  {
167  TRACE (interfaceregistry, "interface %s, version %d, instance %s", self->interface, self->version, self->name);
168  LumieraInterfacenode node = (LumieraInterfacenode) psplay_find (lumiera_interfaceregistry, self, 0);
169  REQUIRE (node->refcnt == 0, "but is %d", node->refcnt);
170 
171  lumiera_interfacenode_delete ((LumieraInterfacenode)psplay_remove (lumiera_interfaceregistry, &node->node));
172  }
173 }
174 
175 
176 void
177 lumiera_interfaceregistry_bulkremove_interfaces (LumieraInterface* self)
178 {
179  TRACE (interfaceregistry_dbg);
180  REQUIRE (self);
181 
182  LUMIERA_RECMUTEX_SECTION (mutex_sync, &lumiera_interface_mutex)
183  {
184  while (*self)
185  {
186  TRACE (interfaceregistry, "interface %s, version %d, instance %s", (*self)->interface, (*self)->version, (*self)->name);
187 
188  LumieraInterfacenode node = (LumieraInterfacenode) psplay_find (lumiera_interfaceregistry, *self, 0);
189  if (node)
190  {
191  REQUIRE (node->refcnt == 0, "but is %d", node->refcnt);
192  lumiera_interfacenode_delete ((LumieraInterfacenode) psplay_remove (lumiera_interfaceregistry, &node->node));
193  }
194  else
195  {
198 
199  WARN (interfaceregistry, "ENTRY NOT FOUND in interfaceregistry at clean-up of interface %s, instance %s"
200  , (*self)->interface
201  , (*self)->name);
202  }
203 
204  ++self;
205  }
206  }
207 }
208 
209 
210 LumieraInterfacenode
211 lumiera_interfaceregistry_interfacenode_find (const char* interface, unsigned version, const char* name)
212 {
213  TRACE (interfaceregistry_dbg);
214  struct lumiera_interface_struct cmp;
215  cmp.interface = interface;
216  cmp.version = version;
217  cmp.name = name;
218 
219  LumieraInterfacenode ret = NULL;
220 
221  LUMIERA_RECMUTEX_SECTION (mutex_sync, &lumiera_interface_mutex)
222  {
223  ret = (LumieraInterfacenode)psplay_find (lumiera_interfaceregistry, &cmp, 100);
224  }
225 
226  return ret;
227 }
228 
229 
230 LumieraInterface
231 lumiera_interfaceregistry_interface_find (const char* interface, unsigned version, const char* name)
232 {
233  return lumiera_interfaceregistry_interfacenode_find (interface, version, name)->interface;
234 }
235 
236 
237 static int
238 lumiera_interface_cmp_fn (const void* keya, const void* keyb)
239 {
240  const LumieraInterface a = (const LumieraInterface)keya;
241  const LumieraInterface b = (const LumieraInterface)keyb;
242 
243  int r = strcmp (a->interface, b->interface);
244  if (r<0)
245  return -1;
246  else if (r>0)
247  return 1;
248 
249  if (a->version < b->version)
250  return -1;
251  else if (a->version > b->version)
252  return 1;
253 
254  r = strcmp (a->name, b->name);
255  if (r<0)
256  return -1;
257  else if (r>0)
258  return 1;
259 
260  return 0;
261 }
262 
263 
264 static const void*
265 lumiera_interface_key_fn (const PSplaynode node)
266 {
267  return ((LumieraInterfacenode)node)->interface;
268 }
269 
270 /*
271 // Local Variables:
272 // mode: C
273 // c-file-style: "gnu"
274 // indent-tabs-mode: nil
275 // End:
276 */
Portable and safe wrappers around some C-Lib functions.
#define LUMIERA_RECMUTEX_SECTION(nobugflag, mtx)
Recursive Mutual exclusive section.
Definition: recmutex.h:41
PSplay psplay_destroy(PSplay self)
Destroy a splay tree Frees all elements and associated resources of a splay tree. ...
Definition: psplay.c:110
void lumiera_interface_destroy(void)
deregistering implementations of the above interface
Definition: interface.c:343
LumieraRecmutex lumiera_recmutex_destroy(LumieraRecmutex self, struct nobug_flag *flag, const struct nobug_context ctx)
Destroy a recursive mutex variable.
Definition: recmutex.c:62
Header for an interface, just the absolute necessary metadata.
Definition: interface.h:380
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:389
This header is for including and configuring NoBug.
unsigned version
major version, 0 means experimental
Definition: interface.h:386
static void lumiera_free(void *mem)
Free previously allocated memory.
Definition: safeclib.h:82
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:309
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:41
PSplaynode psplay_insert(PSplay self, PSplaynode node, int splayfactor)
Insert a element into a splay tree.
Definition: psplay.c:255
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:124
static size_t psplay_nelements(PSplay self)
Number of elements in tree.
Definition: psplay.h:112
#define LUMIERA_DIE(err)
Abort unconditionally with a &#39;Fatal Error!&#39; message.
Definition: error.h:63
PSplay psplay_new(psplay_cmp_fn cmp, psplay_key_fn key, psplay_delete_fn del)
Allocate a splay tree.
Definition: psplay.c:97
Probabilistic splay tree.
void * lumiera_malloc(size_t size)
Allocate memory.
Definition: safeclib.c:122
const char * interface
name of the interface (type)
Definition: interface.h:383
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:349
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:131
ElementBoxWidget::Config::Qualifier name(string id)
define the name-ID displayed in the caption