LCOV - code coverage report
Current view: top level - lunchbox - pluginFactory.ipp (source / functions) Hit Total Coverage
Test: Lunchbox Lines: 24 25 96.0 %
Date: 2018-10-03 05:33:11 Functions: 6 6 100.0 %

          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             : template <typename T>
      25          12 : PluginFactory<T>& PluginFactory<T>::getInstance()
      26             : {
      27          12 :     static PluginFactory<T> factory;
      28          12 :     return factory;
      29             : }
      30             : 
      31             : template <typename T>
      32           1 : PluginFactory<T>::~PluginFactory()
      33             : {
      34             :     // Do not do this: dtor is called in atexit(), at which point the other DSOs
      35             :     // might be unloaded already, causing dlclose to trip. It's pointless
      36             :     // anyways, we're in atexit, so the OS will dispose the DSOs for us anyways.
      37             :     // Let's call this a static deinitializer fiasco.
      38             :     //   deregisterAll(); // unload the DSO libraries
      39           1 : }
      40             : 
      41             : template <typename T>
      42             : bool PluginFactory<T>::handles(const typename T::InitDataT& initData)
      43             : {
      44             :     for (auto& plugin : _plugins)
      45             :         if (plugin.handles(initData))
      46             :             return true;
      47             :     return false;
      48             : }
      49             : 
      50             : template <typename T>
      51           4 : T* PluginFactory<T>::create(const typename T::InitDataT& initData)
      52             : {
      53           6 :     for (auto& plugin : _plugins)
      54           4 :         if (plugin.handles(initData))
      55           4 :             return plugin.construct(initData);
      56             : 
      57           2 :     LBTHROW(std::runtime_error("No plugin implementation available for " +
      58             :                                std::to_string(initData)));
      59             : }
      60             : 
      61             : template <typename T>
      62           4 : void PluginFactory<T>::register_(const PluginT& plugin)
      63             : {
      64           4 :     _plugins.push_back(plugin);
      65           4 : }
      66             : 
      67             : template <typename T>
      68             : bool PluginFactory<T>::deregister(const PluginT& plugin)
      69             : {
      70             :     typename Plugins::iterator i =
      71             :         std::find(_plugins.begin(), _plugins.end(), plugin);
      72             :     if (i == _plugins.end())
      73             :         return false;
      74             : 
      75             :     _plugins.erase(i);
      76             :     return true;
      77             : }
      78             : 
      79             : template <typename T>
      80           4 : void PluginFactory<T>::deregisterAll()
      81             : {
      82           4 :     _plugins.clear();
      83           4 :     for (auto& plugin : _libraries)
      84           0 :         delete plugin.first;
      85           4 :     _libraries.clear();
      86           4 : }
      87             : 
      88             : template <typename T>
      89           2 : std::string PluginFactory<T>::getDescriptions() const
      90             : {
      91           2 :     std::string descriptions;
      92           5 :     for (const auto& plugin : _plugins)
      93           6 :         descriptions +=
      94           3 :             (descriptions.empty() ? "" : "\n\n") + plugin.getDescription();
      95           2 :     return descriptions;
      96             : }
      97             : 
      98             : template <typename T>
      99             : void PluginFactory<T>::load(const int version, const Strings& paths,
     100             :                             const std::string& pattern)
     101             : {
     102             :     Strings unique = paths;
     103             :     lunchbox::usort(unique);
     104             : 
     105             :     for (const auto& path : unique)
     106             :         load(version, path, pattern);
     107             : }
     108             : 
     109             : template <typename T>
     110             : void PluginFactory<T>::load(const int version, const std::string& path,
     111             :                             const std::string& pattern)
     112             : {
     113             : #ifdef _MSC_VER
     114             :     const std::string regex(pattern + ".dll");
     115             : #elif __APPLE__
     116             :     const std::string regex("lib" + pattern + ".dylib");
     117             : #else
     118             :     const std::string regex("lib" + pattern + ".so");
     119             : #endif
     120             :     const Strings& libs = searchDirectory(path, regex);
     121             : 
     122             :     for (const auto& lib : libs)
     123             :     {
     124             :         lunchbox::DSO* dso = new lunchbox::DSO(path + "/" + lib);
     125             :         if (!dso->isOpen())
     126             :         {
     127             :             delete dso;
     128             :             continue;
     129             :         }
     130             : 
     131             :         typedef int (*GetVersion_t)();
     132             :         typedef bool (*Register_t)();
     133             : 
     134             :         GetVersion_t getVersion =
     135             :             dso->getFunctionPointer<GetVersion_t>("LunchboxPluginGetVersion");
     136             :         Register_t registerFunc =
     137             :             dso->getFunctionPointer<Register_t>("LunchboxPluginRegister");
     138             :         const bool matchesVersion = getVersion && (getVersion() == version);
     139             : 
     140             :         if (!getVersion || !registerFunc || !matchesVersion)
     141             :         {
     142             :             LBERROR << "Disable " << lib << ": "
     143             :                     << (getVersion
     144             :                             ? ""
     145             :                             : "Symbol for LunchboxPluginGetVersion missing ")
     146             :                     << (registerFunc
     147             :                             ? ""
     148             :                             : "Symbol for LunchboxPluginRegister missing ");
     149             :             if (getVersion && !matchesVersion)
     150             :                 LBERROR << "Plugin version " << getVersion() << " does not"
     151             :                         << " match application version " << version;
     152             :             LBERROR << std::endl;
     153             : 
     154             :             delete dso;
     155             :             continue;
     156             :         }
     157             : 
     158             :         if (registerFunc())
     159             :         {
     160             :             _libraries.insert(std::make_pair(dso, _plugins.back()));
     161             :             LBINFO << "Loaded plugin " << lib << std::endl;
     162             :         }
     163             :         else
     164             :             delete dso;
     165             :     }
     166             : }
     167             : }

Generated by: LCOV version 1.11