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   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   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   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     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       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       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           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           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   logDebug("class_loader.class_loader_private: Attempting to load library %s on behalf of ClassLoader handle %p...\n", library_path.c_str(), loader);
00419 
00420   //If it's already open, just update existing metaobjects to have an additional owner.
00421   if(isLibraryLoadedByAnybody(library_path))
00422   {
00423     logDebug("class_loader.class_loader_private: Library already in memory, but binding existing MetaObjects to loader if necesesary.\n");
00424     addClassLoaderOwnerForAllExistingMetaObjectsForLibrary(library_path, loader);
00425     return;
00426   }
00427   
00428   Poco::SharedLibrary* library_handle = NULL;
00429   static boost::recursive_mutex loader_mutex;
00430 
00431   {
00432     boost::recursive_mutex::scoped_lock loader_lock(loader_mutex);
00433 
00434     try
00435     {
00436       setCurrentlyActiveClassLoader(loader);
00437       setCurrentlyLoadingLibraryName(library_path);
00438       library_handle = new Poco::SharedLibrary(library_path);
00439     }
00440     catch(const Poco::LibraryLoadException& e)
00441     {
00442       setCurrentlyLoadingLibraryName("");
00443       setCurrentlyActiveClassLoader(NULL);
00444       throw(class_loader::LibraryLoadException("Could not load library (Poco exception = " + std::string(e.message()) + ")"));
00445     }
00446     catch(const Poco::LibraryAlreadyLoadedException& e)
00447     {
00448       setCurrentlyLoadingLibraryName("");
00449       setCurrentlyActiveClassLoader(NULL);
00450       throw(class_loader::LibraryLoadException("Library already loaded (Poco exception = " + std::string(e.message()) + ")"));
00451     }
00452     catch(const Poco::NotFoundException& e)
00453     {
00454       setCurrentlyLoadingLibraryName("");
00455       setCurrentlyActiveClassLoader(NULL);
00456       throw(class_loader::LibraryLoadException("Library not found (Poco exception = " + std::string(e.message()) + ")"));
00457     }
00458 
00459     setCurrentlyLoadingLibraryName("");
00460     setCurrentlyActiveClassLoader(NULL);
00461   }
00462 
00463   assert(library_handle != NULL);
00464   logDebug("class_loader.class_loader_private: Successfully loaded library %s into memory (Poco::SharedLibrary handle = %p).", library_path.c_str(), library_handle);
00465 
00466   //Graveyard scenario
00467   unsigned int num_lib_objs = allMetaObjectsForLibrary(library_path).size();
00468   if(num_lib_objs == 0)
00469   {
00470     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());
00471     revivePreviouslyCreateMetaobjectsFromGraveyard(library_path, loader);
00472     purgeGraveyardOfMetaobjects(library_path, loader, false); //Note: The 'false' indicates we don't want to invoke delete on the metaobject
00473   }
00474   else
00475   {
00476     logDebug("class_loader.class_loader_private: Library %s generated new factory metaobjects on load. Destroying graveyarded objects from previous loads...", library_path.c_str());
00477     purgeGraveyardOfMetaobjects(library_path, loader, true);
00478   }
00479 
00480   //Insert library into global loaded library vectory
00481   boost::recursive_mutex::scoped_lock llv_lock(getLoadedLibraryVectorMutex());
00482   LibraryVector& open_libraries =  getLoadedLibraryVector();
00483   open_libraries.push_back(LibraryPair(library_path, library_handle)); //Note: Poco::SharedLibrary automatically calls load() when library passed to constructor
00484 }
00485 
00486 void unloadLibrary(const std::string& library_path, ClassLoader* loader)
00487 /*****************************************************************************/
00488 { 
00489   if(hasANonPurePluginLibraryBeenOpened())
00490   {
00491     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());
00492   }
00493   else
00494   { 
00495     logDebug("class_loader.class_loader_private: Unloading library %s on behalf of ClassLoader %p...", library_path.c_str(), loader);
00496     boost::recursive_mutex::scoped_lock lock(getLoadedLibraryVectorMutex());
00497     LibraryVector& open_libraries =  getLoadedLibraryVector();
00498     LibraryVector::iterator itr = findLoadedLibrary(library_path);
00499     if(itr != open_libraries.end())
00500     {
00501       Poco::SharedLibrary* library = itr->second;
00502       std::string library_path = itr->first;
00503       try
00504       {
00505         destroyMetaObjectsForLibrary(library_path, loader);
00506      
00507         //Remove from loaded library list as well if no more factories associated with said library
00508         if(!areThereAnyExistingMetaObjectsForLibrary(library_path))
00509         {
00510           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());
00511           library->unload();          
00512           assert(library->isLoaded() == false);
00513           delete(library);
00514           itr = open_libraries.erase(itr);
00515         }
00516         else
00517           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());
00518         return;
00519       }
00520       catch(const Poco::RuntimeException& e)
00521       {
00522         delete(library);
00523         throw(class_loader::LibraryUnloadException("Could not unload library (Poco exception = " + std::string(e.message()) + ")"));
00524       }
00525     }
00526     throw(class_loader::LibraryUnloadException("Attempt to unload library that class_loader is unaware of."));
00527   }
00528 }
00529 
00530 
00531 //Other
00532 /*****************************************************************************/
00533 /*****************************************************************************/
00534 /*****************************************************************************/
00535 
00536 void printDebugInfoToScreen()
00537 /*****************************************************************************/
00538 {
00539   printf("*******************************************************************************\n");
00540   printf("*****               class_loader_private DEBUG INFORMATION                   *****\n");
00541   printf("*******************************************************************************\n");
00542 
00543   printf("OPEN LIBRARIES IN MEMORY:\n");
00544   printf("--------------------------------------------------------------------------------\n");
00545   boost::recursive_mutex::scoped_lock lock(getLoadedLibraryVectorMutex());
00546   LibraryVector libs = getLoadedLibraryVector();
00547   for(unsigned int c = 0; c < libs.size(); c++)
00548     printf("Open library %i = %s (Poco SharedLibrary handle = %p)\n", c, (libs.at(c)).first.c_str(), (libs.at(c)).second);
00549 
00550   printf("METAOBJECTS (i.e. FACTORIES) IN MEMORY:\n");
00551   printf("--------------------------------------------------------------------------------\n");
00552   MetaObjectVector meta_objs = allMetaObjects();
00553   for(unsigned int c = 0; c < meta_objs.size(); c++)
00554   {
00555     AbstractMetaObjectBase* obj = meta_objs.at(c);
00556     printf("Metaobject %i (ptr = %p):\n TypeId = %s\n Associated Library = %s\n", 
00557            c, 
00558            obj, 
00559            (typeid(*obj).name()), 
00560            obj->getAssociatedLibraryPath().c_str());
00561   
00562     ClassLoaderVector loaders = obj->getAssociatedClassLoaders();
00563     for(unsigned int i = 0; i < loaders.size(); i++)
00564       printf(" Associated Loader %i = %p\n", i, loaders.at(i));
00565     printf("--------------------------------------------------------------------------------\n");
00566   }
00567 
00568   printf("********************************** END DEBUG **********************************\n");
00569   printf("*******************************************************************************\n\n");
00570 }
00571 
00572 
00573 
00574 
00575 } //End namespace class_loader_private
00576 } //End namespace class_loader


class_loader
Author(s): Mirza Shah
autogenerated on Fri Aug 28 2015 10:17:12