33 #include <Poco/SharedLibrary.h>
50 static boost::recursive_mutex m;
56 static boost::recursive_mutex m;
69 std::string base_class_name = typeid_base_class_name;
70 if (factoryMapMap.find(base_class_name) == factoryMapMap.end()) {
74 return factoryMapMap[base_class_name];
91 static std::string library_name;
103 library_name_ref = library_name;
145 for (
auto & it : factories) {
146 all_meta_objs.push_back(it.second);
148 return all_meta_objs;
157 BaseToFactoryMapMap::iterator itr;
159 for (
auto & it : factory_map_map) {
161 all_meta_objs.insert(all_meta_objs.end(), objs.begin(), objs.end());
163 return all_meta_objs;
170 for (
auto & f : to_filter) {
171 if (f->isOwnedBy(owner)) {
172 filtered_objs.push_back(f);
175 return filtered_objs;
183 for (
auto & f : to_filter) {
184 if (f->getAssociatedLibraryPath() == library_path) {
185 filtered_objs.push_back(f);
188 return filtered_objs;
211 CONSOLE_BRIDGE_logDebug(
212 "class_loader.impl: "
213 "Inserting MetaObject (class = %s, base_class = %s, ptr = %p) into graveyard",
215 reinterpret_cast<void *
>(meta_obj));
222 FactoryMap::iterator factory_itr = factories.begin();
223 while (factory_itr != factories.end()) {
228 FactoryMap::iterator factory_itr_copy = factory_itr;
233 factories.erase(factory_itr_copy);
257 CONSOLE_BRIDGE_logDebug(
258 "class_loader.impl: "
259 "Removing MetaObjects associated with library %s and class loader %p from global "
260 "plugin-to-factorymap map.\n",
261 library_path.c_str(),
reinterpret_cast<const void *
>(loader));
265 for (
auto & it : factory_map_map) {
269 CONSOLE_BRIDGE_logDebug(
"%s",
"class_loader.impl: Metaobjects removed.");
281 for (
auto it = open_libraries.begin(); it != open_libraries.end(); ++it) {
282 if (it->first == library_path) {
286 return open_libraries.end();
296 if (itr != open_libraries.end()) {
297 assert(itr->second->isLoaded() ==
true);
308 size_t num_meta_objs_for_lib_bound_to_loader =
310 bool are_meta_objs_bound_to_loader =
311 (0 == num_meta_objs_for_lib) ?
true : (
312 num_meta_objs_for_lib_bound_to_loader <= num_meta_objs_for_lib);
314 return is_lib_loaded_by_anyone && are_meta_objs_bound_to_loader;
320 std::vector<std::string> all_libs;
321 for (
auto & meta_obj : all_loader_meta_objs) {
322 std::string lib_path = meta_obj->getAssociatedLibraryPath();
323 if (std::find(all_libs.begin(), all_libs.end(), lib_path) == all_libs.end()) {
324 all_libs.push_back(lib_path);
334 const std::string & library_path,
ClassLoader * loader)
337 for (
auto & meta_obj : all_meta_objs) {
338 CONSOLE_BRIDGE_logDebug(
339 "class_loader.impl: "
340 "Tagging existing MetaObject %p (base = %s, derived = %s) with "
341 "class loader %p (library path = %s).",
342 reinterpret_cast<void *
>(meta_obj), meta_obj->baseClassName().c_str(),
343 meta_obj->className().c_str(),
344 reinterpret_cast<void *
>(loader),
346 meta_obj->addOwningClassLoader(loader);
351 const std::string & library_path,
ClassLoader * loader)
356 for (
auto & obj : graveyard) {
357 if (obj->getAssociatedLibraryPath() == library_path) {
358 CONSOLE_BRIDGE_logDebug(
359 "class_loader.impl: "
360 "Resurrected factory metaobject from graveyard, class = %s, base_class = %s ptr = %p..."
361 "bound to ClassLoader %p (library path = %s)",
362 obj->className().c_str(), obj->baseClassName().c_str(),
reinterpret_cast<void *
>(obj),
363 reinterpret_cast<void *
>(loader),
366 obj->addOwningClassLoader(loader);
367 assert(obj->typeidBaseClassName() !=
"UNSET");
369 factory[obj->className()] = obj;
375 const std::string & library_path,
ClassLoader * loader,
bool delete_objs)
382 MetaObjectVector::iterator itr = graveyard.begin();
384 while (itr != graveyard.end()) {
387 CONSOLE_BRIDGE_logDebug(
388 "class_loader.impl: "
389 "Purging factory metaobject from graveyard, class = %s, base_class = %s ptr = %p.."
390 ".bound to ClassLoader %p (library path = %s)",
392 reinterpret_cast<void *
>(loader),
395 bool is_address_in_graveyard_same_as_global_factory_map =
396 std::find(all_meta_objs.begin(), all_meta_objs.end(), *itr) != all_meta_objs.end();
397 itr = graveyard.erase(itr);
399 if (is_address_in_graveyard_same_as_global_factory_map) {
400 CONSOLE_BRIDGE_logDebug(
"%s",
401 "class_loader.impl: "
402 "Newly created metaobject factory in global factory map map has same address as "
403 "one in graveyard -- metaobject has been purged from graveyard but not deleted.");
406 CONSOLE_BRIDGE_logDebug(
407 "class_loader.impl: "
408 "Also destroying metaobject %p (class = %s, base_class = %s, library_path = %s) "
409 "in addition to purging it from graveyard.",
413 #pragma GCC diagnostic push
414 #pragma GCC diagnostic ignored "-Wdelete-non-virtual-dtor"
418 #pragma GCC diagnostic pop
430 static boost::recursive_mutex loader_mutex;
431 CONSOLE_BRIDGE_logDebug(
432 "class_loader.impl: "
433 "Attempting to load library %s on behalf of ClassLoader handle %p...\n",
434 library_path.c_str(),
reinterpret_cast<void *
>(loader));
435 boost::recursive_mutex::scoped_lock loader_lock(loader_mutex);
440 CONSOLE_BRIDGE_logDebug(
"%s",
441 "class_loader.impl: "
442 "Library already in memory, but binding existing MetaObjects to loader if necesesary.\n");
447 Poco::SharedLibrary * library_handle =
nullptr;
453 library_handle =
new Poco::SharedLibrary(library_path);
454 }
catch (
const Poco::LibraryLoadException & e) {
458 "Could not load library (Poco exception = " + std::string(e.message()) +
")");
459 }
catch (
const Poco::LibraryAlreadyLoadedException & e) {
463 "Library already loaded (Poco exception = " + std::string(e.message()) +
")");
464 }
catch (
const Poco::NotFoundException & e) {
468 "Library not found (Poco exception = " + std::string(e.message()) +
")");
475 assert(library_handle !=
nullptr);
476 CONSOLE_BRIDGE_logDebug(
477 "class_loader.impl: "
478 "Successfully loaded library %s into memory (Poco::SharedLibrary handle = %p).",
479 library_path.c_str(),
reinterpret_cast<void *
>(library_handle));
483 if (0 == num_lib_objs) {
484 CONSOLE_BRIDGE_logDebug(
485 "class_loader.impl: "
486 "Though the library %s was just loaded, it seems no factory metaobjects were registered. "
487 "Checking factory graveyard for previously loaded metaobjects...",
488 library_path.c_str());
493 CONSOLE_BRIDGE_logDebug(
494 "class_loader.impl: "
495 "Library %s generated new factory metaobjects on load. "
496 "Destroying graveyarded objects from previous loads...",
497 library_path.c_str());
505 open_libraries.push_back(
LibraryPair(library_path, library_handle));
511 CONSOLE_BRIDGE_logDebug(
512 "class_loader.impl: "
513 "Cannot unload %s or ANY other library as a non-pure plugin library was opened. "
514 "As class_loader has no idea which libraries class factories were exported from, "
515 "it can safely close any library without potentially unlinking symbols that are still "
516 "actively being used. "
517 "You must refactor your plugin libraries to be made exclusively of plugins "
518 "in order for this error to stop happening.",
519 library_path.c_str());
521 CONSOLE_BRIDGE_logDebug(
522 "class_loader.impl: "
523 "Unloading library %s on behalf of ClassLoader %p...",
524 library_path.c_str(),
reinterpret_cast<void *
>(loader));
528 if (itr != open_libraries.end()) {
529 Poco::SharedLibrary * library = itr->second;
530 std::string library_path = itr->first;
536 CONSOLE_BRIDGE_logDebug(
537 "class_loader.impl: "
538 "There are no more MetaObjects left for %s so unloading library and "
539 "removing from loaded library vector.\n",
540 library_path.c_str());
542 assert(library->isLoaded() ==
false);
544 itr = open_libraries.erase(itr);
546 CONSOLE_BRIDGE_logDebug(
547 "class_loader.impl: "
548 "MetaObjects still remain in memory meaning other ClassLoaders are still using library"
549 ", keeping library %s open.",
550 library_path.c_str());
553 }
catch (
const Poco::RuntimeException & e) {
556 "Caught a poco exception while unloading library " + library_path +
": " + e.message());
560 "Attempt to unload library that class_loader is unaware of: " + library_path);
569 printf(
"*******************************************************************************\n");
570 printf(
"***** class_loader impl DEBUG INFORMATION *****\n");
571 printf(
"*******************************************************************************\n");
573 printf(
"OPEN LIBRARIES IN MEMORY:\n");
574 printf(
"--------------------------------------------------------------------------------\n");
577 for (
size_t c = 0; c < libs.size(); c++) {
579 "Open library %zu = %s (Poco SharedLibrary handle = %p)\n",
580 c, (libs.at(c)).first.c_str(),
reinterpret_cast<void *
>((libs.at(c)).second));
583 printf(
"METAOBJECTS (i.e. FACTORIES) IN MEMORY:\n");
584 printf(
"--------------------------------------------------------------------------------\n");
586 for (
size_t c = 0; c < meta_objs.size(); c++) {
588 printf(
"Metaobject %zu (ptr = %p):\n TypeId = %s\n Associated Library = %s\n",
590 reinterpret_cast<void *
>(obj),
591 (
typeid(*obj).name()),
595 for (
size_t i = 0; i < loaders.size(); i++) {
596 printf(
" Associated Loader %zu = %p\n", i,
reinterpret_cast<void *
>(loaders.at(i)));
598 printf(
"--------------------------------------------------------------------------------\n");
601 printf(
"********************************** END DEBUG **********************************\n");
602 printf(
"*******************************************************************************\n\n");