Lunchbox  1.17.0
Multi-threaded C++ toolbox library for all application developers creating high-performance multi-threaded programs.
pluginFactory.ipp
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>
26 {
27  static PluginFactory<T> factory;
28  return factory;
29 }
30 
31 template <typename T>
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 }
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 T* PluginFactory<T>::create(const typename T::InitDataT& initData)
52 {
53  for (auto& plugin : _plugins)
54  if (plugin.handles(initData))
55  return plugin.construct(initData);
56 
57  LBTHROW(std::runtime_error("No plugin implementation available for " +
58  std::to_string(initData)));
59 }
60 
61 template <typename T>
63 {
64  _plugins.push_back(plugin);
65 }
66 
67 template <typename T>
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>
81 {
82  _plugins.clear();
83  for (auto& plugin : _libraries)
84  delete plugin.first;
85  _libraries.clear();
86 }
87 
88 template <typename T>
90 {
91  std::string descriptions;
92  for (const auto& plugin : _plugins)
93  descriptions +=
94  (descriptions.empty() ? "" : "\n\n") + plugin.getDescription();
95  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 }
Helper to access dynamic shared objects (DSO)
Definition: dso.h:38
void * getFunctionPointer(const std::string &functionName) const
void deregisterAll()
Unregister all plugin types.
Strings searchDirectory(const std::string &directory, const std::string &pattern)
Retrieve a list of files in a directory matching a boost::regex pattern.
#define LBINFO
Output an informational message to the per-thread Log.
Definition: log.h:199
Factory for Plugin classes.
Definition: pluginFactory.h:56
std::string getDescriptions() const
T * create(const typename T::InitDataT &initData)
Create a plugin instance.
bool isOpen() const
void register_(const PluginT &plugin)
Register a plugin type.
std::vector< std::string > Strings
A vector of std::strings.
Definition: types.h:220
#define LBERROR
Output an error message to the per-thread Log stream.
Definition: log.h:193
void load(const int version, const std::string &path, const std::string &pattern)
Load all compatible plugin libraries from a directory matching a pattern.
Abstraction layer and common utilities for multi-threaded programming.
Definition: algorithm.h:29
bool handles(const typename T::InitDataT &initData)
#define LBTHROW(exc)
Log a std::exception if topic LOG_EXCEPTION is set before throwing exception.
Definition: log.h:230
static PluginFactory & getInstance()
Get the single class instance.
void usort(C &c)
Uniquely sort and eliminate duplicates in a container.
Definition: algorithm.h:72
bool deregister(const PluginT &plugin)
Deregister a plugin type.