mirror of
https://git.rwth-aachen.de/acs/public/villas/node/
synced 2025-03-09 00:00:00 +01:00
plugin: rewrite
This commit is contained in:
parent
75f994f61d
commit
3d7eb963ec
2 changed files with 101 additions and 115 deletions
|
@ -32,82 +32,106 @@
|
|||
#include <villas/common.h>
|
||||
|
||||
namespace villas {
|
||||
namespace plugin {
|
||||
|
||||
/* Forward declarations */
|
||||
class Plugin;
|
||||
|
||||
template<typename T = Plugin>
|
||||
using List = std::list<T *>;
|
||||
|
||||
class Registry {
|
||||
|
||||
protected:
|
||||
static List<> *plugins;
|
||||
|
||||
class Plugin {
|
||||
public:
|
||||
|
||||
enum class Type {
|
||||
Unknown,
|
||||
FpgaIp,
|
||||
FpgaCard,
|
||||
Gpu
|
||||
};
|
||||
static SpdLogger
|
||||
getLogger()
|
||||
{ return loggerGetOrCreate("plugin:registry"); }
|
||||
|
||||
Plugin(Type type, const std::string& name);
|
||||
virtual ~Plugin();
|
||||
static void dump();
|
||||
|
||||
// copying a plugin doesn't make sense, so explicitly deny it
|
||||
Plugin(Plugin const&) = delete;
|
||||
void operator=(Plugin const&) = delete;
|
||||
static void add(Plugin *p)
|
||||
{
|
||||
if (plugins == nullptr)
|
||||
plugins = new List<>;
|
||||
|
||||
int load();
|
||||
plugins->push_back(p);
|
||||
}
|
||||
|
||||
static void remove(Plugin *p)
|
||||
{
|
||||
plugins->remove(p);
|
||||
}
|
||||
|
||||
template<typename T = Plugin>
|
||||
static T *
|
||||
lookup(const std::string &name)
|
||||
{
|
||||
for (Plugin *p : *plugins) {
|
||||
T *t = dynamic_cast<T *>(p);
|
||||
if (!t || t->name != name)
|
||||
continue;
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template<typename T = Plugin>
|
||||
static List<T>
|
||||
lookup()
|
||||
{
|
||||
List<T> list;
|
||||
|
||||
for (Plugin *p : *plugins) {
|
||||
T *t = dynamic_cast<T *>(p);
|
||||
if (t)
|
||||
list.push_back(t);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
};
|
||||
|
||||
class Loader {
|
||||
|
||||
public:
|
||||
int load(const std::string &path);
|
||||
int unload();
|
||||
|
||||
virtual int parse(json_t *cfg);
|
||||
};
|
||||
|
||||
class Plugin {
|
||||
|
||||
friend plugin::Registry;
|
||||
|
||||
public:
|
||||
Plugin(const std::string& name, const std::string &desc);
|
||||
virtual ~Plugin();
|
||||
|
||||
// copying a plugin doesn't make sense, so explicitly deny it
|
||||
Plugin(Plugin const&) = delete;
|
||||
void operator=(Plugin const&) = delete;
|
||||
|
||||
virtual void dump();
|
||||
|
||||
static void
|
||||
dumpList();
|
||||
std::string getName();
|
||||
std::string getDescription();
|
||||
|
||||
/// Find plugin by type and (optional if empty) by name. If more match, it
|
||||
/// is not defined which one will be returned.
|
||||
static Plugin *
|
||||
lookup(Type type, std::string name);
|
||||
|
||||
/// Get all plugins of a given type.
|
||||
static std::list<Plugin*>
|
||||
lookup(Type type);
|
||||
|
||||
// TODO: check if this makes sense! (no intermediate plugins)
|
||||
bool
|
||||
operator==(const Plugin& other) const;
|
||||
|
||||
Type pluginType;
|
||||
protected:
|
||||
std::string name;
|
||||
std::string description;
|
||||
std::string path;
|
||||
void *handle;
|
||||
enum state state;
|
||||
|
||||
protected:
|
||||
static SpdLogger
|
||||
getStaticLogger()
|
||||
{ return loggerGetOrCreate("plugin"); }
|
||||
|
||||
private:
|
||||
/* Just using a standard std::list<> to hold plugins is problematic, because
|
||||
we want to push Plugins to the list from within each Plugin's constructor
|
||||
that is executed during static initialization. Since the order of static
|
||||
initialization is undefined in C++, it may happen that a Plugin
|
||||
constructor is executed before the list could be initialized. Therefore,
|
||||
we use the Nifty Counter Idiom [1] to initialize the list ourself before
|
||||
the first usage.
|
||||
|
||||
In short:
|
||||
- allocate a buffer for the list
|
||||
- initialize list before first usage
|
||||
- (complicatedly) declaring a buffer is neccessary in order to avoid
|
||||
that the constructor of the static list is executed again
|
||||
|
||||
[1] https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Nifty_Counter
|
||||
*/
|
||||
|
||||
using PluginList = std::list<Plugin *>;
|
||||
using PluginListBuffer = typename std::aligned_storage<sizeof (Plugin::PluginList), alignof (Plugin::PluginList)>::type;
|
||||
|
||||
static PluginListBuffer pluginListBuffer; ///< buffer to hold a PluginList
|
||||
static PluginList& pluginList; ///< reference to pluginListBuffer
|
||||
static int pluginListNiftyCounter; ///< track if pluginList has been initialized
|
||||
SpdLogger
|
||||
getLogger()
|
||||
{ return loggerGetOrCreate("plugin:" + name); }
|
||||
};
|
||||
|
||||
} // namespace plugin
|
||||
} // namespace villas
|
||||
|
|
|
@ -28,41 +28,23 @@
|
|||
|
||||
#include <villas/plugin.hpp>
|
||||
|
||||
namespace villas {
|
||||
using namespace villas::plugin;
|
||||
|
||||
// list of all registered plugins
|
||||
Plugin::PluginList&
|
||||
Plugin::pluginList = reinterpret_cast<Plugin::PluginList&>(Plugin::pluginListBuffer);
|
||||
List<> * Registry::plugins;
|
||||
|
||||
Plugin::PluginListBuffer
|
||||
Plugin::pluginListBuffer;
|
||||
|
||||
// relies on zero initialization
|
||||
int Plugin::pluginListNiftyCounter;
|
||||
|
||||
|
||||
Plugin::Plugin(Type type, const std::string& name) :
|
||||
pluginType(type),
|
||||
Plugin::Plugin(const std::string& name, const std::string& desc) :
|
||||
name(name),
|
||||
description(""),
|
||||
path(""),
|
||||
state(STATE_INITIALIZED)
|
||||
description(desc)
|
||||
{
|
||||
// see comment in plugin.hpp on why we need to do this (Nifty Counter Idiom)
|
||||
if(pluginListNiftyCounter++ == 0)
|
||||
new (&pluginList) PluginList;
|
||||
|
||||
// push to global plugin list
|
||||
pluginList.push_back(this);
|
||||
Registry::add(this);
|
||||
}
|
||||
|
||||
Plugin::~Plugin()
|
||||
{
|
||||
// clean from global plugin list
|
||||
pluginList.remove(this);
|
||||
Registry::remove(this);
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
int
|
||||
Plugin::parse(json_t *cfg)
|
||||
{
|
||||
|
@ -109,52 +91,32 @@ Plugin::unload()
|
|||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
Plugin::dump()
|
||||
{
|
||||
auto logger = getStaticLogger();
|
||||
auto logger = Registry::getLogger();
|
||||
logger->info("Name: '{}' Description: '{}'", name, description);
|
||||
}
|
||||
|
||||
void
|
||||
Plugin::dumpList()
|
||||
Registry::dump()
|
||||
{
|
||||
auto logger = getStaticLogger();
|
||||
auto logger = Registry::getLogger();
|
||||
|
||||
logger->info("Registered plugins:");
|
||||
for(auto& p : pluginList) {
|
||||
logger->info(" - {}", p->name);
|
||||
for(auto p : *plugins) {
|
||||
logger->info(" - {}", p->getName());
|
||||
}
|
||||
}
|
||||
|
||||
Plugin*
|
||||
Plugin::lookup(Plugin::Type type, std::string name)
|
||||
std::string Plugin::getName()
|
||||
{
|
||||
for(auto& p : pluginList) {
|
||||
if(p->pluginType == type and (name.empty() or p->name == name))
|
||||
return p;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
return name;
|
||||
}
|
||||
|
||||
std::list<Plugin*>
|
||||
Plugin::lookup(Plugin::Type type)
|
||||
std::string Plugin::getDescription()
|
||||
{
|
||||
std::list<Plugin*> list;
|
||||
for(auto& p : pluginList) {
|
||||
if(p->pluginType == type)
|
||||
list.push_back(p);
|
||||
}
|
||||
|
||||
return list;
|
||||
return description;
|
||||
}
|
||||
|
||||
bool
|
||||
Plugin::operator==(const Plugin &other) const
|
||||
{
|
||||
return (this->pluginType == other.pluginType) and (this->name == other.name);
|
||||
}
|
||||
|
||||
} // namespace villas
|
||||
|
|
Loading…
Add table
Reference in a new issue