Lumiera 0.pre.04~rc.1
»edit your freedom«
Loading...
Searching...
No Matches
interface.c
Go to the documentation of this file.
1/*
2 Interface - Lumiera interface handling
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
24#include "include/logging.h"
25
26#include "lib/recmutex.h"
27#include "lib/safeclib.h"
28
29#include "common/plugin.h"
30#include "common/interface.h"
31
33
34#include <nobug.h>
35
36
37
40
43
44static void
46
47
49lumiera_interface_open (const char* interface, unsigned version, size_t minminorversion, const char* name)
50{
52 TRACE (interface, "%s", name);
53 WARN_IF (version == 0, interface, "opening experimental interface: %s_%d_%s", interface, version, name);
54
56 {
57 self = lumiera_interfaceregistry_interfacenode_find (interface, version, name);
58
59 if (!self)
60 {
61 UNIMPLEMENTED ("query plugindb and load plugin if exists");
62 }
63
64 if (self)
65 {
66 if (minminorversion > self->interface->size)
67 {
68 UNIMPLEMENTED ("set error");
69 self = NULL;
70 }
71 else
72 {
74 }
75 }
76 }
77 return self->interface;
78}
79
80
81static void
83{
84 /* push a dependency on the dependency array, allocate or resize it on demand */
85 TRACE (interface_dbg, "%s %s", parent->interface->name, child->interface->name);
86
87 /* no dependencies recorded yet, allocate a first block for 4 pointers */
88 if (!parent->deps_size)
89 parent->deps = lumiera_calloc (parent->deps_size = 4, sizeof (LumieraInterfacenode));
90
91 size_t sz = parent->deps_size;
92 LumieraInterfacenode* itr = parent->deps;
93
94 while (*itr)
95 {
96 --sz;
97 ++itr;
98 if (sz == 1)
99 {
100 /* block too small, realloc it with twice its size, we keep the block NULL terminated */
101 sz = parent->deps_size + 1;
102 parent->deps_size *= 2;
103 parent->deps = lumiera_realloc (parent->deps, parent->deps_size * sizeof (LumieraInterface));
104 itr = parent->deps + sz - 2;
105 memset (itr, 0, sz * sizeof (LumieraInterface));
106 }
107 }
108
109 /* found free element, store self in dependencies */
110 *itr = child;
111}
112
113
114static void
116{
117 /* increment refcount for all non-cyclic dependencies recursively */
118 if (self->deps)
119 {
120 TRACE (interface_dbg, "%s %d", self->interface->name, self->refcnt);
121 for (LumieraInterfacenode* dep = self->deps; *dep; ++dep)
122 {
123 TRACE (interface_dbg, "loop %s", (*dep)->interface->name);
124 int cycle = 0;
125 for (LumieraInterfacenode itr = *stack; itr; itr = itr->lnk)
126 {
127 if (itr == *dep)
128 {
129 TRACE (interface_dbg, "CYCLE");
130 cycle = 1;
131 break;
132 }
133 }
134
135 if (!cycle)
136 {
137 if ((*dep)->plugin)
138 lumiera_plugin_refinc ((*dep)->plugin);
139 ++(*dep)->refcnt;
140 (*dep)->lnk = *stack;
141 *stack = *dep;
142
143 depwalk (*dep, stack);
144
145 *stack = (*dep)->lnk;
146 (*dep)->lnk = NULL;
147 }
148 }
149 }
150}
151
152
155{
156 static unsigned collect_dependencies = 0;
157 static LumieraInterfacenode stack = NULL;
158
159 /*
160 OK, this got little more complicated than it should be,
161 but finally it handles any kind of cross dependencies between interfaces gracefully
162 */
163
164 if (self)
165 {
166 TRACE (interface_dbg, "%s %d (%s)", self->interface->name, self->refcnt, stack?stack->interface->name:"");
167
169 {
170 /* discover cycles, cycles don't refcount! */
171 int cycle = 0;
172
173 for (LumieraInterfacenode itr = stack; itr; itr = itr->lnk)
174 {
175 if (itr == self)
176 {
177 TRACE (interface_dbg, "CYCLE");
178 cycle = 1;
179 break;
180 }
181 }
182
183 /* 'stack' is ensured to be !NULL here because only a parent call can switch collect_dependencies on */
184 if (collect_dependencies)
185 push_dependency (stack, self);
186
187 if (!cycle)
188 {
189 if (self->plugin)
190 lumiera_plugin_refinc (self->plugin);
191 ++self->refcnt;
192
193 self->lnk = stack;
194 stack = self;
195 int collect_dependencies_bak = collect_dependencies;
196
197 if (self->refcnt == 1)
198 {
199 /* first opening, run acquire, recursive opening shall record its dependencies here */
200 if (self->interface->acquire)
201 {
202 TRACE (interface_dbg, "Acquire %s", self->interface->name);
203 collect_dependencies = self->deps?0:1;
204 self->interface = self->interface->acquire (self->interface, lumiera_interface_interface);
205 }
206 }
207 else
208 {
209 /* opening again recurse dependencies */
210 collect_dependencies = 0;
211 depwalk (self, &stack);
212 }
213
214 collect_dependencies = collect_dependencies_bak;
215 stack = self->lnk;
216 self->lnk = NULL;
217 }
218 }
219 }
220
221 return self;
222}
223
224
225void
235
236
237unsigned
239{
240 if (self && iname && !strcmp (self->interface, iname))
241 return self->version;
242
243 return ~0;
244}
245
246
247/* internal function, does no locking! */
248static void
250{
251 static LumieraInterfacenode stack = NULL;
252
253 if (!self)
254 return;
255
256 TRACE (interface, "%s %d (%s)", self->interface->name, self->refcnt, stack?stack->interface->name:"");
257
258 REQUIRE (self->refcnt);
259
260 int cycle = 0;
261
262 for (LumieraInterfacenode itr = stack; itr; itr = itr->lnk)
263 {
264 if (itr == self)
265 {
266 TRACE (interface_dbg, "CYCLE");
267 cycle = 1;
268 break;
269 }
270 }
271
272 if (!cycle)
273 {
274 self->lnk = stack;
275 stack = self;
276
277 if (self->refcnt == 1)
278 {
279 if (self->interface->release)
280 {
281 TRACE (interface_dbg, "Release %s", self->interface->name);
282 self->interface->release (self->interface);
283 }
284 }
285 else
286 {
287 if (self->deps)
288 {
289 TRACE (interface_dbg, "Recurse %s %d", self->interface->name, self->refcnt);
290
291 for (LumieraInterfacenode* dep = self->deps; *dep; ++dep)
293 }
294 }
295
296 stack = self->lnk;
297 self->lnk = NULL;
298 if (self->plugin)
299 lumiera_plugin_refdec (self->plugin);
300 --self->refcnt;
301 }
302}
303
310 LUMIERA_INTERFACE_DEFINE (lumieraorg_interface, 0,
311 lumieraorg_interface,
312 NULL,
313 NULL,
314 NULL,
315 LUMIERA_INTERFACE_MAP (open,
317 LUMIERA_INTERFACE_MAP (close,
319 LUMIERA_INTERFACE_MAP (version,
321 )
322 )
323
324
325void
327{
330 lumiera_interface_open ("lumieraorg_interface", 0, 0, "lumieraorg_interface");
331}
332
333void
339
340/*
341// Local Variables:
342// mode: C
343// c-file-style: "gnu"
344// indent-tabs-mode: nil
345// End:
346*/
LumieraInterface lumiera_interface_open(const char *interface, unsigned version, size_t minminorversion, const char *name)
Open an interface by version and name.
Definition interface.c:49
static void lumiera_interfacenode_close(LumieraInterfacenode self)
Definition interface.c:249
static LumieraInterfacenode lumiera_interface_open_interfacenode(LumieraInterfacenode self)
Definition interface.c:154
void lumiera_interface_destroy(void)
deregistering implementations of the above interface
Definition interface.c:334
void lumiera_interface_close(LumieraInterface self)
Close an interface after use.
Definition interface.c:226
unsigned lumiera_interface_version(LumieraInterface self, const char *iname)
Runtime check for interface type and version.
Definition interface.c:238
static void depwalk(LumieraInterfacenode self, LumieraInterfacenode *stack)
Definition interface.c:115
LumieraInterface lumiera_interface_interface
the mother of all interfaces
Definition interface.c:39
static void push_dependency(LumieraInterfacenode parent, LumieraInterfacenode child)
Definition interface.c:82
Lumiera interface macros and structures.
#define LUMIERA_INTERFACE_UNREGISTEREXPORTED
Unregister all exported interfaces when not a plugin This is a no-op when LUMIERA_PLUGIN is defined,...
Definition interface.h:330
#define LUMIERA_EXPORT(...)
Generate interface container suitable for enumerating interfaces.
Definition interface.h:273
#define LUMIERA_INTERFACE_REGISTEREXPORTED
Register all exported interfaces when not a plugin This is a no-op when LUMIERA_PLUGIN is defined,...
Definition interface.h:324
lumiera_interface * LumieraInterface
Definition interface.h:355
void lumiera_interface_init(void)
registering implementations of the above interface
LumieraInterfacenode lumiera_interfaceregistry_interfacenode_find(const char *interface, unsigned version, const char *name)
lumiera_recmutex lumiera_interface_mutex
PSplay lumiera_interfaceregistry
Global registry for interfaces (extension points).
lumiera_interfacenode * LumieraInterfacenode
return NULL
Definition llist.h:586
This header is for including and configuring NoBug.
void lumiera_plugin_refdec(LumieraPlugin self)
Definition plugin.c:179
void lumiera_plugin_refinc(LumieraPlugin self)
Definition plugin.c:172
Lumiera plugins define 'interfaces' as shown in interface.h, the plugin system handles the loading of...
PSplaynode psplay_find(PSplay self, const void *key, int splayfactor)
Find a element in a splay tree.
Definition psplay.c:300
Mutual exclusion locking, header.
#define LUMIERA_RECMUTEX_SECTION(nobugflag, mtx)
Recursive Mutual exclusive section.
Definition recmutex.h:32
void * lumiera_calloc(size_t n, size_t size)
Allocate cleared memory for an array.
Definition safeclib.c:130
void * lumiera_realloc(void *ptr, size_t size)
Change the size of a memory block.
Definition safeclib.c:149
Portable and safe wrappers around some C-Lib functions.