1
0
Fork 0
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:
daniel-k 2017-12-06 12:08:33 +01:00
parent 151abd2fd5
commit 68c9f08457
2 changed files with 38 additions and 4 deletions

View file

@ -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

View file

@ -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);
}