Lunchbox  1.15.0
Multi-threaded C++ toolbox library for all application developers creating high-performance multi-threaded programs.
pluginFactory.ipp
1 
2 /* Copyright (c) 2013-2016, EPFL/Blue Brain Project
3  * Raphael Dumusc <raphael.dumusc@epfl.ch>
4  * Stefan.Eilemann@epfl.ch
5  *
6  * This file is part of Lunchbox <https://github.com/Eyescale/Lunchbox>
7  *
8  * This library is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU Lesser General Public License version 2.1 as published
10  * by the Free Software Foundation.
11  *
12  * This library is distributed in the hope that it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14  * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
15  * details.
16  *
17  * You should have received a copy of the GNU Lesser General Public License
18  * along with this library; if not, write to the Free Software Foundation, Inc.,
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20  */
21 
22 namespace lunchbox
23 {
25 {
26  static PluginFactory< T > factory;
27  return factory;
28 }
29 
30 template< typename T > PluginFactory< T >::~PluginFactory()
31 {
32  // Do not do this: dtor is called in atexit(), at which point the other DSOs
33  // might be unloaded already, causing dlclose to trip. It's pointless
34  // anyways, we're in atexit, so the OS will dispose the DSOs for us anyways.
35  // Let's call this a static deinitializer fiasco.
36  // deregisterAll(); // unload the DSO libraries
37 }
38 
39 template< typename T >
40 T* PluginFactory< T >::create( const typename T::InitDataT& initData )
41 {
42  for( auto& plugin : _plugins )
43  if( plugin.handles( initData ))
44  return plugin.construct( initData );
45 
46  LBTHROW( std::runtime_error( "No plugin implementation available for " +
47  std::to_string( initData )));
48 }
49 
50 template< typename T >
52 {
53  _plugins.push_back( plugin );
54 }
55 
56 template< typename T >
58 {
59  typename Plugins::iterator i = std::find( _plugins.begin(), _plugins.end(),
60  plugin );
61  if( i == _plugins.end( ))
62  return false;
63 
64  _plugins.erase( i );
65  return true;
66 }
67 
68 template< typename T > void PluginFactory< T >::deregisterAll()
69 {
70  _plugins.clear();
71  for( auto& plugin : _libraries )
72  delete plugin.first;
73  _libraries.clear();
74 }
75 
76 template< typename T >
77 void PluginFactory< T >::load( const int version, const Strings& paths,
78  const std::string& pattern )
79 {
80  Strings unique = paths;
81  lunchbox::usort( unique );
82 
83  for( const auto& path : unique )
84  load( version, path, pattern );
85 }
86 
87 template< typename T >
88 void PluginFactory< T >::load( const int version, const std::string& path,
89  const std::string& pattern )
90 {
91 #ifdef _MSC_VER
92  const std::string regex( pattern + ".dll" );
93 #elif __APPLE__
94  const std::string regex( "lib" + pattern + ".dylib" );
95 #else
96  const std::string regex( "lib" + pattern + ".so" );
97 #endif
98  const Strings& libs = searchDirectory( path, regex );
99 
100  for( const auto& lib : libs )
101  {
102  lunchbox::DSO* dso = new lunchbox::DSO( path + "/" + lib );
103  if( !dso->isOpen())
104  {
105  delete dso;
106  continue;
107  }
108 
109  typedef int( *GetVersion_t )();
110  typedef bool( *Register_t )();
111 
112  GetVersion_t getVersion = dso->getFunctionPointer< GetVersion_t >(
113  "LunchboxPluginGetVersion" );
114  Register_t registerFunc = dso->getFunctionPointer< Register_t >(
115  "LunchboxPluginRegister" );
116  const bool matchesVersion = getVersion && (getVersion() == version);
117 
118  if( !getVersion || !registerFunc || !matchesVersion )
119  {
120  LBERROR << "Disable " << lib << ": "
121  << ( getVersion ? "" :
122  "Symbol for LunchboxPluginGetVersion missing " )
123  << ( registerFunc ? "" :
124  "Symbol for LunchboxPluginRegister missing " );
125  if( getVersion && !matchesVersion )
126  LBERROR << "Plugin version " << getVersion() << " does not"
127  << " match application version " << version;
128  LBERROR << std::endl;
129 
130  delete dso;
131  continue;
132  }
133 
134  if( registerFunc( ))
135  {
136  _libraries.insert( std::make_pair( dso, _plugins.back( )));
137  LBINFO << "Enabled plugin " << lib << std::endl;
138  }
139  else
140  delete dso;
141  }
142 }
143 }
Helper to access dynamic shared objects (DSO)
Definition: dso.h:35
void * getFunctionPointer(const std::string &functionName) const
void deregisterAll()
Unregister all plugin types.
std::vector< std::string > Strings
A vector of std::strings.
Definition: types.h:215
Strings searchDirectory(const std::string &directory, const std::string &pattern)
Retrieve a list of files in a directory matching a boost::regex pattern.
#define LBINFO
Output an informational message to the per-thread Log.
Definition: log.h:192
Factory for Plugin classes.
Definition: pluginFactory.h:55
#define LBTHROW(exc)
Log a std::exception if topic LOG_EXCEPTION is set before throwing exception.
Definition: log.h:218
T * create(const typename T::InitDataT &initData)
Create a plugin instance.
bool isOpen() const
void register_(const PluginT &plugin)
Register a plugin type.
#define LBERROR
Output an error message to the per-thread Log stream.
Definition: log.h:187
void load(const int version, const std::string &path, const std::string &pattern)
Load all compatible plugin libraries from a directory matching a pattern.
Abstraction layer and common utilities for multi-threaded programming.
Definition: algorithm.h:32
Manages a class deriving from a T interface.
Definition: plugin.h:47
static PluginFactory & getInstance()
Get the single class instance.
void usort(C &c)
Uniquely sort and eliminate duplicates in a container.
Definition: algorithm.h:62
bool deregister(const PluginT &plugin)
Deregister a plugin type.