LCOV - code coverage report
Current view: top level - lunchbox - pluginFactory.ipp (source / functions) Hit Total Coverage
Test: Lunchbox Lines: 18 19 94.7 %
Date: 2016-03-29 17:09:06 Functions: 10 10 100.0 %

          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             : }

Generated by: LCOV version 1.11