Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #ifndef CLASS_LOADER_CLASS_LOADER_H_DEFINED
00031 #define CLASS_LOADER_CLASS_LOADER_H_DEFINED
00032
00033 #include <boost/shared_ptr.hpp>
00034 #include <boost/thread/recursive_mutex.hpp>
00035 #include <boost/bind.hpp>
00036 #include <vector>
00037 #include <string>
00038 #include <console_bridge/console.h>
00039 #include "class_loader/class_loader_register_macro.h"
00040 #include "class_loader/class_loader_core.h"
00041 #include "class_loader/console_bridge_compatibility.h"
00042
00043 #if __cplusplus >= 201103L
00044 # include<memory>
00045 # include<functional>
00046 #endif
00047
00048 namespace class_loader
00049 {
00050
00054 std::string systemLibrarySuffix();
00055
00060 class ClassLoader
00061 {
00062 public:
00063 #if __cplusplus >= 201103L
00064 template<typename Base>
00065 using DeleterType = std::function<void (Base *)>;
00066
00067 template<typename Base>
00068 using UniquePtr = std::unique_ptr<Base, DeleterType<Base>>;
00069 #endif
00070
00076 ClassLoader(const std::string& library_path, bool ondemand_load_unload = false);
00077
00081 virtual ~ClassLoader();
00082
00087 template <class Base>
00088 std::vector<std::string> getAvailableClasses()
00089 {
00090 return(class_loader::class_loader_private::getAvailableClasses<Base>(this));
00091 }
00092
00096 std::string getLibraryPath(){return(library_path_);}
00097
00107 template <class Base>
00108 boost::shared_ptr<Base> createInstance(const std::string& derived_class_name)
00109 {
00110 return boost::shared_ptr<Base>(createRawInstance<Base>(derived_class_name, true),
00111 boost::bind(&ClassLoader::onPluginDeletion<Base>, this, _1));
00112 }
00113
00114 #if __cplusplus >= 201103L
00115
00127 template<class Base>
00128 UniquePtr<Base> createUniqueInstance(const std::string& derived_class_name)
00129 {
00130 Base* raw = createRawInstance<Base>(derived_class_name, true);
00131 return std::unique_ptr<Base, DeleterType<Base>>(raw, boost::bind(&ClassLoader::onPluginDeletion<Base>, this, _1));
00132 }
00133 #endif
00134
00147 template <class Base>
00148 Base* createUnmanagedInstance(const std::string& derived_class_name)
00149 {
00150 return createRawInstance<Base>(derived_class_name, false);
00151 }
00152
00159 template <class Base>
00160 bool isClassAvailable(const std::string& class_name)
00161 {
00162 std::vector<std::string> available_classes = getAvailableClasses<Base>();
00163 return(std::find(available_classes.begin(), available_classes.end(), class_name) != available_classes.end());
00164 }
00165
00171 bool isLibraryLoaded();
00172
00177 bool isLibraryLoadedByAnyClassloader();
00178
00182 bool isOnDemandLoadUnloadEnabled(){return(ondemand_load_unload_);}
00183
00188 void loadLibrary();
00189
00194 int unloadLibrary();
00195
00196 private:
00201 template <class Base>
00202 void onPluginDeletion(Base* obj)
00203 {
00204 CONSOLE_BRIDGE_logDebug("class_loader::ClassLoader: Calling onPluginDeletion() for obj ptr = %p.\n", obj);
00205 if(obj)
00206 {
00207 boost::recursive_mutex::scoped_lock lock(plugin_ref_count_mutex_);
00208 delete(obj);
00209 plugin_ref_count_ = plugin_ref_count_ - 1;
00210 assert(plugin_ref_count_ >= 0);
00211 if(plugin_ref_count_ == 0 && isOnDemandLoadUnloadEnabled())
00212 {
00213 if(!ClassLoader::hasUnmanagedInstanceBeenCreated())
00214 unloadLibraryInternal(false);
00215 else
00216 CONSOLE_BRIDGE_logWarn("class_loader::ClassLoader: Cannot unload library %s even though last shared pointer went out of scope. This is because createUnmanagedInstance was used within the scope of this process, perhaps by a different ClassLoader. Library will NOT be closed.", getLibraryPath().c_str());
00217 }
00218 }
00219 }
00220
00231 template <class Base>
00232 Base* createRawInstance(const std::string& derived_class_name, bool managed)
00233 {
00234 if (!managed)
00235 has_unmananged_instance_been_created_ = true;
00236
00237 if (managed && ClassLoader::hasUnmanagedInstanceBeenCreated() && isOnDemandLoadUnloadEnabled())
00238 CONSOLE_BRIDGE_logInform("class_loader::ClassLoader: An attempt is being made to create a managed plugin instance (i.e. boost::shared_ptr), however an unmanaged instance was created within this process address space. This means libraries for the managed instances will not be shutdown automatically on final plugin destruction if on demand (lazy) loading/unloading mode is used.");
00239
00240 if (!isLibraryLoaded())
00241 loadLibrary();
00242
00243 Base* obj = class_loader::class_loader_private::createInstance<Base>(derived_class_name, this);
00244 assert(obj != NULL);
00245
00246 if (managed)
00247 {
00248 boost::recursive_mutex::scoped_lock lock(plugin_ref_count_mutex_);
00249 plugin_ref_count_ = plugin_ref_count_ + 1;
00250 }
00251
00252 return obj;
00253 }
00254
00258 static bool hasUnmanagedInstanceBeenCreated();
00259
00265 int unloadLibraryInternal(bool lock_plugin_ref_count);
00266
00267 private:
00268
00269 bool ondemand_load_unload_;
00270 std::string library_path_;
00271 int load_ref_count_;
00272 boost::recursive_mutex load_ref_count_mutex_;
00273 int plugin_ref_count_;
00274 boost::recursive_mutex plugin_ref_count_mutex_;
00275 static bool has_unmananged_instance_been_created_;
00276 };
00277
00278 }
00279
00280
00281 #endif