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 8 : PluginT* PluginFactory< PluginT, InitDataT >::create( const InitDataT& initData )
34 : {
35 12 : BOOST_FOREACH( PluginHolder& plugin, _plugins )
36 8 : if( plugin.handles( initData ))
37 8 : return plugin.constructor( initData );
38 :
39 4 : LBTHROW( std::runtime_error( "No plugin implementation available for " +
40 : boost::lexical_cast<std::string>( initData )));
41 : }
42 :
43 : template< typename PluginT, typename InitDataT >
44 8 : void PluginFactory< PluginT, InitDataT >::register_(
45 : const Plugin< PluginT, InitDataT >& plugin )
46 : {
47 8 : _plugins.push_back( plugin );
48 8 : }
49 :
50 : template< typename PluginT, typename InitDataT >
51 : bool PluginFactory< PluginT, InitDataT >::deregister(
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 >
64 8 : void PluginFactory< PluginT, InitDataT >::deregisterAll()
65 : {
66 8 : _plugins.clear();
67 8 : BOOST_FOREACH( typename PluginMap::value_type& plugin, _libraries )
68 0 : delete plugin.first;
69 8 : _libraries.clear();
70 8 : }
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 >
97 : void PluginFactory< PluginT, InitDataT >::_load( DSOs& result,
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 >
157 : bool PluginFactory< PluginT, InitDataT >::unload( DSO* dso )
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 : }
|