Line data Source code
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 >&
26 24 : PluginFactory< PluginT, InitDataT >::getInstance()
27 : {
28 24 : static PluginFactory< PluginT, InitDataT > factory;
29 24 : return factory;
30 : }
31 :
32 : template< typename PluginT, typename InitDataT >
33 2 : PluginFactory< PluginT, InitDataT >::~PluginFactory()
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 2 : }
41 :
42 : template< typename PluginT, typename InitDataT >
43 8 : PluginT* PluginFactory< PluginT, InitDataT >::create( const InitDataT& initData )
44 : {
45 12 : BOOST_FOREACH( PluginHolder& plugin, _plugins )
46 8 : if( plugin.handles( initData ))
47 8 : return plugin.constructor( initData );
48 :
49 4 : LBTHROW( std::runtime_error( "No plugin implementation available for " +
50 : boost::lexical_cast<std::string>( initData )));
51 : }
52 :
53 : template< typename PluginT, typename InitDataT >
54 8 : void PluginFactory< PluginT, InitDataT >::register_(
55 : const Plugin< PluginT, InitDataT >& plugin )
56 : {
57 8 : _plugins.push_back( plugin );
58 8 : }
59 :
60 : template< typename PluginT, typename InitDataT >
61 : bool PluginFactory< PluginT, InitDataT >::deregister(
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 >
74 8 : void PluginFactory< PluginT, InitDataT >::deregisterAll()
75 : {
76 8 : _plugins.clear();
77 8 : BOOST_FOREACH( typename PluginMap::value_type& plugin, _libraries )
78 0 : delete plugin.first;
79 8 : _libraries.clear();
80 8 : }
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 >
107 : void PluginFactory< PluginT, InitDataT >::_load( DSOs& result,
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 >
167 : bool PluginFactory< PluginT, InitDataT >::unload( DSO* dso )
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 : }
|