class_loader_core.cpp
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 #include "class_loader/class_loader_core.h"
00031 #include "class_loader/class_loader.h"
00032 #include <cassert>
00033 
00034 namespace class_loader
00035 {
00036 namespace class_loader_private
00037 {
00038 
00039 
00040 //Global data
00041 /*****************************************************************************/
00042 /*****************************************************************************/
00043 /*****************************************************************************/
00044 
00045 boost::recursive_mutex& getLoadedLibraryVectorMutex()
00046 /*****************************************************************************/
00047 {
00048   static boost::recursive_mutex m;
00049   return m;
00050 }
00051 
00052 boost::recursive_mutex& getPluginBaseToFactoryMapMapMutex()
00053 /*****************************************************************************/
00054 {
00055   static boost::recursive_mutex m;
00056   return m;
00057 }
00058 
00059 BaseToFactoryMapMap& getGlobalPluginBaseToFactoryMapMap()
00060 /*****************************************************************************/
00061 {
00062   static BaseToFactoryMapMap instance;
00063   return instance;
00064 }
00065 
00066 FactoryMap& getFactoryMapForBaseClass(const std::string& typeid_base_class_name)
00067 /*****************************************************************************/
00068 {
00069   BaseToFactoryMapMap& factoryMapMap = getGlobalPluginBaseToFactoryMapMap();
00070   std::string base_class_name = typeid_base_class_name;
00071   if(factoryMapMap.find(base_class_name) == factoryMapMap.end())
00072     factoryMapMap[base_class_name] = FactoryMap();
00073 
00074   return(factoryMapMap[base_class_name]);
00075 }
00076 
00077 MetaObjectVector& getMetaObjectGraveyard()
00078 /*****************************************************************************/
00079 {
00080   static MetaObjectVector instance;
00081   return instance;
00082 }
00083 
00084 LibraryVector& getLoadedLibraryVector()
00085 /*****************************************************************************/
00086 {
00087   static LibraryVector instance;
00088   return instance;
00089 }
00090 
00091 std::string& getCurrentlyLoadingLibraryNameReference()
00092 /*****************************************************************************/
00093 {
00094   static std::string library_name;
00095   return library_name;
00096 }
00097 
00098 std::string getCurrentlyLoadingLibraryName()
00099 /*****************************************************************************/
00100 {
00101   return(getCurrentlyLoadingLibraryNameReference());
00102 }
00103 
00104 void setCurrentlyLoadingLibraryName(const std::string& library_name)
00105 /*****************************************************************************/
00106 {
00107   std::string& library_name_ref = getCurrentlyLoadingLibraryNameReference();
00108   library_name_ref = library_name;
00109 }
00110 
00111 ClassLoader*& getCurrentlyActiveClassLoaderReference()
00112 /*****************************************************************************/
00113 {
00114   static ClassLoader* loader = NULL;
00115   return(loader);
00116 }
00117 
00118 ClassLoader* getCurrentlyActiveClassLoader()
00119 /*****************************************************************************/
00120 {
00121   return(getCurrentlyActiveClassLoaderReference());
00122 }
00123 
00124 void setCurrentlyActiveClassLoader(ClassLoader* loader)
00125 /*****************************************************************************/
00126 {
00127   ClassLoader*& loader_ref = getCurrentlyActiveClassLoaderReference();
00128   loader_ref = loader;
00129 }
00130 
00131 bool& hasANonPurePluginLibraryBeenOpenedReference()
00132 /*****************************************************************************/
00133 {
00134   static bool hasANonPurePluginLibraryBeenOpenedReference = false;
00135   return hasANonPurePluginLibraryBeenOpenedReference;
00136 }
00137 
00138 bool hasANonPurePluginLibraryBeenOpened()
00139 /*****************************************************************************/
00140 {
00141   return(hasANonPurePluginLibraryBeenOpenedReference());
00142 }
00143 
00144 void hasANonPurePluginLibraryBeenOpened(bool hasIt)
00145 /*****************************************************************************/
00146 {
00147   hasANonPurePluginLibraryBeenOpenedReference() = hasIt;
00148 }
00149 
00150 
00151 //MetaObject search/insert/removal/query
00152 /*****************************************************************************/
00153 /*****************************************************************************/
00154 /*****************************************************************************/
00155 
00156 MetaObjectVector allMetaObjects(const FactoryMap& factories)
00157 /*****************************************************************************/
00158 {
00159   MetaObjectVector all_meta_objs;
00160   for(FactoryMap::const_iterator factoryItr = factories.begin(); factoryItr != factories.end(); factoryItr++)
00161       all_meta_objs.push_back(factoryItr->second);
00162   return(all_meta_objs);
00163 }
00164 
00165 MetaObjectVector allMetaObjects()
00166 /*****************************************************************************/
00167 {
00168   boost::recursive_mutex::scoped_lock lock(getPluginBaseToFactoryMapMapMutex());
00169 
00170   MetaObjectVector all_meta_objs;
00171   BaseToFactoryMapMap& factory_map_map = getGlobalPluginBaseToFactoryMapMap();
00172   BaseToFactoryMapMap::iterator itr;
00173 
00174   for(itr = factory_map_map.begin(); itr != factory_map_map.end(); itr++)
00175   {
00176     MetaObjectVector objs = allMetaObjects(itr->second);
00177     all_meta_objs.insert(all_meta_objs.end(), objs.begin(), objs.end());
00178   }
00179   return(all_meta_objs);
00180 }
00181 
00182 MetaObjectVector filterAllMetaObjectsOwnedBy(const MetaObjectVector& to_filter, const ClassLoader* owner)
00183 /*****************************************************************************/
00184 {
00185   MetaObjectVector filtered_objs;
00186   for(unsigned int c = 0; c < to_filter.size(); c++)
00187     if(to_filter.at(c)->isOwnedBy(owner))
00188       filtered_objs.push_back(to_filter.at(c));
00189   return(filtered_objs);
00190 }
00191 
00192 MetaObjectVector filterAllMetaObjectsAssociatedWithLibrary(const MetaObjectVector& to_filter, const std::string& library_path)
00193 /*****************************************************************************/
00194 {
00195   MetaObjectVector filtered_objs;
00196   for(unsigned int c = 0; c < to_filter.size(); c++)
00197     if(to_filter.at(c)->getAssociatedLibraryPath()==library_path)
00198       filtered_objs.push_back(to_filter.at(c));
00199   return(filtered_objs);
00200 }
00201 
00202 MetaObjectVector allMetaObjectsForClassLoader(const ClassLoader* owner)
00203 /*****************************************************************************/
00204 {
00205   return(filterAllMetaObjectsOwnedBy(allMetaObjects(), owner));
00206 }
00207 
00208 MetaObjectVector allMetaObjectsForLibrary(const std::string& library_path)
00209 /*****************************************************************************/
00210 {
00211   return(filterAllMetaObjectsAssociatedWithLibrary(allMetaObjects(), library_path));
00212 }
00213 
00214 MetaObjectVector allMetaObjectsForLibraryOwnedBy(const std::string& library_path, const ClassLoader* owner)
00215 /*****************************************************************************/
00216 {
00217   return(filterAllMetaObjectsOwnedBy(allMetaObjectsForLibrary(library_path), owner));
00218 }
00219 
00220 void insertMetaObjectIntoGraveyard(AbstractMetaObjectBase* meta_obj)
00221 /*****************************************************************************/
00222 {
00223   CONSOLE_BRIDGE_logDebug("class_loader.class_loader_private: Inserting MetaObject (class = %s, base_class = %s, ptr = %p) into graveyard", meta_obj->className().c_str(), meta_obj->baseClassName().c_str(), meta_obj);
00224   getMetaObjectGraveyard().push_back(meta_obj);
00225 }
00226 
00227 void destroyMetaObjectsForLibrary(const std::string& library_path, FactoryMap& factories, const ClassLoader* loader)
00228 /*****************************************************************************/
00229 {
00230   FactoryMap::iterator factory_itr = factories.begin();
00231   while(factory_itr != factories.end())
00232   {
00233     AbstractMetaObjectBase* meta_obj = factory_itr->second;
00234     if(meta_obj->getAssociatedLibraryPath() == library_path && meta_obj->isOwnedBy(loader))
00235     {
00236       meta_obj->removeOwningClassLoader(loader);
00237       if(!meta_obj->isOwnedByAnybody())
00238       {
00239         FactoryMap::iterator factory_itr_copy = factory_itr;
00240         factory_itr++;
00241         factories.erase(factory_itr_copy); //Note: map::erase does not return iterator like vector::erase does. Hence the ugliness of this code and a need for copy. Should be fixed in next C++ revision
00242 
00243         //Insert into graveyard
00244         //We remove the metaobject from its factory map, but we don't destroy it...instead it saved to
00245         //a "graveyard" to the side. This is due to our static global variable initialization problem
00246         //that causes factories to not be registered when a library is closed and then reopened. This is
00247         //because it's truly not closed due to the use of global symbol binding i.e. calling dlopen
00248         //with RTLD_GLOBAL instead of RTLD_LOCAL. We require using the former as the which is required to support
00249         //RTTI
00250         insertMetaObjectIntoGraveyard(meta_obj);
00251       }
00252       else
00253         factory_itr++;
00254     }
00255     else
00256       factory_itr++;
00257   }
00258 }
00259 
00260 void destroyMetaObjectsForLibrary(const std::string& library_path, const ClassLoader* loader)
00261 /*****************************************************************************/
00262 {
00263   boost::recursive_mutex::scoped_lock lock(getPluginBaseToFactoryMapMapMutex());
00264 
00265   CONSOLE_BRIDGE_logDebug("class_loader.class_loader_private: Removing MetaObjects associated with library %s and class loader %p from global plugin-to-factorymap map.\n", library_path.c_str(), loader);
00266 
00267   //We have to walk through all FactoryMaps to be sure
00268   BaseToFactoryMapMap& factory_map_map = getGlobalPluginBaseToFactoryMapMap();
00269   BaseToFactoryMapMap::iterator itr;
00270   for(itr = factory_map_map.begin(); itr != factory_map_map.end(); itr++)
00271     destroyMetaObjectsForLibrary(library_path, itr->second, loader);
00272 
00273   CONSOLE_BRIDGE_logDebug("class_loader.class_loader_private: Metaobjects removed.");
00274 }
00275 
00276 bool areThereAnyExistingMetaObjectsForLibrary(const std::string& library_path)
00277 /*****************************************************************************/
00278 {
00279   return(allMetaObjectsForLibrary(library_path).size() > 0);
00280 }
00281 
00282 //Loaded Library Vector manipulation
00283 /*****************************************************************************/
00284 /*****************************************************************************/
00285 /*****************************************************************************/
00286 LibraryVector::iterator findLoadedLibrary(const std::string& library_path)
00287 /*****************************************************************************/
00288 {
00289   LibraryVector& open_libraries =  getLoadedLibraryVector();
00290   LibraryVector::iterator itr;
00291   for(itr = open_libraries.begin(); itr != open_libraries.end(); itr++ )
00292   {
00293     if(itr->first == library_path)
00294       break;
00295   }
00296   return(itr);
00297 }
00298 
00299 bool isLibraryLoadedByAnybody(const std::string& library_path)
00300 /*****************************************************************************/
00301 {
00302   boost::recursive_mutex::scoped_lock lock(getLoadedLibraryVectorMutex());
00303 
00304   LibraryVector& open_libraries =  getLoadedLibraryVector();
00305   LibraryVector::iterator itr = findLoadedLibrary(library_path);
00306 
00307   if(itr != open_libraries.end())
00308   {
00309     assert(itr->second->isLoaded() == true); //Ensure Poco actually thinks the library is loaded
00310     return(true);
00311   }
00312   else
00313     return(false);
00314 };
00315 
00316 bool isLibraryLoaded(const std::string& library_path, ClassLoader* loader)
00317 /*****************************************************************************/
00318 {
00319   bool is_lib_loaded_by_anyone = isLibraryLoadedByAnybody(library_path);
00320   int num_meta_objs_for_lib = allMetaObjectsForLibrary(library_path).size();
00321   int num_meta_objs_for_lib_bound_to_loader = allMetaObjectsForLibraryOwnedBy(library_path,loader).size();
00322   bool are_meta_objs_bound_to_loader = (num_meta_objs_for_lib == 0) ? true : (num_meta_objs_for_lib_bound_to_loader <= num_meta_objs_for_lib);
00323 
00324   return(is_lib_loaded_by_anyone && are_meta_objs_bound_to_loader);
00325 }
00326 
00327 std::vector<std::string> getAllLibrariesUsedByClassLoader(const ClassLoader* loader)
00328 /*****************************************************************************/
00329 {
00330   MetaObjectVector all_loader_meta_objs = allMetaObjectsForClassLoader(loader);
00331   std::vector<std::string> all_libs;
00332   for(unsigned int c = 0; c < all_loader_meta_objs.size(); c++)
00333   {
00334     std::string lib_path = all_loader_meta_objs.at(c)->getAssociatedLibraryPath();
00335     if(std::find(all_libs.begin(), all_libs.end(), lib_path) == all_libs.end())
00336       all_libs.push_back(lib_path);
00337   }
00338   return(all_libs);
00339 }
00340 
00341 
00342 //Implementation of Remaining Core plugin_private Functions
00343 /*****************************************************************************/
00344 /*****************************************************************************/
00345 /*****************************************************************************/
00346 
00347 void addClassLoaderOwnerForAllExistingMetaObjectsForLibrary(const std::string& library_path, ClassLoader* loader)
00348 /*****************************************************************************/
00349 {
00350   MetaObjectVector all_meta_objs = allMetaObjectsForLibrary(library_path);
00351   for(unsigned int c = 0; c < all_meta_objs.size(); c++)
00352   {
00353     AbstractMetaObjectBase* meta_obj = all_meta_objs.at(c);
00354     CONSOLE_BRIDGE_logDebug("class_loader.class_loader_private: Tagging existing MetaObject %p (base = %s, derived = %s) with class loader %p (library path = %s).", meta_obj, meta_obj->baseClassName().c_str(), meta_obj->className().c_str(), loader, loader ? loader->getLibraryPath().c_str() : "NULL");
00355     all_meta_objs.at(c)->addOwningClassLoader(loader);
00356   }
00357 }
00358 
00359 void revivePreviouslyCreateMetaobjectsFromGraveyard(const std::string& library_path, ClassLoader* loader)
00360 /*****************************************************************************/
00361 {
00362   boost::recursive_mutex::scoped_lock b2fmm_lock(getPluginBaseToFactoryMapMapMutex());
00363   MetaObjectVector& graveyard = getMetaObjectGraveyard();
00364 
00365   for(MetaObjectVector::iterator itr = graveyard.begin(); itr != graveyard.end(); itr++)
00366   {
00367     AbstractMetaObjectBase* obj = *itr;
00368     if(obj->getAssociatedLibraryPath() == library_path)
00369     {
00370       CONSOLE_BRIDGE_logDebug("class_loader.class_loader_private: Resurrected factory metaobject from graveyard, class = %s, base_class = %s ptr = %p...bound to ClassLoader %p (library path = %s)", obj->className().c_str(), obj->baseClassName().c_str(), obj, loader, loader ? loader->getLibraryPath().c_str() : "NULL");
00371 
00372       obj->addOwningClassLoader(loader);
00373       assert(obj->typeidBaseClassName() != "UNSET");
00374       FactoryMap& factory = getFactoryMapForBaseClass(obj->typeidBaseClassName());
00375       factory[obj->className()] = obj;
00376     }
00377   }
00378 }
00379 
00380 void purgeGraveyardOfMetaobjects(const std::string& library_path, ClassLoader* loader, bool delete_objs)
00381 /*****************************************************************************/
00382 {
00383   MetaObjectVector all_meta_objs = allMetaObjects();
00384   boost::recursive_mutex::scoped_lock b2fmm_lock(getPluginBaseToFactoryMapMapMutex()); //Note: Lock must happen after call to allMetaObjects as that will lock
00385 
00386   MetaObjectVector& graveyard = getMetaObjectGraveyard();
00387   MetaObjectVector::iterator itr = graveyard.begin();
00388 
00389   while(itr != graveyard.end())
00390   {
00391     AbstractMetaObjectBase* obj = *itr;
00392     if(obj->getAssociatedLibraryPath() == library_path)
00393     {
00394       CONSOLE_BRIDGE_logDebug("class_loader.class_loader_private: Purging factory metaobject from graveyard, class = %s, base_class = %s ptr = %p...bound to ClassLoader %p (library path = %s)", obj->className().c_str(), obj->baseClassName().c_str(), obj, loader, loader ? loader->getLibraryPath().c_str() : "NULL");
00395 
00396       bool is_address_in_graveyard_same_as_global_factory_map = std::find(all_meta_objs.begin(), all_meta_objs.end(), *itr) != all_meta_objs.end();
00397       itr = graveyard.erase(itr);
00398       if(delete_objs)
00399       {
00400         if(is_address_in_graveyard_same_as_global_factory_map)
00401           CONSOLE_BRIDGE_logDebug("class_loader.class_loader_private: Newly created metaobject factory in global factory map map has same address as one in graveyard -- metaobject has been purged from graveyard but not deleted.");
00402         else
00403         {
00404           assert(hasANonPurePluginLibraryBeenOpened() == false);
00405           CONSOLE_BRIDGE_logDebug("class_loader.class_loader_private: Also destroying metaobject %p (class = %s, base_class = %s, library_path = %s) in addition to purging it from graveyard.", obj, obj->className().c_str(), obj->baseClassName().c_str(), obj->getAssociatedLibraryPath().c_str());
00406           delete(obj); //Note: This is the only place where metaobjects can be destroyed
00407         }
00408       }
00409     }
00410     else
00411       itr++;
00412   }
00413 }
00414 
00415 void loadLibrary(const std::string& library_path, ClassLoader* loader)
00416 /*****************************************************************************/
00417 {
00418   static boost::recursive_mutex loader_mutex;
00419   CONSOLE_BRIDGE_logDebug("class_loader.class_loader_private: Attempting to load library %s on behalf of ClassLoader handle %p...\n", library_path.c_str(), loader);
00420   boost::recursive_mutex::scoped_lock loader_lock(loader_mutex);
00421 
00422   //If it's already open, just update existing metaobjects to have an additional owner.
00423   if(isLibraryLoadedByAnybody(library_path))
00424   {
00425     boost::recursive_mutex::scoped_lock lock(getPluginBaseToFactoryMapMapMutex());
00426     CONSOLE_BRIDGE_logDebug("class_loader.class_loader_private: Library already in memory, but binding existing MetaObjects to loader if necesesary.\n");
00427     addClassLoaderOwnerForAllExistingMetaObjectsForLibrary(library_path, loader);
00428     return;
00429   }
00430 
00431   Poco::SharedLibrary* library_handle = NULL;
00432 
00433   {
00434 
00435     try
00436     {
00437       setCurrentlyActiveClassLoader(loader);
00438       setCurrentlyLoadingLibraryName(library_path);
00439       library_handle = new Poco::SharedLibrary(library_path);
00440     }
00441     catch(const Poco::LibraryLoadException& e)
00442     {
00443       setCurrentlyLoadingLibraryName("");
00444       setCurrentlyActiveClassLoader(NULL);
00445       throw(class_loader::LibraryLoadException("Could not load library (Poco exception = " + std::string(e.message()) + ")"));
00446     }
00447     catch(const Poco::LibraryAlreadyLoadedException& e)
00448     {
00449       setCurrentlyLoadingLibraryName("");
00450       setCurrentlyActiveClassLoader(NULL);
00451       throw(class_loader::LibraryLoadException("Library already loaded (Poco exception = " + std::string(e.message()) + ")"));
00452     }
00453     catch(const Poco::NotFoundException& e)
00454     {
00455       setCurrentlyLoadingLibraryName("");
00456       setCurrentlyActiveClassLoader(NULL);
00457       throw(class_loader::LibraryLoadException("Library not found (Poco exception = " + std::string(e.message()) + ")"));
00458     }
00459 
00460     setCurrentlyLoadingLibraryName("");
00461     setCurrentlyActiveClassLoader(NULL);
00462   }
00463 
00464   assert(library_handle != NULL);
00465   CONSOLE_BRIDGE_logDebug("class_loader.class_loader_private: Successfully loaded library %s into memory (Poco::SharedLibrary handle = %p).", library_path.c_str(), library_handle);
00466 
00467   //Graveyard scenario
00468   unsigned int num_lib_objs = allMetaObjectsForLibrary(library_path).size();
00469   if(num_lib_objs == 0)
00470   {
00471     CONSOLE_BRIDGE_logDebug("class_loader.class_loader_private: Though the library %s was just loaded, it seems no factory metaobjects were registered. Checking factory graveyard for previously loaded metaobjects...", library_path.c_str());
00472     revivePreviouslyCreateMetaobjectsFromGraveyard(library_path, loader);
00473     purgeGraveyardOfMetaobjects(library_path, loader, false); //Note: The 'false' indicates we don't want to invoke delete on the metaobject
00474   }
00475   else
00476   {
00477     CONSOLE_BRIDGE_logDebug("class_loader.class_loader_private: Library %s generated new factory metaobjects on load. Destroying graveyarded objects from previous loads...", library_path.c_str());
00478     purgeGraveyardOfMetaobjects(library_path, loader, true);
00479   }
00480 
00481   //Insert library into global loaded library vectory
00482   boost::recursive_mutex::scoped_lock llv_lock(getLoadedLibraryVectorMutex());
00483   LibraryVector& open_libraries =  getLoadedLibraryVector();
00484   open_libraries.push_back(LibraryPair(library_path, library_handle)); //Note: Poco::SharedLibrary automatically calls load() when library passed to constructor
00485 }
00486 
00487 void unloadLibrary(const std::string& library_path, ClassLoader* loader)
00488 /*****************************************************************************/
00489 {
00490   if(hasANonPurePluginLibraryBeenOpened())
00491   {
00492     CONSOLE_BRIDGE_logDebug("class_loader.class_loader_private: Cannot unload %s or ANY other library as a non-pure plugin library was opened. As class_loader has no idea which libraries class factories were exported from, it can safely close any library without potentially unlinking symbols that are still actively being used. You must refactor your plugin libraries to be made exclusively of plugins in order for this error to stop happening.", library_path.c_str());
00493   }
00494   else
00495   {
00496     CONSOLE_BRIDGE_logDebug("class_loader.class_loader_private: Unloading library %s on behalf of ClassLoader %p...", library_path.c_str(), loader);
00497     boost::recursive_mutex::scoped_lock lock(getLoadedLibraryVectorMutex());
00498     LibraryVector& open_libraries =  getLoadedLibraryVector();
00499     LibraryVector::iterator itr = findLoadedLibrary(library_path);
00500     if(itr != open_libraries.end())
00501     {
00502       Poco::SharedLibrary* library = itr->second;
00503       std::string library_path = itr->first;
00504       try
00505       {
00506         destroyMetaObjectsForLibrary(library_path, loader);
00507 
00508         //Remove from loaded library list as well if no more factories associated with said library
00509         if(!areThereAnyExistingMetaObjectsForLibrary(library_path))
00510         {
00511           CONSOLE_BRIDGE_logDebug("class_loader.class_loader_private: There are no more MetaObjects left for %s so unloading library and removing from loaded library vector.\n", library_path.c_str());
00512           library->unload();
00513           assert(library->isLoaded() == false);
00514           delete(library);
00515           itr = open_libraries.erase(itr);
00516         }
00517         else
00518           CONSOLE_BRIDGE_logDebug("class_loader.class_loader_private: MetaObjects still remain in memory meaning other ClassLoaders are still using library, keeping library %s open.", library_path.c_str());
00519         return;
00520       }
00521       catch(const Poco::RuntimeException& e)
00522       {
00523         delete(library);
00524         throw(class_loader::LibraryUnloadException("Could not unload library (Poco exception = " + std::string(e.message()) + ")"));
00525       }
00526     }
00527     throw(class_loader::LibraryUnloadException("Attempt to unload library that class_loader is unaware of."));
00528   }
00529 }
00530 
00531 
00532 //Other
00533 /*****************************************************************************/
00534 /*****************************************************************************/
00535 /*****************************************************************************/
00536 
00537 void printDebugInfoToScreen()
00538 /*****************************************************************************/
00539 {
00540   printf("*******************************************************************************\n");
00541   printf("*****               class_loader_private DEBUG INFORMATION                   *****\n");
00542   printf("*******************************************************************************\n");
00543 
00544   printf("OPEN LIBRARIES IN MEMORY:\n");
00545   printf("--------------------------------------------------------------------------------\n");
00546   boost::recursive_mutex::scoped_lock lock(getLoadedLibraryVectorMutex());
00547   LibraryVector libs = getLoadedLibraryVector();
00548   for(unsigned int c = 0; c < libs.size(); c++)
00549     printf("Open library %i = %s (Poco SharedLibrary handle = %p)\n", c, (libs.at(c)).first.c_str(), (libs.at(c)).second);
00550 
00551   printf("METAOBJECTS (i.e. FACTORIES) IN MEMORY:\n");
00552   printf("--------------------------------------------------------------------------------\n");
00553   MetaObjectVector meta_objs = allMetaObjects();
00554   for(unsigned int c = 0; c < meta_objs.size(); c++)
00555   {
00556     AbstractMetaObjectBase* obj = meta_objs.at(c);
00557     printf("Metaobject %i (ptr = %p):\n TypeId = %s\n Associated Library = %s\n",
00558            c,
00559            obj,
00560            (typeid(*obj).name()),
00561            obj->getAssociatedLibraryPath().c_str());
00562 
00563     ClassLoaderVector loaders = obj->getAssociatedClassLoaders();
00564     for(unsigned int i = 0; i < loaders.size(); i++)
00565       printf(" Associated Loader %i = %p\n", i, loaders.at(i));
00566     printf("--------------------------------------------------------------------------------\n");
00567   }
00568 
00569   printf("********************************** END DEBUG **********************************\n");
00570   printf("*******************************************************************************\n\n");
00571 }
00572 
00573 
00574 
00575 
00576 } //End namespace class_loader_private
00577 } //End namespace class_loader


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