class_loader.hpp
Go to the documentation of this file.
1 /*
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2012, Willow Garage, Inc.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are met:
9  *
10  * * Redistributions of source code must retain the above copyright
11  * notice, this list of conditions and the following disclaimer.
12  * * Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in the
14  * documentation and/or other materials provided with the distribution.
15  * * Neither the name of the copyright holders nor the names of its
16  * contributors may be used to endorse or promote products derived from
17  * this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #ifndef CLASS_LOADER__CLASS_LOADER_HPP_
33 #define CLASS_LOADER__CLASS_LOADER_HPP_
34 
35 #include <boost/bind.hpp>
36 #include <boost/shared_ptr.hpp>
37 #include <boost/thread/recursive_mutex.hpp>
38 #include <string>
39 #include <vector>
40 
41 #include "console_bridge/console.h"
42 
46 
47 #if __cplusplus >= 201103L
48 #include <memory>
49 #include <functional>
50 #endif
51 
52 // TODO(mikaelarguedas) : replace no lints with the explicit keyword in an ABI breaking release
53 
54 namespace class_loader
55 {
56 
60 std::string systemLibrarySuffix();
61 
67 {
68 public:
69 #if __cplusplus >= 201103L
70  template<typename Base>
71  using DeleterType = std::function<void(Base *)>;
72 
73  template<typename Base>
74  using UniquePtr = std::unique_ptr<Base, DeleterType<Base>>;
75 #endif
76 
82  ClassLoader(const std::string & library_path, bool ondemand_load_unload = false); // NOLINT
83 
87  virtual ~ClassLoader();
88 
93  template<class Base>
94  std::vector<std::string> getAvailableClasses()
95  {
96  return class_loader::class_loader_private::getAvailableClasses<Base>(this);
97  }
98 
102  std::string getLibraryPath() {return library_path_;}
103 
113  template<class Base>
114  boost::shared_ptr<Base> createInstance(const std::string & derived_class_name)
115  {
116  return boost::shared_ptr<Base>(
117  createRawInstance<Base>(derived_class_name, true),
118  boost::bind(&ClassLoader::onPluginDeletion<Base>, this, _1));
119  }
120 
121 #if __cplusplus >= 201103L
122 
134  template<class Base>
135  UniquePtr<Base> createUniqueInstance(const std::string & derived_class_name)
136  {
137  Base * raw = createRawInstance<Base>(derived_class_name, true);
138  return std::unique_ptr<Base, DeleterType<Base>>(
139  raw,
140  boost::bind(&ClassLoader::onPluginDeletion<Base>, this, _1));
141  }
142 #endif
143 
156  template<class Base>
157  Base * createUnmanagedInstance(const std::string & derived_class_name)
158  {
159  return createRawInstance<Base>(derived_class_name, false);
160  }
161 
168  template<class Base>
169  bool isClassAvailable(const std::string & class_name)
170  {
171  std::vector<std::string> available_classes = getAvailableClasses<Base>();
172  return std::find(
173  available_classes.begin(), available_classes.end(), class_name) != available_classes.end();
174  }
175 
181  bool isLibraryLoaded();
182 
188 
193 
198  void loadLibrary();
199 
204  int unloadLibrary();
205 
206 private:
211  template<class Base>
212  void onPluginDeletion(Base * obj)
213  {
215  "class_loader::ClassLoader: Calling onPluginDeletion() for obj ptr = %p.\n", obj);
216  if (obj) {
217  boost::recursive_mutex::scoped_lock lock(plugin_ref_count_mutex_);
218  delete (obj);
220  assert(plugin_ref_count_ >= 0);
223  unloadLibraryInternal(false);
224  } else {
226  "class_loader::ClassLoader: "
227  "Cannot unload library %s even though last shared pointer went out of scope. "
228  "This is because createUnmanagedInstance was used within the scope of this process,"
229  " perhaps by a different ClassLoader. Library will NOT be closed.",
230  getLibraryPath().c_str());
231  }
232  }
233  }
234  }
235 
246  template<class Base>
247  Base * createRawInstance(const std::string & derived_class_name, bool managed)
248  {
249  if (!managed) {
251  }
252 
253  if (
254  managed &&
257  {
259  "class_loader::ClassLoader: "
260  "An attempt is being made to create a managed plugin instance (i.e. boost::shared_ptr), "
261  "however an unmanaged instance was created within this process address space. "
262  "This means libraries for the managed instances will not be shutdown automatically on "
263  "final plugin destruction if on demand (lazy) loading/unloading mode is used."
264  );
265  }
266  if (!isLibraryLoaded()) {
267  loadLibrary();
268  }
269 
270  Base * obj =
271  class_loader::class_loader_private::createInstance<Base>(derived_class_name, this);
272  assert(obj != NULL); // Unreachable assertion if createInstance() throws on failure
273 
274  if (managed) {
275  boost::recursive_mutex::scoped_lock lock(plugin_ref_count_mutex_);
277  }
278 
279  return obj;
280  }
281 
285  static bool hasUnmanagedInstanceBeenCreated();
286 
292  int unloadLibraryInternal(bool lock_plugin_ref_count);
293 
294 private:
296  std::string library_path_;
298  boost::recursive_mutex load_ref_count_mutex_;
300  boost::recursive_mutex plugin_ref_count_mutex_;
302 };
303 
304 } // namespace class_loader
305 
306 
307 #endif // CLASS_LOADER__CLASS_LOADER_HPP_
#define CONSOLE_BRIDGE_logWarn(fmt,...)
Definition: base.hpp:33
std::vector< std::string > getAvailableClasses()
Indicates which classes (i.e. class_loader) that can be loaded by this object.
void onPluginDeletion(Base *obj)
Callback method when a plugin created by this class loader is destroyed.
bool isLibraryLoaded()
Indicates if a library is loaded within the scope of this ClassLoader. Note that the library may alre...
boost::recursive_mutex plugin_ref_count_mutex_
Base * createUnmanagedInstance(const std::string &derived_class_name)
Generates an instance of loadable classes (i.e. class_loader).
Base * createRawInstance(const std::string &derived_class_name, bool managed)
Generates an instance of loadable classes (i.e. class_loader).
#define CONSOLE_BRIDGE_logDebug(fmt,...)
std::string systemLibrarySuffix()
ClassLoader(const std::string &library_path, bool ondemand_load_unload=false)
Constructor for ClassLoader.
This class allows loading and unloading of dynamically linked libraries which contain class definitio...
int unloadLibraryInternal(bool lock_plugin_ref_count)
As the library may be unloaded in "on-demand load/unload" mode, unload maybe called from createInstan...
bool isLibraryLoadedByAnyClassloader()
Indicates if a library is loaded by some entity in the plugin system (another ClassLoader), but not necessarily loaded by this ClassLoader.
bool isOnDemandLoadUnloadEnabled()
Indicates if the library is to be loaded/unloaded on demand...meaning that only to load a lib when th...
bool isClassAvailable(const std::string &class_name)
Indicates if a plugin class is available.
int unloadLibrary()
Attempts to unload a library loaded within scope of the ClassLoader. If the library is not opened...
virtual ~ClassLoader()
Destructor for ClassLoader. All libraries opened by this ClassLoader are unloaded automatically...
static bool has_unmananged_instance_been_created_
boost::shared_ptr< Base > createInstance(const std::string &derived_class_name)
Generates an instance of loadable classes (i.e. class_loader).
std::string getLibraryPath()
Gets the full-qualified path and name of the library associated with this class loader.
void loadLibrary()
Attempts to load a library on behalf of the ClassLoader. If the library is already opened...
static bool hasUnmanagedInstanceBeenCreated()
Getter for if an unmanaged (i.e. unsafe) instance has been created flag.
boost::recursive_mutex load_ref_count_mutex_
#define CONSOLE_BRIDGE_logInform(fmt,...)


class_loader
Author(s): Mirza Shah
autogenerated on Mon Jun 10 2019 12:51:50