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


class_loader
Author(s): Mirza Shah
autogenerated on Sun Oct 5 2014 22:50:57