Line data Source code
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 : {
24 12 : template< typename T > PluginFactory< T >& PluginFactory< T >::getInstance()
25 : {
26 12 : static PluginFactory< T > factory;
27 12 : return factory;
28 : }
29 :
30 1 : 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 1 : }
38 :
39 : template< typename T >
40 4 : T* PluginFactory< T >::create( const typename T::InitDataT& initData )
41 : {
42 6 : for( auto& plugin : _plugins )
43 4 : if( plugin.handles( initData ))
44 4 : return plugin.construct( initData );
45 :
46 2 : LBTHROW( std::runtime_error( "No plugin implementation available for " +
47 : std::to_string( initData )));
48 : }
49 :
50 : template< typename T >
51 4 : void PluginFactory< T >::register_( const PluginT& plugin )
52 : {
53 4 : _plugins.push_back( plugin );
54 4 : }
55 :
56 : template< typename T >
57 : bool PluginFactory< T >::deregister( const PluginT& plugin )
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 4 : template< typename T > void PluginFactory< T >::deregisterAll()
69 : {
70 4 : _plugins.clear();
71 4 : for( auto& plugin : _libraries )
72 0 : delete plugin.first;
73 4 : _libraries.clear();
74 4 : }
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 : }
|