33 #include <Poco/SharedLibrary.h> 41 namespace class_loader_private
53 static boost::recursive_mutex m;
60 static boost::recursive_mutex m;
75 std::string base_class_name = typeid_base_class_name;
76 if (factoryMapMap.find(base_class_name) == factoryMapMap.end()) {
80 return factoryMapMap[base_class_name];
100 static std::string library_name;
114 library_name_ref = library_name;
167 FactoryMap::const_iterator factoryItr = factories.begin();
168 factoryItr != factories.end(); factoryItr++
171 all_meta_objs.push_back(factoryItr->second);
173 return all_meta_objs;
183 BaseToFactoryMapMap::iterator itr;
185 for (itr = factory_map_map.begin(); itr != factory_map_map.end(); itr++) {
187 all_meta_objs.insert(all_meta_objs.end(), objs.begin(), objs.end());
189 return all_meta_objs;
197 for (
unsigned int c = 0; c < to_filter.size(); c++) {
198 if (to_filter.at(c)->isOwnedBy(owner)) {
199 filtered_objs.push_back(to_filter.at(c));
202 return filtered_objs;
211 for (
unsigned int c = 0; c < to_filter.size(); c++) {
212 if (to_filter.at(c)->getAssociatedLibraryPath() == library_path) {
213 filtered_objs.push_back(to_filter.at(c));
216 return filtered_objs;
244 "class_loader.class_loader_private: " 245 "Inserting MetaObject (class = %s, base_class = %s, ptr = %p) into graveyard",
254 FactoryMap::iterator factory_itr = factories.begin();
255 while (factory_itr != factories.end()) {
260 FactoryMap::iterator factory_itr_copy = factory_itr;
265 factories.erase(factory_itr_copy);
291 "class_loader.class_loader_private: " 292 "Removing MetaObjects associated with library %s and class loader %p from global " 293 "plugin-to-factorymap map.\n",
294 library_path.c_str(), loader);
298 BaseToFactoryMapMap::iterator itr;
299 for (itr = factory_map_map.begin(); itr != factory_map_map.end(); itr++) {
320 LibraryVector::iterator itr;
321 for (itr = open_libraries.begin(); itr != open_libraries.end(); itr++) {
322 if (itr->first == library_path) {
337 if (itr != open_libraries.end()) {
338 assert(itr->second->isLoaded() ==
true);
350 int num_meta_objs_for_lib_bound_to_loader =
352 bool are_meta_objs_bound_to_loader =
353 (0 == num_meta_objs_for_lib) ?
true : (
354 num_meta_objs_for_lib_bound_to_loader <= num_meta_objs_for_lib);
356 return is_lib_loaded_by_anyone && are_meta_objs_bound_to_loader;
363 std::vector<std::string> all_libs;
364 for (
unsigned int c = 0; c < all_loader_meta_objs.size(); c++) {
365 std::string lib_path = all_loader_meta_objs.at(c)->getAssociatedLibraryPath();
366 if (std::find(all_libs.begin(), all_libs.end(), lib_path) == all_libs.end()) {
367 all_libs.push_back(lib_path);
380 const std::string & library_path,
ClassLoader * loader)
384 for (
unsigned int c = 0; c < all_meta_objs.size(); c++) {
387 "class_loader.class_loader_private: " 388 "Tagging existing MetaObject %p (base = %s, derived = %s) with " 389 "class loader %p (library path = %s).",
392 all_meta_objs.at(c)->addOwningClassLoader(loader);
397 const std::string & library_path,
ClassLoader * loader)
403 for (MetaObjectVector::iterator itr = graveyard.begin(); itr != graveyard.end(); itr++) {
407 "class_loader.class_loader_private: " 408 "Resurrected factory metaobject from graveyard, class = %s, base_class = %s ptr = %p..." 409 "bound to ClassLoader %p (library path = %s)",
422 const std::string & library_path,
ClassLoader * loader,
bool delete_objs)
430 MetaObjectVector::iterator itr = graveyard.begin();
432 while (itr != graveyard.end()) {
436 "class_loader.class_loader_private: " 437 "Purging factory metaobject from graveyard, class = %s, base_class = %s ptr = %p.." 438 ".bound to ClassLoader %p (library path = %s)",
442 bool is_address_in_graveyard_same_as_global_factory_map =
443 std::find(all_meta_objs.begin(), all_meta_objs.end(), *itr) != all_meta_objs.end();
444 itr = graveyard.erase(itr);
446 if (is_address_in_graveyard_same_as_global_factory_map) {
448 "class_loader.class_loader_private: " 449 "Newly created metaobject factory in global factory map map has same address as " 450 "one in graveyard -- metaobject has been purged from graveyard but not deleted.");
454 "class_loader.class_loader_private: " 455 "Also destroying metaobject %p (class = %s, base_class = %s, library_path = %s) " 456 "in addition to purging it from graveyard.",
471 static boost::recursive_mutex loader_mutex;
473 "class_loader.class_loader_private: " 474 "Attempting to load library %s on behalf of ClassLoader handle %p...\n",
475 library_path.c_str(), loader);
476 boost::recursive_mutex::scoped_lock loader_lock(loader_mutex);
482 "class_loader.class_loader_private: " 483 "Library already in memory, but binding existing MetaObjects to loader if necesesary.\n");
488 Poco::SharedLibrary * library_handle = NULL;
494 library_handle =
new Poco::SharedLibrary(library_path);
495 }
catch (
const Poco::LibraryLoadException & e) {
499 "Could not load library (Poco exception = " + std::string(e.message()) +
")"));
500 }
catch (
const Poco::LibraryAlreadyLoadedException & e) {
504 "Library already loaded (Poco exception = " + std::string(e.message()) +
")"));
505 }
catch (
const Poco::NotFoundException & e) {
509 "Library not found (Poco exception = " + std::string(e.message()) +
")"));
516 assert(library_handle != NULL);
518 "class_loader.class_loader_private: " 519 "Successfully loaded library %s into memory (Poco::SharedLibrary handle = %p).",
520 library_path.c_str(), library_handle);
524 if (0 == num_lib_objs) {
526 "class_loader.class_loader_private: " 527 "Though the library %s was just loaded, it seems no factory metaobjects were registered. " 528 "Checking factory graveyard for previously loaded metaobjects...",
529 library_path.c_str());
535 "class_loader.class_loader_private: " 536 "Library %s generated new factory metaobjects on load. " 537 "Destroying graveyarded objects from previous loads...",
538 library_path.c_str());
546 open_libraries.push_back(
LibraryPair(library_path, library_handle));
554 "class_loader.class_loader_private: " 555 "Cannot unload %s or ANY other library as a non-pure plugin library was opened. " 556 "As class_loader has no idea which libraries class factories were exported from, " 557 "it can safely close any library without potentially unlinking symbols that are still " 558 "actively being used. " 559 "You must refactor your plugin libraries to be made exclusively of plugins " 560 "in order for this error to stop happening.",
561 library_path.c_str());
564 "class_loader.class_loader_private: " 565 "Unloading library %s on behalf of ClassLoader %p...",
566 library_path.c_str(), loader);
570 if (itr != open_libraries.end()) {
571 Poco::SharedLibrary * library = itr->second;
572 std::string library_path = itr->first;
579 "class_loader.class_loader_private: " 580 "There are no more MetaObjects left for %s so unloading library and " 581 "removing from loaded library vector.\n",
582 library_path.c_str());
584 assert(library->isLoaded() ==
false);
586 itr = open_libraries.erase(itr);
589 "class_loader.class_loader_private: " 590 "MetaObjects still remain in memory meaning other ClassLoaders are still using library" 591 ", keeping library %s open.",
592 library_path.c_str());
595 }
catch (
const Poco::RuntimeException & e) {
598 "Could not unload library (Poco exception = " + std::string(e.message()) +
")"));
602 "Attempt to unload library that class_loader is unaware of."));
615 printf(
"*******************************************************************************\n");
616 printf(
"***** class_loader_private DEBUG INFORMATION *****\n");
617 printf(
"*******************************************************************************\n");
619 printf(
"OPEN LIBRARIES IN MEMORY:\n");
620 printf(
"--------------------------------------------------------------------------------\n");
623 for (
unsigned int c = 0; c < libs.size(); c++) {
625 "Open library %i = %s (Poco SharedLibrary handle = %p)\n",
626 c, (libs.at(c)).first.c_str(), (libs.at(c)).second);
629 printf(
"METAOBJECTS (i.e. FACTORIES) IN MEMORY:\n");
630 printf(
"--------------------------------------------------------------------------------\n");
632 for (
unsigned int c = 0; c < meta_objs.size(); c++) {
634 printf(
"Metaobject %i (ptr = %p):\n TypeId = %s\n Associated Library = %s\n",
637 (
typeid(*obj).name()),
641 for (
unsigned int i = 0; i < loaders.size(); i++) {
642 printf(
" Associated Loader %i = %p\n", i, loaders.at(i));
644 printf(
"--------------------------------------------------------------------------------\n");
647 printf(
"********************************** END DEBUG **********************************\n");
648 printf(
"*******************************************************************************\n\n");
std::vector< std::string > getAllLibrariesUsedByClassLoader(const ClassLoader *loader)
This function returns the names of all libraries in use by a given class loader.
void destroyMetaObjectsForLibrary(const std::string &library_path, FactoryMap &factories, const ClassLoader *loader)
bool hasANonPurePluginLibraryBeenOpened()
Indicates if a library containing more than just plugins has been opened by the running process...
boost::recursive_mutex & getPluginBaseToFactoryMapMapMutex()
std::map< BaseClassName, FactoryMap > BaseToFactoryMapMap
void purgeGraveyardOfMetaobjects(const std::string &library_path, ClassLoader *loader, bool delete_objs)
An exception class thrown when class_loader is unable to load a runtime library.
boost::recursive_mutex & getLoadedLibraryVectorMutex()
To provide thread safety, all exposed plugin functions can only be run serially by multiple threads...
ClassLoader * getCurrentlyActiveClassLoader()
Gets the ClassLoader currently in scope which used when a library is being loaded.
BaseToFactoryMapMap & getGlobalPluginBaseToFactoryMapMap()
Gets a handle to a global data structure that holds a map of base class names (Base class describes p...
std::string getCurrentlyLoadingLibraryName()
When a library is being loaded, in order for factories to know which library they are being associate...
void addClassLoaderOwnerForAllExistingMetaObjectsForLibrary(const std::string &library_path, ClassLoader *loader)
ClassLoader *& getCurrentlyActiveClassLoaderReference()
void loadLibrary(const std::string &library_path, ClassLoader *loader)
Loads a library into memory if it has not already been done so. Attempting to load an already loaded ...
#define CONSOLE_BRIDGE_logDebug(fmt,...)
MetaObjectVector filterAllMetaObjectsOwnedBy(const MetaObjectVector &to_filter, const ClassLoader *owner)
void setCurrentlyLoadingLibraryName(const std::string &library_name)
When a library is being loaded, in order for factories to know which library they are being associate...
This class allows loading and unloading of dynamically linked libraries which contain class definitio...
bool & hasANonPurePluginLibraryBeenOpenedReference()
void unloadLibrary(const std::string &library_path, ClassLoader *loader)
Unloads a library if it loaded in memory and cleans up its corresponding class factories. If it is not loaded, the function has no effect.
std::vector< AbstractMetaObjectBase * > MetaObjectVector
LibraryVector::iterator findLoadedLibrary(const std::string &library_path)
MetaObjectVector allMetaObjectsForLibraryOwnedBy(const std::string &library_path, const ClassLoader *owner)
LibraryVector & getLoadedLibraryVector()
Gets a handle to a list of open libraries in the form of LibraryPairs which encode the library path+n...
std::vector< LibraryPair > LibraryVector
void revivePreviouslyCreateMetaobjectsFromGraveyard(const std::string &library_path, ClassLoader *loader)
void setCurrentlyActiveClassLoader(ClassLoader *loader)
Sets the ClassLoader currently in scope which used when a library is being loaded.
void insertMetaObjectIntoGraveyard(AbstractMetaObjectBase *meta_obj)
bool isLibraryLoaded(const std::string &library_path, ClassLoader *loader)
Indicates if passed library loaded within scope of a ClassLoader. The library maybe loaded in memory...
void printDebugInfoToScreen()
FactoryMap & getFactoryMapForBaseClass(const std::string &typeid_base_class_name)
This function extracts a reference to the FactoryMap for appropriate base class out of the global plu...
std::string getLibraryPath()
Gets the full-qualified path and name of the library associated with this class loader.
std::pair< LibraryPath, Poco::SharedLibrary * > LibraryPair
MetaObjectVector filterAllMetaObjectsAssociatedWithLibrary(const MetaObjectVector &to_filter, const std::string &library_path)
MetaObjectVector allMetaObjectsForClassLoader(const ClassLoader *owner)
bool areThereAnyExistingMetaObjectsForLibrary(const std::string &library_path)
MetaObjectVector & getMetaObjectGraveyard()
bool isLibraryLoadedByAnybody(const std::string &library_path)
Indicates if passed library has been loaded by ANY ClassLoader.
std::vector< class_loader::ClassLoader * > ClassLoaderVector
std::string & getCurrentlyLoadingLibraryNameReference()
MetaObjectVector allMetaObjects(const FactoryMap &factories)
std::map< ClassName, class_loader_private::AbstractMetaObjectBase * > FactoryMap
MetaObjectVector allMetaObjectsForLibrary(const std::string &library_path)
An exception class thrown when class_loader is unable to unload a runtime library.