class_loader.h
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2012, Willow Garage, Inc.
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions are met:
00007  *
00008  *     * Redistributions of source code must retain the above copyright
00009  *       notice, this list of conditions and the following disclaimer.
00010  *     * Redistributions in binary form must reproduce the above copyright
00011  *       notice, this list of conditions and the following disclaimer in the
00012  *       documentation and/or other materials provided with the distribution.
00013  *     * Neither the name of the Willow Garage, Inc. nor the names of its
00014  *       contributors may be used to endorse or promote products derived from
00015  *       this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00018  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00021  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00022  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00023  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00024  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00025  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00026  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00027  * POSSIBILITY OF SUCH DAMAGE.
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); //Unreachable assertion if createInstance() throws on failure
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


class_loader
Author(s): Mirza Shah
autogenerated on Fri Jul 28 2017 05:48:18