Lunchbox  1.11.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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 >
33 PluginT* PluginFactory< PluginT, InitDataT >::create( const InitDataT& initData )
34 {
35  BOOST_FOREACH( PluginHolder& plugin, _plugins )
36  if( plugin.handles( initData ))
37  return plugin.constructor( initData );
38 
39  LBTHROW( std::runtime_error( "No plugin implementation available for " +
40  boost::lexical_cast<std::string>( initData )));
41 }
42 
43 template< typename PluginT, typename InitDataT >
45  const Plugin< PluginT, InitDataT >& plugin )
46 {
47  _plugins.push_back( plugin );
48 }
49 
50 template< typename PluginT, typename InitDataT >
52  const Plugin< PluginT, InitDataT >& plugin )
53 {
54  typename Plugins::iterator i =
55  std::find( _plugins.begin(), _plugins.end(), plugin );
56  if( i == _plugins.end( ))
57  return false;
58 
59  _plugins.erase( i );
60  return true;
61 }
62 
63 template< typename PluginT, typename InitDataT >
65 {
66  _plugins.clear();
67  BOOST_FOREACH( typename PluginMap::value_type& plugin, _libraries )
68  delete plugin.first;
69  _libraries.clear();
70 }
71 
72 template< typename PluginT, typename InitDataT >
73 DSOs PluginFactory< PluginT, InitDataT >::load( const int version,
74  const Strings& paths,
75  const std::string& pattern )
76 {
77  Strings unique = paths;
78  lunchbox::usort( unique );
79 
80  DSOs result;
81  BOOST_FOREACH( const std::string& path, unique )
82  _load( result, version, path, pattern );
83  return result;
84 }
85 
86 template< typename PluginT, typename InitDataT >
87 DSOs PluginFactory< PluginT, InitDataT >::load( const int version,
88  const std::string& path,
89  const std::string& pattern )
90 {
91  DSOs loaded;
92  _load( loaded, version, path, pattern );
93  return loaded;
94 }
95 
96 template< typename PluginT, typename InitDataT >
98  const int version,
99  const std::string& path,
100  const std::string& pattern )
101 {
102 #ifdef _MSC_VER
103  const std::string regex( pattern + ".dll" );
104 #elif __APPLE__
105  const std::string regex( "lib" + pattern + ".dylib" );
106 #else
107  const std::string regex( "lib" + pattern + ".so" );
108 #endif
109  const Strings& libs = searchDirectory( path, regex );
110 
111  BOOST_FOREACH( const std::string& lib, libs )
112  {
113  lunchbox::DSO* dso = new lunchbox::DSO( path + "/" + lib );
114  if( !dso->isOpen())
115  {
116  delete dso;
117  continue;
118  }
119 
120  typedef int( *GetVersion_t )();
121  typedef bool( *Register_t )();
122 
123  GetVersion_t getVersion = dso->getFunctionPointer< GetVersion_t >(
124  "LunchboxPluginGetVersion" );
125  Register_t registerFunc = dso->getFunctionPointer< Register_t >(
126  "LunchboxPluginRegister" );
127  const bool matchesVersion = getVersion && (getVersion() == version);
128 
129  if( !getVersion || !registerFunc || !matchesVersion )
130  {
131  LBERROR << "Disable " << lib << ": "
132  << ( getVersion ? "" :
133  "Symbol for LunchboxPluginGetVersion missing " )
134  << ( registerFunc ? "" :
135  "Symbol for LunchboxPluginRegister missing " );
136  if( getVersion && !matchesVersion )
137  LBERROR << "Plugin version " << getVersion() << " does not"
138  << " match application version " << version;
139  LBERROR << std::endl;
140 
141  delete dso;
142  continue;
143  }
144 
145  if( registerFunc( ))
146  {
147  _libraries.insert( std::make_pair( dso, _plugins.back( )));
148  result.push_back( dso );
149  LBINFO << "Enabled plugin " << lib << std::endl;
150  }
151  else
152  delete dso;
153  }
154 }
155 
156 template< typename PluginT, typename InitDataT >
158 {
159  typename PluginMap::iterator i = _libraries.find( dso );
160  if( i == _libraries.end( ))
161  return false;
162 
163  delete i->first;
164  const bool ret = deregister( i->second );
165  _libraries.erase( i );
166  return ret;
167 }
168 }
LUNCHBOX_API void * getFunctionPointer(const std::string &functionName) const
Helper to access dynamic shared objects (DSO)
Definition: dso.h:35
LUNCHBOX_API bool isOpen() 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:214
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
LUNCHBOX_API Strings searchDirectory(const std::string &directory, const std::string &pattern)
Retrieve a list of files in a directory matching a boost::regex pattern.
#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.
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.