Lunchbox  1.13.0
Multi-threaded C++ toolbox library for all application developers creating high-performance multi-threaded programs.
pluginFactory.ipp
1 
2 /* Copyright (c) 2013-2015, 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 {
24 template< typename PluginT, typename InitDataT >
25 PluginFactory< PluginT, InitDataT >&
27 {
29  return factory;
30 }
31 
32 template< typename PluginT, typename InitDataT >
34 {
35  // Do not do this: dtor is called in atexit(), at which point the other DSOs
36  // might be unloaded already, causing dlclose to trip. It's pointless
37  // anyways, we're in atexit, so the OS will dispose the DSOs for us anyways.
38  // Let's call this a static deinitializer fiasco.
39  // deregisterAll(); // unload the DSO libraries
40 }
41 
42 template< typename PluginT, typename InitDataT >
43 PluginT* PluginFactory< PluginT, InitDataT >::create( const InitDataT& initData )
44 {
45  BOOST_FOREACH( PluginHolder& plugin, _plugins )
46  if( plugin.handles( initData ))
47  return plugin.constructor( initData );
48 
49  LBTHROW( std::runtime_error( "No plugin implementation available for " +
50  boost::lexical_cast<std::string>( initData )));
51 }
52 
53 template< typename PluginT, typename InitDataT >
55  const Plugin< PluginT, InitDataT >& plugin )
56 {
57  _plugins.push_back( plugin );
58 }
59 
60 template< typename PluginT, typename InitDataT >
62  const Plugin< PluginT, InitDataT >& plugin )
63 {
64  typename Plugins::iterator i =
65  std::find( _plugins.begin(), _plugins.end(), plugin );
66  if( i == _plugins.end( ))
67  return false;
68 
69  _plugins.erase( i );
70  return true;
71 }
72 
73 template< typename PluginT, typename InitDataT >
75 {
76  _plugins.clear();
77  BOOST_FOREACH( typename PluginMap::value_type& plugin, _libraries )
78  delete plugin.first;
79  _libraries.clear();
80 }
81 
82 template< typename PluginT, typename InitDataT >
83 DSOs PluginFactory< PluginT, InitDataT >::load( const int version,
84  const Strings& paths,
85  const std::string& pattern )
86 {
87  Strings unique = paths;
88  lunchbox::usort( unique );
89 
90  DSOs result;
91  BOOST_FOREACH( const std::string& path, unique )
92  _load( result, version, path, pattern );
93  return result;
94 }
95 
96 template< typename PluginT, typename InitDataT >
97 DSOs PluginFactory< PluginT, InitDataT >::load( const int version,
98  const std::string& path,
99  const std::string& pattern )
100 {
101  DSOs loaded;
102  _load( loaded, version, path, pattern );
103  return loaded;
104 }
105 
106 template< typename PluginT, typename InitDataT >
108  const int version,
109  const std::string& path,
110  const std::string& pattern )
111 {
112 #ifdef _MSC_VER
113  const std::string regex( pattern + ".dll" );
114 #elif __APPLE__
115  const std::string regex( "lib" + pattern + ".dylib" );
116 #else
117  const std::string regex( "lib" + pattern + ".so" );
118 #endif
119  const Strings& libs = searchDirectory( path, regex );
120 
121  BOOST_FOREACH( const std::string& lib, libs )
122  {
123  lunchbox::DSO* dso = new lunchbox::DSO( path + "/" + lib );
124  if( !dso->isOpen())
125  {
126  delete dso;
127  continue;
128  }
129 
130  typedef int( *GetVersion_t )();
131  typedef bool( *Register_t )();
132 
133  GetVersion_t getVersion = dso->getFunctionPointer< GetVersion_t >(
134  "LunchboxPluginGetVersion" );
135  Register_t registerFunc = dso->getFunctionPointer< Register_t >(
136  "LunchboxPluginRegister" );
137  const bool matchesVersion = getVersion && (getVersion() == version);
138 
139  if( !getVersion || !registerFunc || !matchesVersion )
140  {
141  LBERROR << "Disable " << lib << ": "
142  << ( getVersion ? "" :
143  "Symbol for LunchboxPluginGetVersion missing " )
144  << ( registerFunc ? "" :
145  "Symbol for LunchboxPluginRegister missing " );
146  if( getVersion && !matchesVersion )
147  LBERROR << "Plugin version " << getVersion() << " does not"
148  << " match application version " << version;
149  LBERROR << std::endl;
150 
151  delete dso;
152  continue;
153  }
154 
155  if( registerFunc( ))
156  {
157  _libraries.insert( std::make_pair( dso, _plugins.back( )));
158  result.push_back( dso );
159  LBINFO << "Enabled plugin " << lib << std::endl;
160  }
161  else
162  delete dso;
163  }
164 }
165 
166 template< typename PluginT, typename InitDataT >
168 {
169  typename PluginMap::iterator i = _libraries.find( dso );
170  if( i == _libraries.end( ))
171  return false;
172 
173  delete i->first;
174  const bool ret = deregister( i->second );
175  _libraries.erase( i );
176  return ret;
177 }
178 }
Helper to access dynamic shared objects (DSO)
Definition: dso.h:35
void * getFunctionPointer(const std::string &functionName) const
DSOs load(const int version, const std::string &path, const std::string &pattern)
Load all compatible plugin libraries from a directory matching a pattern.
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.
STL namespace.
PluginT * create(const InitDataT &initData)
Create a plugin instance.
#define LBINFO
Output an informational message to the per-thread Log.
Definition: log.h:192
Factory for Plugin classes.
Definition: pluginFactory.h:59
bool isOpen() const
#define LBERROR
Output an error message to the per-thread Log stream.
Definition: log.h:187
bool deregister(const Plugin< PluginT, InitDataT > &plugin)
Deregister a plugin type.
bool unload(DSO *dso)
Unload and deregister a previously loaded plugin.
Abstraction layer and common utilities for multi-threaded programming.
Definition: algorithm.h:32
Manages a class deriving from a PluginT interface.
Definition: plugin.h:47
static PluginFactory & getInstance()
Get the single class instance.
void register_(const Plugin< PluginT, InitDataT > &plugin)
Register a plugin type.
void usort(C &c)
Uniquely sort and eliminate duplicates in a container.
Definition: algorithm.h:62
#define LBTHROW(exc)
Log a std::exception if topic LOG_EXCEPTION is set before throwing exception.
Definition: log.h:218
void deregisterAll()
Unregister all plugin types.