Skip to content
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

Interface composition revised #285

Merged
Show file tree
Hide file tree
Changes from 4 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
Original file line number Diff line number Diff line change
Expand Up @@ -46,24 +46,9 @@ namespace hardware_interface
// SFINAE workaround, so that we have reflection inside the template functions
template <typename T>
struct CheckIsResourceManager {
// variable definitions for compiler-time logic
typedef char yes[1];
typedef char no[2];

// method called if C is a ResourceManager
template <typename C>
static yes& testRM(typename C::resource_manager_type*);

// method called if C is not a ResourceManager
template <typename>
static no& testRM(...);

// CheckIsResourceManager<T>::value == true when T is a ResourceManager
static const bool value = (sizeof(testRM<T>(0)) == sizeof(yes));

// method called if C is a ResourceManager
template <typename C>
static yes& callCM(typename std::vector<C*>& managers, C* result, typename C::resource_manager_type*)
static void callCM(typename std::vector<C*>& managers, C* result, typename C::resource_manager_type*)
{
std::vector<typename C::resource_manager_type*> managers_in;
// we have to typecase back to base class
Expand All @@ -74,7 +59,7 @@ struct CheckIsResourceManager {

// method called if C is not a ResourceManager
template <typename C>
static no& callCM(typename std::vector<C*>& managers, C* result, ...) {}
static void callCM(typename std::vector<C*>& managers, C* result, ...) {}

// calls ResourceManager::concatManagers if C is a ResourceManager
static const void callConcatManagers(typename std::vector<T*>& managers, T* result)
Expand All @@ -83,18 +68,43 @@ struct CheckIsResourceManager {

// method called if C is a ResourceManager
template <typename C>
static std::vector<std::string> callGR(C* iface, typename C::resource_manager_type*)
static void callGR(std::vector<std::string> &resources, C* iface, typename C::resource_manager_type*)
{
return iface->getNames();
resources = iface->getNames();
}

// method called if C is not a ResourceManager
template <typename C>
static std::vector<std::string> callGR(T* iface, ...) {}
static void callGR(std::vector<std::string> &resources, T* iface, ...) { }

// calls ResourceManager::concatManagers if C is a ResourceManager
static std::vector<std::string> callGetResources(T* iface)
{ return callGR<T>(iface, 0); }
static void callGetResources(std::vector<std::string> &resources, T* iface)
{ return callGR<T>(resources, iface, 0); }

template <typename C>
static T* newCI(boost::ptr_vector<ResourceManagerBase> &guards, typename C::resource_manager_type*)
{
T* iface_combo = new T;
// save the new interface pointer to allow for its correct destruction
guards.push_back(static_cast<ResourceManagerBase*>(iface_combo));
return iface_combo;
}

// method called if C is not a ResourceManager
template <typename C>
static T* newCI(boost::ptr_vector<ResourceManagerBase> &guards, ...) {
// it is not a ResourceManager
ROS_ERROR("You cannot register multiple interfaces of the same type which are "
"not of type ResourceManager. There is no established protocol "
"for combining them.");
return NULL;
}

static T* newCombinedInterface(boost::ptr_vector<ResourceManagerBase> &guards)
{
return newCI<T>(guards, 0);
}

};

class InterfaceManager
Expand All @@ -118,14 +128,7 @@ class InterfaceManager
ROS_WARN_STREAM("Replacing previously registered interface '" << iface_name << "'.");
}
interfaces_[iface_name] = iface;

std::vector<std::string> resources;
if(CheckIsResourceManager<T>::value)
{
// it is a ResourceManager. Get the names of the resources
resources = CheckIsResourceManager<T>::callGetResources(iface);
}
resources_[iface_name] = resources;
CheckIsResourceManager<T>::callGetResources(resources_[iface_name], iface);
}

void registerInterfaceManager(InterfaceManager* iface_man)
Expand Down Expand Up @@ -187,13 +190,8 @@ class InterfaceManager
iface_combo = static_cast<T*>(it_combo->second);
} else {
// no existing combined interface
if(CheckIsResourceManager<T>::value) {
// it is a ResourceManager

// create a new combined interface
iface_combo = new T;
// save the new interface pointer to allow for its correct destruction
interface_destruction_list_.push_back(reinterpret_cast<ResourceManagerBase*>(iface_combo));
iface_combo = CheckIsResourceManager<T>::newCombinedInterface(interface_destruction_list_);
if(iface_combo) {
// concat all of the resource managers together
CheckIsResourceManager<T>::callConcatManagers(iface_list, iface_combo);
// save the combined interface for if this is called again
Expand Down
11 changes: 4 additions & 7 deletions hardware_interface/test/interface_manager_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ using namespace hardware_interface;

struct FooInterface
{
FooInterface(int foo): foo(foo) {}
int foo;
};

Expand All @@ -50,7 +51,7 @@ struct BazInterface
TEST(InterfaceManagerTest, InterfaceRegistration)
{
// Register interfaces
FooInterface foo_iface;
FooInterface foo_iface(0);
BarInterface bar_iface;

InterfaceManager iface_mgr;
Expand All @@ -66,11 +67,8 @@ TEST(InterfaceManagerTest, InterfaceRegistration)
TEST(InterfaceManagerTest, InterfaceRewriting)
{
// Two instances of the same interface
FooInterface foo_iface_1;
foo_iface_1.foo = 1;

FooInterface foo_iface_2;
foo_iface_2.foo = 2;
FooInterface foo_iface_1(1);
FooInterface foo_iface_2(2);

// Register first interface and validate it
InterfaceManager iface_mgr;
Expand All @@ -91,4 +89,3 @@ int main(int argc, char** argv)
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}