-
Notifications
You must be signed in to change notification settings - Fork 96
Add ClassLoader::createUniqueInstance #38
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Thanks @de-vri-es. This will help us upgrade MoveIt! to C++11 |
include/class_loader/class_loader.h
Outdated
template <class Base> | ||
std::unique_ptr<Base> createUniqueInstance(const std::string& derived_class_name) | ||
{ | ||
return boost::shared_ptr<Base>(createRawInstance<Base>(derived_class_name, true)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this still using a boost::shared_ptr
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops...
ff1e6bf
to
42b4106
Compare
I forgot the deleters, fixed now. Tests pass locally. |
I should also update |
Should also extend unit tests for the |
8975ee8
to
6536c49
Compare
@mikaelarguedas think you can look at this? |
Started reading it but will do a more thorough review very soon |
looks good to me. |
Thanks for reviewing @mikaelarguedas. Do you think this could be released by the next kinetic sync? |
Note I'm working on a unit test now which revealed some problems with the unique_ptr API. Will update the PR within the hour. |
6536c49
to
fab4684
Compare
fab4684
to
c73f783
Compare
Unit test added. Also changed the |
c73f783
to
27c468b
Compare
Thanks @de-vri-es for adding the unit test and cleaning up branching. |
test/unique_ptr_test.cpp
Outdated
ClassLoader loader1(LIBRARY_1); | ||
ASSERT_TRUE(loader1.isLibraryLoaded()); | ||
|
||
//Note: Hard to test thread safety to make sure memory isn't corrupted. The hope is this test is hard enough that once in a while it'll segfault or something if there's some implementation error. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed that it's hard to test. Will try it locally with a lot of threads to make sure it passes every time but a thousand seems to be definitely hard enough to unveil any threading issue
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that I copied this from the shared_ptr
test. It's somewhat double, since this test is actually testing if the deleter behaves correctly.
Both the shared and unique pointers have the same deleter though, so unless the unique_ptr
implementation is buggy (which is unlikely), the behaviour should be the same. Still, I figured it can't hurt to test this with the unique_ptr
too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair point thanks for the explaination.
I couldn't produce any failure locally either. Agreed that it can't hurt to keep the test.
throw(class_loader::CreateClassException("MultiLibraryClassLoader: Could not create object of class type " + class_name + " as no factory exists for it. Make sure that the library exists and was explicitly loaded through MultiLibraryClassLoader::loadLibrary()")); | ||
ClassLoader* loader = getClassLoaderForClass<Base>(class_name); | ||
if (loader == NULL) | ||
throw class_loader::CreateClassException("MultiLibraryClassLoader: Could not create object of class type " + class_name + " as no factory exists for it. Make sure that the library exists and was explicitly loaded through MultiLibraryClassLoader::loadLibrary()"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know it's a copy paste from previous error throwing but would you mind wrapping these lines to compile with google styleguide ? it can also be done in a following style PR to address all the occurences of the lack of wrapping in classloader
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can do that, but there is something to be said for not breaking up user-visible error messages (to quickly point them to the relevant bit of code when they grep).
There are some natural break-up points (variables and punctuation) that can be used without making grep useles, but I'm not sure that will stay within a strict 80 character line limit in all cases.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a very good point, let's keep it as is given that it's consistent with every other error message in this package
test/CMakeLists.txt
Outdated
endif() | ||
|
||
catkin_add_gtest(${PROJECT_NAME}_unique_ptr_test unique_ptr_test.cpp) | ||
if(TARGET ${PROJECT_NAME}_unique_ptr_test) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this test is never triggered because by default c++11 flag is not set for any rosdistro (c.f. http://build.ros.org/job/Kpr__class_loader__ubuntu_xenial_amd64/19/console#console-section-17)
Could you test if c++11 is available and set the flag only for this test? using this kind of logic:
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
if(COMPILER_SUPPORTS_CXX11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
endif()
Thanks!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point, I'm used to working with GCC 6 which did compile the test (it defaults to -std=gnu++14
).
Test updated: removed the #ifdef
in the test and instead made the compilation conditional in the CMakeLists.txt
with the flags added if supported by the compiler.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for iterating on this, tests are compiled and run properly now.
27c468b
to
7705792
Compare
Thanks for the thorough review :) /edit: And now on to pluginlib for me ;) |
My pleasure, especially when there is nothing to complain about like on this PR :) |
Released on kinetic and will release on earlier distros once we're sure that no unexpected behaviour emerges |
* manual port of #38 * add static private setter function for unmanaged flag * missing newline * use NULL unless within a "if C++11" block * fixups
@de-vri-es I noticed that the added test file doesnt have a copyright notice. Is it possible to provide a follow up PR adding it with the appropriate copyright holder? thanks! |
Good point, will do it now. Going to be my employer. Although I see I copied a lot. |
This PR adds a function to create managed instances wrapped in a
std::unique_ptr
.There are a number of advantages to
unique_ptr
:std::shared_ptr
andboost::shared_ptr
(since boost 1.53).The header hides the
#include <memory>
and the extra function if C++11 support is not available. That means dependent projects are not forced to enable C++11 support. Since the added function is actually a function template, there isn't even a need to enable C++11 support for compilingClassLoader
. As such it is even safe to merge this into indigo.Since
std::unique_ptr
is implicitly convertible toboost::shared_ptr
I was also contemplating just changing the return type ofClassLoader::createInstance
. It would be mostly API compatible. However, it would not ABI compatible and there are cases where it would not be API backwards compatible either (if someone is using an implicit conversion on the returnedboost::shared_ptr
that is not available forstd::unique_ptr
, for example). Doing this may make sense in the future, but for now this seemed the most pragmatic approach.