mirror of
https://git.rwth-aachen.de/acs/public/villas/node/
synced 2025-03-09 00:00:00 +01:00
plugin: use Nifty Counter Idiom to intialize plugin list
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
This commit is contained in:
parent
151abd2fd5
commit
68c9f08457
2 changed files with 38 additions and 4 deletions
|
@ -74,8 +74,29 @@ public:
|
|||
enum state state;
|
||||
|
||||
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 *>;
|
||||
static std::list<Plugin *> pluginList;
|
||||
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
|
||||
};
|
||||
|
||||
} // namespace villas
|
||||
|
|
|
@ -25,7 +25,9 @@
|
|||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <iostream>
|
||||
|
||||
#include <new>
|
||||
#include <type_traits>
|
||||
|
||||
#include "plugin.hpp"
|
||||
|
||||
|
@ -33,16 +35,27 @@
|
|||
namespace villas {
|
||||
|
||||
// list of all registered plugins
|
||||
Plugin::PluginList Plugin::pluginList;
|
||||
Plugin::PluginList&
|
||||
Plugin::pluginList = reinterpret_cast<Plugin::PluginList&>(Plugin::pluginListBuffer);
|
||||
|
||||
Plugin::PluginListBuffer
|
||||
Plugin::pluginListBuffer;
|
||||
|
||||
// relies on zero initialization
|
||||
int Plugin::pluginListNiftyCounter;
|
||||
|
||||
|
||||
Plugin::Plugin() :
|
||||
pluginType(Plugin::Type::Unknown),
|
||||
name(""),
|
||||
description(""),
|
||||
path(""),
|
||||
pluginType(Plugin::Type::Unknown),
|
||||
state(STATE_INITIALIZED)
|
||||
{
|
||||
// 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);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue