Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions include/class_loader/class_loader_core.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,23 @@ registerPlugin(const std::string & class_name, const std::string & base_class_na
break;
}
}

BaseToFactoryMapMap & factory_map_map = getGlobalPluginBaseToFactoryMapMap();
bool erase_flag = false;
for (auto & factory_map_item : factory_map_map) {
FactoryMap & factory_map = factory_map_item.second;
for (auto iter = factory_map.begin(); iter != factory_map.end(); ++iter) {
if (iter->second == p) {
factory_map.erase(iter);
erase_flag = true;
break;
}
}
if (erase_flag) {
break;
}
}

getPluginBaseToFactoryMapMapMutex().unlock();

#ifndef _WIN32
Expand Down
2 changes: 1 addition & 1 deletion src/class_loader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,10 +117,10 @@ int ClassLoader::unloadLibrary()

int ClassLoader::unloadLibraryInternal(bool lock_plugin_ref_count)
{
std::lock_guard<std::recursive_mutex> load_ref_lock(load_ref_count_mutex_);
if (lock_plugin_ref_count) {
plugin_ref_count_mutex_.lock();
}
std::lock_guard<std::recursive_mutex> load_ref_lock(load_ref_count_mutex_);

try {
if (plugin_ref_count_ > 0) {
Expand Down
7 changes: 5 additions & 2 deletions src/class_loader_core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -521,9 +521,12 @@ void unloadLibrary(const std::string & library_path, ClassLoader * loader)
throw class_loader::LibraryUnloadException(
"Could not unload library (rcpputils exception = " + std::string(e.what()) + ")");
}
} else {
CONSOLE_BRIDGE_logDebug(
"class_loader.impl: "
"Attempt to unload library %s that class_loader is unaware of or is already unloaded",
library_path.c_str());
}
throw class_loader::LibraryUnloadException(
"Attempt to unload library that class_loader is unaware of.");
}
}

Expand Down
50 changes: 47 additions & 3 deletions src/multi_library_class_loader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,47 @@
namespace class_loader
{

typedef std::vector<std::shared_ptr<class_loader::ClassLoader>> ClassLoaderPtrVector;

class ClassLoaderDependency
{
protected:
ClassLoaderDependency()
{
// make the static variable in `ClassLoader` destroyed after `class_loader_ptrs_`,
// which is a member of ClassLoaderPtrVectorImpl defined as a static instance in the
// `getClassLoaderPtrVectorImpl`
class_loader::impl::getLoadedLibraryVectorMutex();
class_loader::impl::getPluginBaseToFactoryMapMapMutex();
class_loader::impl::getGlobalPluginBaseToFactoryMapMap();
class_loader::impl::getMetaObjectGraveyard();
class_loader::impl::getLoadedLibraryVector();
class_loader::impl::getCurrentlyLoadingLibraryName();
class_loader::impl::getCurrentlyActiveClassLoader();
class_loader::impl::hasANonPurePluginLibraryBeenOpened();
}
};

class ClassLoaderPtrVectorImpl : public ClassLoaderDependency
{
public:
ClassLoaderPtrVector class_loader_ptrs_;
std::mutex loader_mutex_;
};

class MultiLibraryClassLoaderImpl
{
public:
bool enable_ondemand_loadunload_;
LibraryToClassLoaderMap active_class_loaders_;
std::mutex loader_mutex_;
};

ClassLoaderPtrVectorImpl & getClassLoaderPtrVectorImpl()
{
static ClassLoaderPtrVectorImpl instance;
return instance;
}

MultiLibraryClassLoader::MultiLibraryClassLoader(bool enable_ondemand_loadunload)
: impl_(new MultiLibraryClassLoaderImpl())
{
Expand Down Expand Up @@ -92,8 +125,12 @@ bool MultiLibraryClassLoader::isLibraryAvailable(const std::string & library_nam
void MultiLibraryClassLoader::loadLibrary(const std::string & library_path)
{
if (!isLibraryAvailable(library_path)) {
std::lock_guard<std::mutex> lock(getClassLoaderPtrVectorImpl().loader_mutex_);
getClassLoaderPtrVectorImpl().class_loader_ptrs_.emplace_back(
std::make_shared<class_loader::ClassLoader>(library_path, isOnDemandLoadUnloadEnabled())
);
impl_->active_class_loaders_[library_path] =
new class_loader::ClassLoader(library_path, isOnDemandLoadUnloadEnabled());
getClassLoaderPtrVectorImpl().class_loader_ptrs_.back().get();
}
}

Expand All @@ -112,7 +149,14 @@ int MultiLibraryClassLoader::unloadLibrary(const std::string & library_path)
remaining_unloads = loader->unloadLibrary();
if (remaining_unloads == 0) {
impl_->active_class_loaders_[library_path] = nullptr;
delete (loader);
std::lock_guard<std::mutex> lock(getClassLoaderPtrVectorImpl().loader_mutex_);
auto & class_loader_ptrs = getClassLoaderPtrVectorImpl().class_loader_ptrs_;
for (auto iter = class_loader_ptrs.begin(); iter != class_loader_ptrs.end(); ++iter) {
if (iter->get() == loader) {
class_loader_ptrs.erase(iter);
break;
}
}
}
}
return remaining_unloads;
Expand Down
3 changes: 0 additions & 3 deletions test/unique_ptr_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,6 @@ TEST(ClassLoaderUniquePtrTest, basicLoadFailures) {
EXPECT_THROW(
class_loader::impl::loadLibrary("LIBRARY_1", &loader1),
class_loader::LibraryLoadException);
EXPECT_THROW(
class_loader::impl::unloadLibrary("LIBRARY_1", &loader1),
class_loader::LibraryUnloadException);
}

TEST(ClassLoaderUniquePtrTest, MultiLibraryClassLoaderFailures) {
Expand Down
3 changes: 0 additions & 3 deletions test/utest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,6 @@ TEST(ClassLoaderUniquePtrTest, basicLoadFailures) {
EXPECT_THROW(
class_loader::impl::loadLibrary("LIBRARY_1", &loader1),
class_loader::LibraryLoadException);
EXPECT_THROW(
class_loader::impl::unloadLibrary("LIBRARY_1", &loader1),
class_loader::LibraryUnloadException);
}

TEST(ClassLoaderUniquePtrTest, MultiLibraryClassLoaderFailures) {
Expand Down