WIP: new plugin.h header

This ditches the old 'proof of concept' implementation, interfaces and
plugins are internally separate now and publically only accessed over
the 'interfaces' api.

The interface registry now gets an additional 'plugin' member to
backreference plugins from interfaces.
This commit is contained in:
Christian Thaeter 2008-10-31 06:42:53 +01:00
parent 7be18d6344
commit 48778cf3d7
3 changed files with 52 additions and 104 deletions

View file

@ -53,13 +53,15 @@ key_fn (const PSplaynode node);
static LumieraInterfacenode
lumiera_interfacenode_new (LumieraInterface iface)
lumiera_interfacenode_new (LumieraInterface iface, LumieraPlugin plugin)
{
LumieraInterfacenode self = lumiera_malloc (sizeof (*self));
psplaynode_init (&self->node);
self->interface = iface;
self->refcnt = 0;
self->plugin = plugin;
FIXME ("plugin handling (refcnt, atime)");
self->lnk = NULL;
self->deps_size = 0;
self->deps = NULL;
@ -74,6 +76,7 @@ lumiera_interfacenode_delete (LumieraInterfacenode self)
if (self)
{
REQUIRE (self->refcnt == 0);
FIXME ("plugin handling");
lumiera_free (self->deps);
lumiera_free (self);
}
@ -115,7 +118,7 @@ lumiera_interfaceregistry_destroy (void)
void
lumiera_interfaceregistry_register_interface (LumieraInterface self)
lumiera_interfaceregistry_register_interface (LumieraInterface self, LumieraPlugin plugin)
{
TRACE (interfaceregistry);
REQUIRE (self);
@ -123,13 +126,13 @@ 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 (lumiera_interfaceregistry, &lumiera_interfacenode_new (self)->node, 100);
psplay_insert (lumiera_interfaceregistry, &lumiera_interfacenode_new (self, plugin)->node, 100);
}
}
void
lumiera_interfaceregistry_bulkregister_interfaces (LumieraInterface* self)
lumiera_interfaceregistry_bulkregister_interfaces (LumieraInterface* self, LumieraPlugin plugin)
{
TRACE (interfaceregistry);
REQUIRE (self);
@ -139,7 +142,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 (lumiera_interfaceregistry, &lumiera_interfacenode_new (*self)->node, 100);
psplay_insert (lumiera_interfaceregistry, &lumiera_interfacenode_new (*self, plugin)->node, 100);
++self;
}
}

View file

@ -25,6 +25,7 @@
#include "lib/psplay.h"
#include "backend/interface.h"
#include "backend/plugin.h"
#include <nobug.h>
@ -62,6 +63,10 @@ struct lumiera_interfacenode_struct
/** reference counters and link used for internal reference management */
unsigned refcnt;
/** backreference to its plugin if it comes from a plugin, else NULL */
LumieraPlugin plugin;
/** temporary used to stack interfaces when recursively opening/closing them */
LumieraInterfacenode lnk;
/** allocated size of the following deps table */
@ -84,10 +89,10 @@ lumiera_interfaceregistry_destroy (void);
void
lumiera_interfaceregistry_register_interface (LumieraInterface self);
lumiera_interfaceregistry_register_interface (LumieraInterface self, LumieraPlugin plugin);
void
lumiera_interfaceregistry_bulkregister_interfaces (LumieraInterface* self);
lumiera_interfaceregistry_bulkregister_interfaces (LumieraInterface* self, LumieraPlugin plugin);
void
lumiera_interfaceregistry_remove_interface (LumieraInterface self);

View file

@ -21,111 +21,68 @@
#ifndef LUMIERA_PLUGIN_H
#define LUMIERA_PLUGIN_H
#ifdef __cplusplus
extern "C" {
#elif 0
} /*eek, fixes emacs indenting for now*/
#endif
#include <stdlib.h>
#include <nobug.h>
#include "error.h"
#include "lib/error.h"
/**
* @file
* Plugin loader, header.
* Lumiera plugins defines 'interfaces' as shown in interface.h, the plugin system handles the loading
* of all kinds of plugins under the hood, invoked from the interface system. Anything defined here is
* called internally and should not be used by other parts of the application.
*/
NOBUG_DECLARE_FLAG (lumiera_plugin);
LUMIERA_ERROR_DECLARE(PLUGIN_DLOPEN);
NOBUG_DECLARE_FLAG (plugin);
/* tool macros*/
#define LUMIERA_INTERFACE_TYPE(name, version) struct lumiera_interface_##name##_##version
#define LUMIERA_INTERFACE_CAST(name, version) (LUMIERA_INTERFACE_TYPE(name, version)*)
/* Interface definition */
#define LUMIERA_INTERFACE(name, version, ...) \
LUMIERA_INTERFACE_TYPE(name, version) \
{ \
struct lumiera_interface interface_header_; \
__VA_ARGS__ \
}
#define LUMIERA_INTERFACE_PROTO(ret, name, params) ret (*name) params;
/* Interface instantiation */
#define LUMIERA_INTERFACE_IMPLEMENT(iname, version, name, open, close, ...) \
LUMIERA_INTERFACE_TYPE(iname, version) name##_##version = \
{ \
{ \
version, \
sizeof(LUMIERA_INTERFACE_TYPE(iname, version)), \
NULL, \
0, \
open, \
close \
}, \
__VA_ARGS__ \
}
struct lumiera_plugin_struct;
typedef struct lumiera_plugin_struct lumiera_plugin;
typedef lumiera_plugin* LumieraPlugin;
/* internally used */
struct lumiera_plugin;
/**
* This is the header for any interface exported by plugins.
* Real interfaces append their functions at the end. There are few standard functions on each Interface
* Every function is required to be implemnted.
*/
struct lumiera_interface
{
/// interface version number
unsigned version;
/// size of the full structure is used to determine the revision (adding a new function increments the size)
size_t size;
/// back reference to plugin
struct lumiera_plugin* plugin;
/// incremented for each user of this interface and decremented when closed
unsigned use_count;
/// called for each open of this interface
int (*open)(void);
/// called for each close of this interface
int (*close)(void);
};
/**
* Initialize the plugin system.
* always succeeds or aborts
*/
void
lumiera_init_plugin (void);
lumiera_pluginregistry_init (void);
/**
* Make an interface available.
* To use an interface provided by a plugin it must be opened first. It is allowed to open an interface
* more than once. Each open must be paired with a close.
* @param name name of the plugin to use.
* @param interface name of the interface to open.
* @param min_revision the size of the interface structure is used as measure of a minimal required
* revision (new functions are appended at the end)
* @return handle to the interface or NULL in case of a error. The application shall cast this handle to
* the actual interface type.
*/
struct lumiera_interface*
lumiera_interface_open (const char* plugin, const char* name, size_t min_revision);
/**
* Close an interface. Does not free associated resources
* Calling this function with self==NULL is legal. Every interface handle must be closed only once.
* @param ptr interface to be closed
* destroy the plugin system, free all resources
*/
void
lumiera_interface_close (void* self);
lumiera_pluginregistry_destroy (void);
LumieraPlugin
lumiera_plugin_load (const char* plugin);
int
lumiera_plugin_register (LumieraPlugin);
/**
* discover new plugins
* traverses the configured plugin dirs and calls the callback_load function for any plugin
* not actually loaded. If callback_load returns a plugin (and not NULL) then this is feed to
* the callback_register function.
*/
int
lumiera_plugin_discover (LumieraPlugin (*callback_load)(const char* plugin),
int (*callback_register) (LumieraPlugin));
/**
* Tries to unload a plugin.
@ -136,22 +93,5 @@ lumiera_interface_close (void* self);
int
lumiera_plugin_unload (const char* plugin);
/**
* Tries to unload plugins which are not in use.
* Calls lumiera_plugin_unload() for each Plugin which is not used for more than age seconds.
* This function might be infrequently called by the scheduler to remove things which are not needed.
* @param age timeout in seconds when to unload plugins
*/
void
lumiera_plugin_expire (time_t age);
LUMIERA_ERROR_DECLARE(PLUGIN_DLOPEN);
LUMIERA_ERROR_DECLARE(PLUGIN_HOOK);
LUMIERA_ERROR_DECLARE(PLUGIN_NFILE);
LUMIERA_ERROR_DECLARE(PLUGIN_NIFACE);
LUMIERA_ERROR_DECLARE(PLUGIN_REVISION);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* LUMIERA_PLUGIN_H */