MarlinMT  0.1.0
PluginManager.h
Go to the documentation of this file.
1 #ifndef MARLINMT_PLUGINMANAGER_h
2 #define MARLINMT_PLUGINMANAGER_h 1
3 
4 // -- std headers
5 #include <map>
6 #include <string>
7 #include <mutex>
8 #include <any>
9 #include <memory>
10 #include <vector>
11 #include <functional>
12 #include <filesystem>
13 
14 // -- marlinmt headers
15 #include "marlinmt/Exceptions.h"
16 #include "marlinmt/Logging.h"
17 
18 // Helper macros to declare plugins
19 // R. Ete: Impossible to make a function outside of main.
20 // The workaround is to create a structure on-the-fly that make the function call in the constructor
21 #define MARLINMT_DECLARE_PLUGIN( Base, Class ) MARLINMT_DECLARE_PLUGIN_NAME( Base, Class, #Class )
22 
23 #define MARLINMT_DECLARE_PLUGIN_NAME( Base, Class, NameStr ) \
24  namespace marlinmt_plugins { \
25  struct PluginDeclaration_##Class { \
26  PluginDeclaration_##Class() { \
27  marlinmt::PluginManager::instance().registerPlugin<Base, Class>( NameStr, false ) ; \
28  } \
29  }; \
30  static PluginDeclaration_##Class __instance_##Class ; \
31  }
32 
33 // processor plugin declaration
34 #define MARLINMT_DECLARE_PROCESSOR( Class ) namespace { \
35  static const auto __processortype__ = Class().type() ; \
36  MARLINMT_DECLARE_PLUGIN_NAME( marlinmt::Processor, Class, __processortype__ ) \
37 }
38 
39 // geometry plugin declaration
40 #define MARLINMT_DECLARE_GEOMETRY( Class ) MARLINMT_DECLARE_PLUGIN( marlinmt::GeometryPlugin, Class )
41 #define MARLINMT_DECLARE_GEOMETRY_NAME( Class, NameStr ) MARLINMT_DECLARE_PLUGIN_NAME( marlinmt::GeometryPlugin, Class, NameStr )
42 
43 // data source plugin declaration
44 #define MARLINMT_DECLARE_DATASOURCE( Class ) MARLINMT_DECLARE_PLUGIN( marlinmt::DataSourcePlugin, Class )
45 #define MARLINMT_DECLARE_DATASOURCE_NAME( Class, NameStr ) MARLINMT_DECLARE_PLUGIN_NAME( marlinmt::DataSourcePlugin, Class, NameStr )
46 
47 // config reader plugin declaration
48 #define MARLINMT_DECLARE_CONFIG_READER( Class ) MARLINMT_DECLARE_PLUGIN( marlinmt::ConfigReader, Class )
49 #define MARLINMT_DECLARE_CONFIG_READER_NAME( Class, NameStr ) MARLINMT_DECLARE_PLUGIN_NAME( marlinmt::ConfigReader, Class, NameStr )
50 
51 // config writer plugin declaration
52 #define MARLINMT_DECLARE_CONFIG_WRITER( Class ) MARLINMT_DECLARE_PLUGIN( marlinmt::ConfigWriter, Class )
53 #define MARLINMT_DECLARE_CONFIG_WRITER_NAME( Class, NameStr ) MARLINMT_DECLARE_PLUGIN_NAME( marlinmt::ConfigWriter, Class, NameStr )
54 
55 namespace marlinmt {
56 
64  class PluginManager {
65  public:
66  // typedefs
67  using FactoryFunction = std::any ;
68  template <typename B>
69  using FactoryFunctionT = std::function<std::unique_ptr<B>()> ;
70  // typedef void* PluginPtr ;
71  // typedef std::function<PluginPtr()> FactoryFunction ;
72 
73  struct FactoryData {
75  std::string _libraryName {} ;
78  };
79 
80  typedef std::map<std::string, FactoryData> PluginFactoryMap ;
81  typedef std::map<std::filesystem::path, void*> LibraryList ;
83  typedef std::recursive_mutex mutex_type ;
84  typedef std::lock_guard<mutex_type> lock_type ;
85 
86  private:
87  PluginManager(const PluginManager &) = delete ;
88  PluginManager& operator=(const PluginManager &) = delete ;
89  ~PluginManager() = default ;
90 
94  PluginManager() ;
95 
96  public:
100  static PluginManager &instance() ;
101 
115  template <typename B, typename T>
116  void registerPlugin( const std::string &name, bool ignoreDuplicate = false ) ;
117 
126  void registerPlugin( const std::string &name, FactoryFunction factoryFunction, bool ignoreDuplicate = false ) ;
127 
133  void loadLibrary( const std::string &library ) ;
134 
140  void loadLibraries( const std::vector<std::string> &libraries ) ;
141 
145  std::vector<std::string> pluginNames() const ;
146 
150  template <typename Base>
151  std::vector<std::string> pluginNames() const ;
152 
158  bool pluginRegistered( const std::string &name ) const ;
159 
168  template <typename T>
169  std::unique_ptr<T> create( const std::string &name ) const ;
170 
174  void dump() const ;
175 
179  Logger logger() const ;
180 
181  private:
183  void doLoadLibrary( const std::string &library ) ;
184 
185  private:
187  PluginFactoryMap _pluginFactories {} ;
189  LibraryList _libraries {} ;
191  mutable Logger _logger {nullptr} ;
193  mutable mutex_type _mutex {} ;
195  std::string _currentLibrary {} ;
196  };
197 
198  //--------------------------------------------------------------------------
199  //--------------------------------------------------------------------------
200 
201  template <typename B, typename T>
202  inline void PluginManager::registerPlugin( const std::string &name, bool ignoreDuplicate ) {
203  FactoryFunctionT<B> factoryFunction = []() -> std::unique_ptr<B> {
204  return std::make_unique<T>() ;
205  };
206  std::any anyFactory = factoryFunction ;
207  registerPlugin( name, anyFactory, ignoreDuplicate ) ;
208  }
209 
210  //--------------------------------------------------------------------------
211 
212  template <typename Base>
213  inline std::vector<std::string> PluginManager::pluginNames() const {
214  std::vector<std::string> names {} ;
215  for( auto &p : _pluginFactories ) {
216  try {
217  auto factory = std::any_cast<FactoryFunctionT<Base>>( p.second._factory ) ;
218  names.push_back( p.first ) ;
219  }
220  catch(const std::bad_any_cast& e) {
221  continue ;
222  }
223  }
224  return names ;
225  }
226 
227  //--------------------------------------------------------------------------
228 
229  template <typename T>
230  inline std::unique_ptr<T> PluginManager::create( const std::string &name ) const {
231  lock_type lock( _mutex ) ;
232  auto factoryIter = _pluginFactories.find( name ) ;
233  // plugin not found ?
234  if ( _pluginFactories.end() == factoryIter ) {
235  return nullptr ;
236  }
237  try {
238  auto factory = std::any_cast<FactoryFunctionT<T>>( factoryIter->second._factory ) ;
239  return factory() ;
240  }
241  catch(const std::bad_any_cast& e) {
242  return nullptr ;
243  }
244  }
245 
246 } // end namespace marlinmt
247 
248 #endif
std::function< std::unique_ptr< B >()> FactoryFunctionT
Definition: PluginManager.h:69
Logger _logger
The plugin manager logger.
std::string _libraryName
The name of the library of the plugin.
Definition: PluginManager.h:75
void doLoadLibrary(const std::string &library)
the workhorse !
std::recursive_mutex mutex_type
Definition: PluginManager.h:83
void loadLibrary(const std::string &library)
Load a shared library to populate the list of plugins.
FactoryFunction _factory
The plugin factory.
Definition: PluginManager.h:77
Logging::Logger Logger
Definition: PluginManager.h:82
std::map< std::string, FactoryData > PluginFactoryMap
Definition: PluginManager.h:80
std::string _currentLibrary
The current library being loaded.
bool pluginRegistered(const std::string &name) const
Whether the plugin with of a given name is registered.
void loadLibraries(const std::vector< std::string > &libraries)
Load shared libraries to populate the list of plugins.
std::vector< std::string > pluginNames() const
Get all registered plugin name.
mutex_type _mutex
The synchronization mutex.
PluginManager & operator=(const PluginManager &)=delete
void dump() const
Dump plugin manager content in console.
Logger logger() const
Get the plugin manager logger.
std::shared_ptr< streamlog::logstreamT< mutex_type > > Logger
Definition: Logging.h:73
PluginManager()
Constructor.
std::unique_ptr< T > create(const std::string &name) const
Create a new plugin instance.
void registerPlugin(const std::string &name, bool ignoreDuplicate=false)
Register a new plugin to the manager.
PluginManager singleton class Responsible for loading shared libraries and collecting processor facto...
Definition: PluginManager.h:64
std::lock_guard< mutex_type > lock_type
Definition: PluginManager.h:84
LibraryList _libraries
The list of loaded libraries.
static PluginManager & instance()
Get the plugin manager instance.
PluginFactoryMap _pluginFactories
The map of plugin factories.
std::map< std::filesystem::path, void * > LibraryList
Definition: PluginManager.h:81