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 <cstddef>
39 #include <functional>
40 #include <memory>
41 #include <string>
42 #include <vector>
43 
44 #include "console_bridge/console.h"
45 
49 
50 namespace class_loader
51 {
52 
57 std::string systemLibraryPrefix();
58 
63 std::string systemLibrarySuffix();
64 
72 std::string systemLibraryFormat(const std::string & library_name);
73 
79 {
80 public:
81  template<typename Base>
82  using DeleterType = std::function<void(Base *)>;
83 
84  template<typename Base>
85  using UniquePtr = std::unique_ptr<Base, DeleterType<Base>>;
86 
93  explicit ClassLoader(const std::string & library_path, bool ondemand_load_unload = false);
94 
99  virtual ~ClassLoader();
100 
105  template<class Base>
106  std::vector<std::string> getAvailableClasses()
107  {
108  return class_loader::impl::getAvailableClasses<Base>(this);
109  }
110 
115  std::string getLibraryPath() {return library_path_;}
116 
126  template<class Base>
127  std::shared_ptr<Base> createSharedInstance(const std::string & derived_class_name)
128  {
129  return std::shared_ptr<Base>(
130  createRawInstance<Base>(derived_class_name, true),
131  boost::bind(&ClassLoader::onPluginDeletion<Base>, this, _1));
132  }
133 
139  template<class Base>
140  boost::shared_ptr<Base> createInstance(const std::string & derived_class_name)
141  {
142  return boost::shared_ptr<Base>(
143  createRawInstance<Base>(derived_class_name, true),
144  boost::bind(&ClassLoader::onPluginDeletion<Base>, this, _1));
145  }
146 
159  template<class Base>
160  UniquePtr<Base> createUniqueInstance(const std::string & derived_class_name)
161  {
162  Base * raw = createRawInstance<Base>(derived_class_name, true);
163  return std::unique_ptr<Base, DeleterType<Base>>(
164  raw,
165  boost::bind(&ClassLoader::onPluginDeletion<Base>, this, _1));
166  }
167 
180  template<class Base>
181  Base * createUnmanagedInstance(const std::string & derived_class_name)
182  {
183  return createRawInstance<Base>(derived_class_name, false);
184  }
185 
192  template<class Base>
193  bool isClassAvailable(const std::string & class_name)
194  {
195  std::vector<std::string> available_classes = getAvailableClasses<Base>();
196  return std::find(
197  available_classes.begin(), available_classes.end(), class_name) != available_classes.end();
198  }
199 
206  bool isLibraryLoaded();
207 
214 
220 
226  void loadLibrary();
227 
233  int unloadLibrary();
234 
235 private:
240  template<class Base>
241  void onPluginDeletion(Base * obj)
242  {
243  CONSOLE_BRIDGE_logDebug(
244  "class_loader::ClassLoader: Calling onPluginDeletion() for obj ptr = %p.\n",
245  reinterpret_cast<void *>(obj));
246  if (nullptr == obj) {
247  return;
248  }
249  boost::recursive_mutex::scoped_lock lock(plugin_ref_count_mutex_);
250  delete (obj);
252  assert(plugin_ref_count_ >= 0);
255  unloadLibraryInternal(false);
256  } else {
257  CONSOLE_BRIDGE_logWarn(
258  "class_loader::ClassLoader: "
259  "Cannot unload library %s even though last shared pointer went out of scope. "
260  "This is because createUnmanagedInstance was used within the scope of this process,"
261  " perhaps by a different ClassLoader. Library will NOT be closed.",
262  getLibraryPath().c_str());
263  }
264  }
265  }
266 
277  template<class Base>
278  Base * createRawInstance(const std::string & derived_class_name, bool managed)
279  {
280  if (!managed) {
282  }
283 
284  if (
285  managed &&
288  {
289  CONSOLE_BRIDGE_logInform("%s",
290  "class_loader::ClassLoader: "
291  "An attempt is being made to create a managed plugin instance (i.e. boost::shared_ptr), "
292  "however an unmanaged instance was created within this process address space. "
293  "This means libraries for the managed instances will not be shutdown automatically on "
294  "final plugin destruction if on demand (lazy) loading/unloading mode is used."
295  );
296  }
297  if (!isLibraryLoaded()) {
298  loadLibrary();
299  }
300 
301  Base * obj = class_loader::impl::createInstance<Base>(derived_class_name, this);
302  assert(obj != nullptr); // Unreachable assertion if createInstance() throws on failure
303 
304  if (managed) {
305  boost::recursive_mutex::scoped_lock lock(plugin_ref_count_mutex_);
307  }
308 
309  return obj;
310  }
311 
316  static bool hasUnmanagedInstanceBeenCreated();
317 
324  int unloadLibraryInternal(bool lock_plugin_ref_count);
325 
326 private:
328  std::string library_path_;
330  boost::recursive_mutex load_ref_count_mutex_;
332  boost::recursive_mutex plugin_ref_count_mutex_;
333 
336 };
337 
338 } // namespace class_loader
339 
340 
341 #endif // CLASS_LOADER__CLASS_LOADER_HPP_
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.
UniquePtr< Base > createUniqueInstance(const std::string &derived_class_name)
Generates an instance of loadable classes (i.e. class_loader).
CLASS_LOADER_PUBLIC 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_
CLASS_LOADER_PUBLIC std::string systemLibraryFormat(const std::string &library_name)
Returns a platform specific version of a basic library name.
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).
CLASS_LOADER_PUBLIC bool isOnDemandLoadUnloadEnabled()
Indicates if the library is to be loaded/unloaded on demand...meaning that only to load a lib when th...
CLASS_LOADER_PUBLIC std::string systemLibrarySuffix()
Returns runtime library extension for native os.
CLASS_LOADER_PUBLIC 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...
CLASS_LOADER_PUBLIC int unloadLibraryInternal(bool lock_plugin_ref_count)
As the library may be unloaded in "on-demand load/unload" mode, unload maybe called from createInstan...
std::shared_ptr< Base > createSharedInstance(const std::string &derived_class_name)
Generates an instance of loadable classes (i.e. class_loader).
CLASS_LOADER_PUBLIC 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 isClassAvailable(const std::string &class_name)
Indicates if a plugin class is available.
CLASS_LOADER_PUBLIC int unloadLibrary()
Attempts to unload a library loaded within scope of the ClassLoader. If the library is not opened...
std::unique_ptr< Base, DeleterType< Base > > UniquePtr
std::function< void(Base *)> DeleterType
CLASS_LOADER_PUBLIC std::string getLibraryPath()
Gets the full-qualified path and name of the library associated with this class loader.
virtual CLASS_LOADER_PUBLIC ~ClassLoader()
Destructor for ClassLoader. All libraries opened by this ClassLoader are unloaded automatically...
#define CLASS_LOADER_PUBLIC
static CLASS_LOADER_PUBLIC 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).
CLASS_LOADER_PUBLIC std::string systemLibraryPrefix()
Returns the default library prefix for the native os.
CLASS_LOADER_PUBLIC void loadLibrary()
Attempts to load a library on behalf of the ClassLoader. If the library is already opened...
static CLASS_LOADER_PUBLIC bool hasUnmanagedInstanceBeenCreated()
Getter for if an unmanaged (i.e. unsafe) instance has been created flag.
boost::recursive_mutex load_ref_count_mutex_


class_loader
Author(s): Mirza Shah, Steven! Ragnarök
autogenerated on Mon Feb 28 2022 22:02:03