class_loader.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2012, Willow Garage, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * * Neither the name of the Willow Garage, Inc. nor the names of its
14  * contributors may be used to endorse or promote products derived from
15  * this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #ifndef CLASS_LOADER__CLASS_LOADER_H_
31 #define CLASS_LOADER__CLASS_LOADER_H_
32 
33 #include <boost/bind.hpp>
34 #include <boost/shared_ptr.hpp>
35 #include <boost/thread/recursive_mutex.hpp>
36 #include <string>
37 #include <vector>
38 
39 #include "console_bridge/console.h"
40 
44 
45 #if __cplusplus >= 201103L
46 #include <memory>
47 #include <functional>
48 #endif
49 
50 // TODO(mikaelarguedas) : replace no lints with the explicit keyword in an ABI breaking release
51 
52 namespace class_loader
53 {
54 
58 std::string systemLibrarySuffix();
59 
65 {
66 public:
67 #if __cplusplus >= 201103L
68  template<typename Base>
69  using DeleterType = std::function<void(Base *)>;
70 
71  template<typename Base>
72  using UniquePtr = std::unique_ptr<Base, DeleterType<Base>>;
73 #endif
74 
80  ClassLoader(const std::string & library_path, bool ondemand_load_unload = false); // NOLINT
81 
85  virtual ~ClassLoader();
86 
91  template<class Base>
92  std::vector<std::string> getAvailableClasses()
93  {
94  return class_loader::class_loader_private::getAvailableClasses<Base>(this);
95  }
96 
100  std::string getLibraryPath() {return library_path_;}
101 
111  template<class Base>
112  boost::shared_ptr<Base> createInstance(const std::string & derived_class_name)
113  {
114  return boost::shared_ptr<Base>(
115  createRawInstance<Base>(derived_class_name, true),
116  boost::bind(&ClassLoader::onPluginDeletion<Base>, this, _1));
117  }
118 
119 #if __cplusplus >= 201103L
120 
132  template<class Base>
133  UniquePtr<Base> createUniqueInstance(const std::string & derived_class_name)
134  {
135  Base * raw = createRawInstance<Base>(derived_class_name, true);
136  return std::unique_ptr<Base, DeleterType<Base>>(
137  raw,
138  boost::bind(&ClassLoader::onPluginDeletion<Base>, this, _1));
139  }
140 #endif
141 
154  template<class Base>
155  Base * createUnmanagedInstance(const std::string & derived_class_name)
156  {
157  return createRawInstance<Base>(derived_class_name, false);
158  }
159 
166  template<class Base>
167  bool isClassAvailable(const std::string & class_name)
168  {
169  std::vector<std::string> available_classes = getAvailableClasses<Base>();
170  return std::find(
171  available_classes.begin(), available_classes.end(), class_name) != available_classes.end();
172  }
173 
179  bool isLibraryLoaded();
180 
186 
191 
196  void loadLibrary();
197 
202  int unloadLibrary();
203 
204 private:
209  template<class Base>
210  void onPluginDeletion(Base * obj)
211  {
213  "class_loader::ClassLoader: Calling onPluginDeletion() for obj ptr = %p.\n", obj);
214  if (obj) {
215  boost::recursive_mutex::scoped_lock lock(plugin_ref_count_mutex_);
216  delete (obj);
218  assert(plugin_ref_count_ >= 0);
221  unloadLibraryInternal(false);
222  } else {
224  "class_loader::ClassLoader: "
225  "Cannot unload library %s even though last shared pointer went out of scope. "
226  "This is because createUnmanagedInstance was used within the scope of this process,"
227  " perhaps by a different ClassLoader. Library will NOT be closed.",
228  getLibraryPath().c_str());
229  }
230  }
231  }
232  }
233 
244  template<class Base>
245  Base * createRawInstance(const std::string & derived_class_name, bool managed)
246  {
247  if (!managed) {
249  }
250 
251  if (
252  managed &&
255  {
257  "class_loader::ClassLoader: "
258  "An attempt is being made to create a managed plugin instance (i.e. boost::shared_ptr), "
259  "however an unmanaged instance was created within this process address space. "
260  "This means libraries for the managed instances will not be shutdown automatically on "
261  "final plugin destruction if on demand (lazy) loading/unloading mode is used."
262  );
263  }
264  if (!isLibraryLoaded()) {
265  loadLibrary();
266  }
267 
268  Base * obj =
269  class_loader::class_loader_private::createInstance<Base>(derived_class_name, this);
270  assert(obj != NULL); // Unreachable assertion if createInstance() throws on failure
271 
272  if (managed) {
273  boost::recursive_mutex::scoped_lock lock(plugin_ref_count_mutex_);
275  }
276 
277  return obj;
278  }
279 
283  static bool hasUnmanagedInstanceBeenCreated();
284 
290  int unloadLibraryInternal(bool lock_plugin_ref_count);
291 
292 private:
294  std::string library_path_;
296  boost::recursive_mutex load_ref_count_mutex_;
298  boost::recursive_mutex plugin_ref_count_mutex_;
300 };
301 
302 } // namespace class_loader
303 
304 
305 #endif // CLASS_LOADER__CLASS_LOADER_H_
Definition: base.h:33
std::vector< std::string > getAvailableClasses()
Indicates which classes (i.e. class_loader) that can be loaded by this object.
Definition: class_loader.h:92
#define CONSOLE_BRIDGE_logDebug(fmt,...)
void onPluginDeletion(Base *obj)
Callback method when a plugin created by this class loader is destroyed.
Definition: class_loader.h:210
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_
Definition: class_loader.h:298
Base * createUnmanagedInstance(const std::string &derived_class_name)
Generates an instance of loadable classes (i.e. class_loader).
Definition: class_loader.h:155
Base * createRawInstance(const std::string &derived_class_name, bool managed)
Generates an instance of loadable classes (i.e. class_loader).
Definition: class_loader.h:245
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...
Definition: class_loader.h:64
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...
Definition: class_loader.h:190
#define CONSOLE_BRIDGE_logWarn(fmt,...)
#define CONSOLE_BRIDGE_logInform(fmt,...)
bool isClassAvailable(const std::string &class_name)
Indicates if a plugin class is available.
Definition: class_loader.h:167
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_
Definition: class_loader.h:299
boost::shared_ptr< Base > createInstance(const std::string &derived_class_name)
Generates an instance of loadable classes (i.e. class_loader).
Definition: class_loader.h:112
std::string getLibraryPath()
Gets the full-qualified path and name of the library associated with this class loader.
Definition: class_loader.h:100
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_
Definition: class_loader.h:296


class_loader
Author(s): Mirza Shah
autogenerated on Thu Dec 7 2017 03:43:35