Skip to content

Commit 0969655

Browse files
committed
Improve memory management
Signed-off-by: ahcorde <ahcorde@gmail.com>
1 parent 471c398 commit 0969655

File tree

5 files changed

+49
-29
lines changed

5 files changed

+49
-29
lines changed

include/class_loader/class_loader.hpp

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ std::string systemLibraryFormat(const std::string & library_name);
7676
* definitions from which objects can be created/destroyed during runtime (i.e. class_loader).
7777
* Libraries loaded by a ClassLoader are only accessible within scope of that ClassLoader object.
7878
*/
79-
class ClassLoader
79+
class ClassLoader : public std::enable_shared_from_this<ClassLoader>
8080
{
8181
public:
8282
template<typename Base>
@@ -122,12 +122,20 @@ class ClassLoader
122122
* @return A std::shared_ptr<Base> to newly created plugin object
123123
*/
124124
template<class Base>
125-
std::shared_ptr<Base> createInstance(const std::string & derived_class_name)
125+
std::shared_ptr<Base> createInstance(const std::string & derived_class_name,
126+
bool is_shared_ptr = false)
126127
{
127-
return std::shared_ptr<Base>(
128-
createRawInstance<Base>(derived_class_name, true),
129-
std::bind(&ClassLoader::onPluginDeletion<Base>, this, std::placeholders::_1)
130-
);
128+
if (is_shared_ptr) {
129+
return std::shared_ptr<Base>(
130+
createRawInstance<Base>(derived_class_name, true),
131+
std::bind(&ClassLoader::onPluginDeletion<Base>, shared_from_this(), std::placeholders::_1)
132+
);
133+
} else {
134+
return std::shared_ptr<Base>(
135+
createRawInstance<Base>(derived_class_name, true),
136+
std::bind(&ClassLoader::onPluginDeletion<Base>, this, std::placeholders::_1)
137+
);
138+
}
131139
}
132140

133141
/// Generates an instance of loadable classes (i.e. class_loader).
@@ -144,13 +152,21 @@ class ClassLoader
144152
* @return A std::unique_ptr<Base> to newly created plugin object.
145153
*/
146154
template<class Base>
147-
UniquePtr<Base> createUniqueInstance(const std::string & derived_class_name)
155+
UniquePtr<Base> createUniqueInstance(const std::string & derived_class_name,
156+
bool is_shared_ptr = false)
148157
{
149158
Base * raw = createRawInstance<Base>(derived_class_name, true);
150-
return std::unique_ptr<Base, DeleterType<Base>>(
151-
raw,
152-
std::bind(&ClassLoader::onPluginDeletion<Base>, this, std::placeholders::_1)
153-
);
159+
if (is_shared_ptr) {
160+
return std::unique_ptr<Base, DeleterType<Base>>(
161+
raw,
162+
std::bind(&ClassLoader::onPluginDeletion<Base>, this, std::placeholders::_1)
163+
);
164+
} else {
165+
return std::unique_ptr<Base, DeleterType<Base>>(
166+
raw,
167+
std::bind(&ClassLoader::onPluginDeletion<Base>, shared_from_this(), std::placeholders::_1)
168+
);
169+
}
154170
}
155171

156172
/// Generates an instance of loadable classes (i.e. class_loader).

include/class_loader/multi_library_class_loader.hpp

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,8 @@ namespace class_loader
5656
{
5757

5858
typedef std::string LibraryPath;
59-
typedef std::map<LibraryPath, class_loader::ClassLoader *> LibraryToClassLoaderMap;
60-
typedef std::vector<ClassLoader *> ClassLoaderVector;
59+
typedef std::map<LibraryPath, std::shared_ptr<class_loader::ClassLoader>> LibraryToClassLoaderMap;
60+
typedef std::vector<std::shared_ptr<ClassLoader>> ClassLoaderVector;
6161

6262
class MultiLibraryClassLoaderImpl;
6363

@@ -96,7 +96,7 @@ class CLASS_LOADER_PUBLIC MultiLibraryClassLoader
9696
"class_loader::MultiLibraryClassLoader: "
9797
"Attempting to create instance of class type %s.",
9898
class_name.c_str());
99-
ClassLoader * loader = getClassLoaderForClass<Base>(class_name);
99+
std::shared_ptr<class_loader::ClassLoader> loader = getClassLoaderForClass<Base>(class_name);
100100
if (nullptr == loader) {
101101
throw class_loader::CreateClassException(
102102
"MultiLibraryClassLoader: Could not create object of class type " +
@@ -105,7 +105,7 @@ class CLASS_LOADER_PUBLIC MultiLibraryClassLoader
105105
"was explicitly loaded through MultiLibraryClassLoader::loadLibrary()");
106106
}
107107

108-
return loader->createInstance<Base>(class_name);
108+
return loader->createInstance<Base>(class_name, true);
109109
}
110110

111111
/**
@@ -121,14 +121,14 @@ class CLASS_LOADER_PUBLIC MultiLibraryClassLoader
121121
std::shared_ptr<Base> createInstance(
122122
const std::string & class_name, const std::string & library_path)
123123
{
124-
ClassLoader * loader = getClassLoaderForLibrary(library_path);
124+
std::shared_ptr<class_loader::ClassLoader> loader = getClassLoaderForLibrary(library_path);
125125
if (nullptr == loader) {
126126
throw class_loader::NoClassLoaderExistsException(
127127
"Could not create instance as there is no ClassLoader in "
128128
"MultiLibraryClassLoader bound to library " + library_path +
129129
" Ensure you called MultiLibraryClassLoader::loadLibrary()");
130130
}
131-
return loader->createInstance<Base>(class_name);
131+
return loader->createInstance<Base>(class_name, true);
132132
}
133133

134134
/// Creates an instance of an object of given class name with ancestor class Base
@@ -146,7 +146,7 @@ class CLASS_LOADER_PUBLIC MultiLibraryClassLoader
146146
CONSOLE_BRIDGE_logDebug(
147147
"class_loader::MultiLibraryClassLoader: Attempting to create instance of class type %s.",
148148
class_name.c_str());
149-
ClassLoader * loader = getClassLoaderForClass<Base>(class_name);
149+
std::shared_ptr<class_loader::ClassLoader> loader = getClassLoaderForClass<Base>(class_name);
150150
if (nullptr == loader) {
151151
throw class_loader::CreateClassException(
152152
"MultiLibraryClassLoader: Could not create object of class type " + class_name +
@@ -170,14 +170,14 @@ class CLASS_LOADER_PUBLIC MultiLibraryClassLoader
170170
ClassLoader::UniquePtr<Base>
171171
createUniqueInstance(const std::string & class_name, const std::string & library_path)
172172
{
173-
ClassLoader * loader = getClassLoaderForLibrary(library_path);
173+
std::shared_ptr<class_loader::ClassLoader> loader = getClassLoaderForLibrary(library_path);
174174
if (nullptr == loader) {
175175
throw class_loader::NoClassLoaderExistsException(
176176
"Could not create instance as there is no ClassLoader in "
177177
"MultiLibraryClassLoader bound to library " + library_path +
178178
" Ensure you called MultiLibraryClassLoader::loadLibrary()");
179179
}
180-
return loader->createUniqueInstance<Base>(class_name);
180+
return loader->createUniqueInstance<Base>(class_name, true);
181181
}
182182

183183
/**
@@ -193,7 +193,7 @@ class CLASS_LOADER_PUBLIC MultiLibraryClassLoader
193193
template<class Base>
194194
Base * createUnmanagedInstance(const std::string & class_name)
195195
{
196-
ClassLoader * loader = getClassLoaderForClass<Base>(class_name);
196+
std::shared_ptr<class_loader::ClassLoader> loader = getClassLoaderForClass<Base>(class_name);
197197
if (nullptr == loader) {
198198
throw class_loader::CreateClassException(
199199
"MultiLibraryClassLoader: Could not create class of type " + class_name);
@@ -213,7 +213,7 @@ class CLASS_LOADER_PUBLIC MultiLibraryClassLoader
213213
template<class Base>
214214
Base * createUnmanagedInstance(const std::string & class_name, const std::string & library_path)
215215
{
216-
ClassLoader * loader = getClassLoaderForLibrary(library_path);
216+
std::shared_ptr<class_loader::ClassLoader> loader = getClassLoaderForLibrary(library_path);
217217
if (nullptr == loader) {
218218
throw class_loader::NoClassLoaderExistsException(
219219
"Could not create instance as there is no ClassLoader in MultiLibraryClassLoader "
@@ -273,7 +273,7 @@ class CLASS_LOADER_PUBLIC MultiLibraryClassLoader
273273
template<class Base>
274274
std::vector<std::string> getAvailableClassesForLibrary(const std::string & library_path)
275275
{
276-
ClassLoader * loader = getClassLoaderForLibrary(library_path);
276+
std::shared_ptr<class_loader::ClassLoader> loader = getClassLoaderForLibrary(library_path);
277277
if (nullptr == loader) {
278278
throw class_loader::NoClassLoaderExistsException(
279279
"There is no ClassLoader in MultiLibraryClassLoader bound to library " +
@@ -321,15 +321,15 @@ class CLASS_LOADER_PUBLIC MultiLibraryClassLoader
321321
* @param library_path - the library from which we want to create the plugin
322322
* @return A pointer to the ClassLoader*, == nullptr if not found
323323
*/
324-
ClassLoader * getClassLoaderForLibrary(const std::string & library_path);
324+
std::shared_ptr<class_loader::ClassLoader> getClassLoaderForLibrary(const std::string & library_path);
325325

326326
/// Gets a handle to the class loader corresponding to a specific class.
327327
/**
328328
* @param class_name name of class for which we want to create instance.
329329
* @return A pointer to the ClassLoader, or NULL if not found.
330330
*/
331331
template<typename Base>
332-
ClassLoader * getClassLoaderForClass(const std::string & class_name)
332+
std::shared_ptr<class_loader::ClassLoader> getClassLoaderForClass(const std::string & class_name)
333333
{
334334
ClassLoaderVector loaders = getAllAvailableClassLoaders();
335335
for (ClassLoaderVector::iterator i = loaders.begin(); i != loaders.end(); ++i) {

src/class_loader_core.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -545,6 +545,7 @@ void unloadLibrary(const std::string & library_path, ClassLoader * loader)
545545
", keeping library %s open.",
546546
library_path.c_str());
547547
}
548+
purgeGraveyardOfMetaobjects(library_path, loader, true);
548549
return;
549550
} catch (const std::runtime_error & e) {
550551
throw class_loader::LibraryUnloadException(

src/meta_object.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,9 @@ AbstractMetaObjectBase::~AbstractMetaObjectBase()
7171
"class_loader.impl.AbstractMetaObjectBase: "
7272
"Destroying MetaObject %p (base = %s, derived = %s, library path = %s)",
7373
this, baseClassName().c_str(), className().c_str(), getAssociatedLibraryPath().c_str());
74+
for (unsigned int i = 0; i < impl_->associated_class_loaders_.size(); i++) {
75+
delete impl_->associated_class_loaders_[i];
76+
}
7477
delete impl_;
7578
}
7679

src/multi_library_class_loader.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,8 @@ std::vector<std::string> MultiLibraryClassLoader::getRegisteredLibraries() const
6868
return libraries;
6969
}
7070

71-
ClassLoader * MultiLibraryClassLoader::getClassLoaderForLibrary(const std::string & library_path)
71+
std::shared_ptr<class_loader::ClassLoader> MultiLibraryClassLoader::getClassLoaderForLibrary(
72+
const std::string & library_path)
7273
{
7374
return impl_->active_class_loaders_[library_path];
7475
}
@@ -93,7 +94,7 @@ void MultiLibraryClassLoader::loadLibrary(const std::string & library_path)
9394
{
9495
if (!isLibraryAvailable(library_path)) {
9596
impl_->active_class_loaders_[library_path] =
96-
new class_loader::ClassLoader(library_path, isOnDemandLoadUnloadEnabled());
97+
std::make_shared<class_loader::ClassLoader>(library_path, isOnDemandLoadUnloadEnabled());
9798
}
9899
}
99100

@@ -108,11 +109,10 @@ int MultiLibraryClassLoader::unloadLibrary(const std::string & library_path)
108109
{
109110
int remaining_unloads = 0;
110111
if (isLibraryAvailable(library_path)) {
111-
ClassLoader * loader = getClassLoaderForLibrary(library_path);
112+
auto loader = getClassLoaderForLibrary(library_path);
112113
remaining_unloads = loader->unloadLibrary();
113114
if (remaining_unloads == 0) {
114115
impl_->active_class_loaders_[library_path] = nullptr;
115-
delete (loader);
116116
}
117117
}
118118
return remaining_unloads;

0 commit comments

Comments
 (0)