class_loader_core.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_CORE_H_
31 #define CLASS_LOADER__CLASS_LOADER_CORE_H_
32 
33 #include <boost/thread/recursive_mutex.hpp>
34 #include <cstdio>
35 #include <map>
36 #include <string>
37 #include <typeinfo>
38 #include <utility>
39 #include <vector>
40 
41 #include "Poco/SharedLibrary.h"
42 
45 
50 namespace class_loader
51 {
52 
53 class ClassLoader; // Forward declaration
54 
55 namespace class_loader_private
56 {
57 
58 // Typedefs
59 /*****************************************************************************/
60 typedef std::string LibraryPath;
61 typedef std::string ClassName;
62 typedef std::string BaseClassName;
63 typedef std::map<ClassName, class_loader_private::AbstractMetaObjectBase *> FactoryMap;
64 typedef std::map<BaseClassName, FactoryMap> BaseToFactoryMapMap;
65 typedef std::pair<LibraryPath, Poco::SharedLibrary *> LibraryPair;
66 typedef std::vector<LibraryPair> LibraryVector;
67 typedef std::vector<AbstractMetaObjectBase *> MetaObjectVector;
68 
69 // Debug
70 /*****************************************************************************/
72 
73 // Global storage
74 /*****************************************************************************/
75 
80 BaseToFactoryMapMap & getGlobalPluginBaseToFactoryMapMap();
81 
86 LibraryVector & getLoadedLibraryVector();
87 
92 std::string getCurrentlyLoadingLibraryName();
93 
98 void setCurrentlyLoadingLibraryName(const std::string & library_name);
99 
100 
106 
112 
113 
118 FactoryMap & getFactoryMapForBaseClass(const std::string & typeid_base_class_name);
119 
124 template<typename Base>
126 {
127  return getFactoryMapForBaseClass(typeid(Base).name());
128 }
129 
134 boost::recursive_mutex & getLoadedLibraryVectorMutex();
135 boost::recursive_mutex & getPluginBaseToFactoryMapMapMutex();
136 
142 
147 void hasANonPurePluginLibraryBeenOpened(bool hasIt);
148 
149 // Plugin Functions
150 /*****************************************************************************/
151 
159 template<typename Derived, typename Base>
160 void registerPlugin(const std::string & class_name, const std::string & base_class_name)
161 {
162  // Note: This function will be automatically invoked when a dlopen() call
163  // opens a library. Normally it will happen within the scope of loadLibrary(),
164  // but that may not be guaranteed.
166  "class_loader.class_loader_private: "
167  "Registering plugin factory for class = %s, ClassLoader* = %p and library name %s.",
168  class_name.c_str(), getCurrentlyActiveClassLoader(),
170 
171  if (NULL == getCurrentlyActiveClassLoader()) {
173  "class_loader.impl: ALERT!!! "
174  "A library containing plugins has been opened through a means other than through the "
175  "class_loader or pluginlib package. "
176  "This can happen if you build plugin libraries that contain more than just plugins "
177  "(i.e. normal code your app links against). "
178  "This inherently will trigger a dlopen() prior to main() and cause problems as class_loader "
179  "is not aware of plugin factories that autoregister under the hood. "
180  "The class_loader package can compensate, but you may run into namespace collision problems "
181  "(e.g. if you have the same plugin class in two different libraries and you load them both "
182  "at the same time). "
183  "The biggest problem is that library can now no longer be safely unloaded as the "
184  "ClassLoader does not know when non-plugin code is still in use. "
185  "In fact, no ClassLoader instance in your application will be unable to unload any library "
186  "once a non-pure one has been opened. "
187  "Please refactor your code to isolate plugins into their own libraries.");
189  }
190 
191  // Create factory
193  new class_loader_private::MetaObject<Derived, Base>(class_name, base_class_name);
196 
197 
198  // Add it to global factory map map
200  FactoryMap & factoryMap = getFactoryMapForBaseClass<Base>();
201  if (factoryMap.find(class_name) != factoryMap.end()) {
203  "class_loader.impl: SEVERE WARNING!!! "
204  "A namespace collision has occured with plugin factory for class %s. "
205  "New factory will OVERWRITE existing one. "
206  "This situation occurs when libraries containing plugins are directly linked against an "
207  "executable (the one running right now generating this message). "
208  "Please separate plugins out into their own library or just don't link against the library "
209  "and use either class_loader::ClassLoader/MultiLibraryClassLoader to open.",
210  class_name.c_str());
211  }
212  factoryMap[class_name] = new_factory;
214 
216  "class_loader.class_loader_private: "
217  "Registration of %s complete (Metaobject Address = %p)",
218  class_name.c_str(), new_factory);
219 }
220 
227 template<typename Base>
228 Base * createInstance(const std::string & derived_class_name, ClassLoader * loader)
229 {
230  AbstractMetaObject<Base> * factory = NULL;
231 
233  FactoryMap & factoryMap = getFactoryMapForBaseClass<Base>();
234  if (factoryMap.find(derived_class_name) != factoryMap.end()) {
235  factory = dynamic_cast<class_loader_private::AbstractMetaObject<Base> *>(
236  factoryMap[derived_class_name]);
237  } else {
239  "class_loader.class_loader_private: No metaobject exists for class type %s.",
240  derived_class_name.c_str());
241  }
243 
244  Base * obj = NULL;
245  if (factory != NULL && factory->isOwnedBy(loader)) {
246  obj = factory->create();
247  }
248 
249  if (NULL == obj) { // Was never created
250  if (factory && factory->isOwnedBy(NULL)) {
252  "class_loader.impl: ALERT!!! "
253  "A metaobject (i.e. factory) exists for desired class, but has no owner. "
254  "This implies that the library containing the class was dlopen()ed by means other than "
255  "through the class_loader interface. "
256  "This can happen if you build plugin libraries that contain more than just plugins "
257  "(i.e. normal code your app links against) -- that intrinsically will trigger a dlopen() "
258  "prior to main(). "
259  "You should isolate your plugins into their own library, otherwise it will not be "
260  "possible to shutdown the library!");
261 
262  obj = factory->create();
263  } else {
265  "Could not create instance of type " + derived_class_name));
266  }
267  }
268 
270  "class_loader.class_loader_private: "
271  "Created instance of type %s and object pointer = %p",
272  (typeid(obj).name()), obj);
273 
274  return obj;
275 }
276 
282 template<typename Base>
283 std::vector<std::string> getAvailableClasses(ClassLoader * loader)
284 {
285  boost::recursive_mutex::scoped_lock lock(getPluginBaseToFactoryMapMapMutex());
286 
287  FactoryMap & factory_map = getFactoryMapForBaseClass<Base>();
288  std::vector<std::string> classes;
289  std::vector<std::string> classes_with_no_owner;
290 
291  for (FactoryMap::const_iterator itr = factory_map.begin(); itr != factory_map.end(); ++itr) {
292  AbstractMetaObjectBase * factory = itr->second;
293  if (factory->isOwnedBy(loader)) {
294  classes.push_back(itr->first);
295  } else if (factory->isOwnedBy(NULL)) {
296  classes_with_no_owner.push_back(itr->first);
297  }
298  }
299 
300  // Added classes not associated with a class loader (Which can happen through
301  // an unexpected dlopen() to the library)
302  classes.insert(classes.end(), classes_with_no_owner.begin(), classes_with_no_owner.end());
303  return classes;
304 }
305 
311 std::vector<std::string> getAllLibrariesUsedByClassLoader(const ClassLoader * loader);
312 
319 bool isLibraryLoaded(const std::string & library_path, ClassLoader * loader);
320 
326 bool isLibraryLoadedByAnybody(const std::string & library_path);
327 
333 void loadLibrary(const std::string & library_path, ClassLoader * loader);
334 
340 void unloadLibrary(const std::string & library_path, ClassLoader * loader);
341 
342 
343 } // namespace class_loader_private
344 } // namespace class_loader
345 
346 #endif // CLASS_LOADER__CLASS_LOADER_CORE_H_
std::vector< std::string > getAllLibrariesUsedByClassLoader(const ClassLoader *loader)
This function returns the names of all libraries in use by a given class loader.
bool hasANonPurePluginLibraryBeenOpened()
Indicates if a library containing more than just plugins has been opened by the running process...
Definition: base.h:33
boost::recursive_mutex & getPluginBaseToFactoryMapMapMutex()
The actual factory. C The derived class (the actual plugin) B The base class interface for the plug...
Definition: meta_object.h:179
std::map< BaseClassName, FactoryMap > BaseToFactoryMapMap
#define CONSOLE_BRIDGE_logDebug(fmt,...)
boost::recursive_mutex & getLoadedLibraryVectorMutex()
To provide thread safety, all exposed plugin functions can only be run serially by multiple threads...
ClassLoader * getCurrentlyActiveClassLoader()
Gets the ClassLoader currently in scope which used when a library is being loaded.
BaseToFactoryMapMap & getGlobalPluginBaseToFactoryMapMap()
Gets a handle to a global data structure that holds a map of base class names (Base class describes p...
#define CONSOLE_BRIDGE_logError(fmt,...)
std::string getCurrentlyLoadingLibraryName()
When a library is being loaded, in order for factories to know which library they are being associate...
A base class for MetaObjects that excludes a polymorphic type parameter. Subclasses are class templat...
Definition: meta_object.h:57
Base * createInstance(const std::string &derived_class_name, ClassLoader *loader)
This function creates an instance of a plugin class given the derived name of the class and returns a...
void loadLibrary(const std::string &library_path, ClassLoader *loader)
Loads a library into memory if it has not already been done so. Attempting to load an already loaded ...
void setCurrentlyLoadingLibraryName(const std::string &library_name)
When a library is being loaded, in order for factories to know which library they are being associate...
An exception class thrown when class_loader is unable to create a plugin.
This class allows loading and unloading of dynamically linked libraries which contain class definitio...
Definition: class_loader.h:64
void unloadLibrary(const std::string &library_path, ClassLoader *loader)
Unloads a library if it loaded in memory and cleans up its corresponding class factories. If it is not loaded, the function has no effect.
std::vector< AbstractMetaObjectBase * > MetaObjectVector
virtual B * create() const =0
Defines the factory interface that the MetaObject must implement.
LibraryVector & getLoadedLibraryVector()
Gets a handle to a list of open libraries in the form of LibraryPairs which encode the library path+n...
#define CONSOLE_BRIDGE_logWarn(fmt,...)
std::vector< std::string > getAvailableClasses(ClassLoader *loader)
This function returns all the available class_loader in the plugin system that are derived from Base ...
std::vector< LibraryPair > LibraryVector
void setCurrentlyActiveClassLoader(ClassLoader *loader)
Sets the ClassLoader currently in scope which used when a library is being loaded.
void addOwningClassLoader(ClassLoader *loader)
Associates a ClassLoader owner with this factory,.
Definition: meta_object.cpp:93
void registerPlugin(const std::string &class_name, const std::string &base_class_name)
This function is called by the CLASS_LOADER_REGISTER_CLASS macro in plugin_register_macro.h to register factories. Classes that use that macro will cause this function to be invoked when the library is loaded. The function will create a MetaObject (i.e. factory) for the corresponding Derived class and insert it into the appropriate FactoryMap in the global Base-to-FactoryMap map. Note that the passed class_name is the literal class name and not the mangled version.
bool isLibraryLoaded(const std::string &library_path, ClassLoader *loader)
Indicates if passed library loaded within scope of a ClassLoader. The library maybe loaded in memory...
bool isOwnedBy(const ClassLoader *loader)
Indicates if the factory is within the usable scope of a ClassLoader.
FactoryMap & getFactoryMapForBaseClass(const std::string &typeid_base_class_name)
This function extracts a reference to the FactoryMap for appropriate base class out of the global plu...
std::pair< LibraryPath, Poco::SharedLibrary * > LibraryPair
bool isLibraryLoadedByAnybody(const std::string &library_path)
Indicates if passed library has been loaded by ANY ClassLoader.
void setAssociatedLibraryPath(std::string library_path)
Sets the path to the library associated with this factory.
Definition: meta_object.cpp:87
std::map< ClassName, class_loader_private::AbstractMetaObjectBase * > FactoryMap
Abstract base class for factories where polymorphic type variable indicates base class for plugin int...
Definition: meta_object.h:145


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