|
@@ -17,13 +17,22 @@
|
|
#include <boost/noncopyable.hpp>
|
|
#include <boost/noncopyable.hpp>
|
|
//robotics
|
|
//robotics
|
|
#include "function_traits.hpp"
|
|
#include "function_traits.hpp"
|
|
|
|
+#include "message_bus_impl.h"
|
|
|
|
|
|
namespace robotics {
|
|
namespace robotics {
|
|
namespace v3 {
|
|
namespace v3 {
|
|
class message_bus :boost::noncopyable {
|
|
class message_bus :boost::noncopyable {
|
|
public:
|
|
public:
|
|
|
|
+ /**
|
|
|
|
+ * @brief 构造
|
|
|
|
+ */
|
|
|
|
+ message_bus() {
|
|
|
|
+ message_bus_impl_ = message_bus_impl::instance();
|
|
|
|
+ }
|
|
|
|
+ /**
|
|
|
|
+ * @brief 析构
|
|
|
|
+ */
|
|
~message_bus() {
|
|
~message_bus() {
|
|
- map_.clear();
|
|
|
|
}
|
|
}
|
|
/**
|
|
/**
|
|
* @brief 注册消息
|
|
* @brief 注册消息
|
|
@@ -32,9 +41,9 @@ namespace robotics {
|
|
* @param f
|
|
* @param f
|
|
*/
|
|
*/
|
|
template<typename _Fn>
|
|
template<typename _Fn>
|
|
- void bind(const std::string& str_topic, _Fn&& f) {
|
|
|
|
|
|
+ void bind_multiple(const std::string& str_topic, _Fn&& f) {
|
|
auto func = v3::to_function(std::forward<_Fn>(f));
|
|
auto func = v3::to_function(std::forward<_Fn>(f));
|
|
- add(str_topic, std::move(func));
|
|
|
|
|
|
+ add_multiple(str_topic, std::move(func));
|
|
}
|
|
}
|
|
/**
|
|
/**
|
|
* @brief 注册消息
|
|
* @brief 注册消息
|
|
@@ -45,20 +54,55 @@ namespace robotics {
|
|
* @param obj
|
|
* @param obj
|
|
*/
|
|
*/
|
|
template<typename _Fn, typename _Obj>
|
|
template<typename _Fn, typename _Obj>
|
|
- void bind(const std::string& str_topic, _Fn&& f, _Obj&& obj) {
|
|
|
|
|
|
+ void bind_multiple(const std::string& str_topic, _Fn&& f, _Obj&& obj) {
|
|
auto func = v3::to_function((v3::function_traits<_Fn>::stl_function_type)(std::bind_front(std::forward<_Fn>(f), std::forward<_Obj>(obj))));
|
|
auto func = v3::to_function((v3::function_traits<_Fn>::stl_function_type)(std::bind_front(std::forward<_Fn>(f), std::forward<_Obj>(obj))));
|
|
- add(str_topic, std::move(func));
|
|
|
|
|
|
+ add_multiple(str_topic, std::move(func));
|
|
|
|
+ }
|
|
|
|
+ /**
|
|
|
|
+ * @brief 注册消息
|
|
|
|
+ * @tparam _Fn
|
|
|
|
+ * @param str_topic
|
|
|
|
+ * @param f
|
|
|
|
+ */
|
|
|
|
+ template<typename _Fn>
|
|
|
|
+ bool bind(const std::string& str_topic, _Fn&& f) {
|
|
|
|
+ auto func = v3::to_function(std::forward<_Fn>(f));
|
|
|
|
+ return add(str_topic, std::move(func));
|
|
|
|
+ }
|
|
|
|
+ /**
|
|
|
|
+ * @brief 注册消息
|
|
|
|
+ * @tparam _Fn
|
|
|
|
+ * @tparam _Obj
|
|
|
|
+ * @param str_topic
|
|
|
|
+ * @param f
|
|
|
|
+ * @param obj
|
|
|
|
+ */
|
|
|
|
+ template<typename _Fn, typename _Obj>
|
|
|
|
+ bool bind(const std::string& str_topic, _Fn&& f, _Obj&& obj) {
|
|
|
|
+ auto func = v3::to_function((v3::function_traits<_Fn>::stl_function_type)(std::bind_front(std::forward<_Fn>(f), std::forward<_Obj>(obj))));
|
|
|
|
+ return add(str_topic, std::move(func));
|
|
}
|
|
}
|
|
/**
|
|
/**
|
|
* @brief 发送消息
|
|
* @brief 发送消息
|
|
* @param str_topic
|
|
* @param str_topic
|
|
*/
|
|
*/
|
|
- void call(const std::string& str_topic) {
|
|
|
|
- using function_type = std::function<void()>;
|
|
|
|
|
|
+ template<typename _Ret>
|
|
|
|
+ _Ret invoke(const std::string& str_topic) {
|
|
|
|
+ using function_type = std::function<_Ret()>;
|
|
std::string str_msg_type = str_topic + typeid(function_type).name();
|
|
std::string str_msg_type = str_topic + typeid(function_type).name();
|
|
- auto range = map_.equal_range(str_msg_type);
|
|
|
|
- for (Iterater it = range.first; it != range.second; ++it) {
|
|
|
|
- std::any_cast<function_type>(it->second)();
|
|
|
|
|
|
+ auto funcs = message_bus_impl_->find(str_msg_type);
|
|
|
|
+ if constexpr(std::is_same<_Ret, void>::value) {
|
|
|
|
+ for(auto &fn : funcs) {
|
|
|
|
+ std::any_cast<function_type>(fn)();
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ if (funcs.empty())
|
|
|
|
+ throw std::runtime_error("no function binded to topic " + str_topic);
|
|
|
|
+ _Ret result = _Ret{};
|
|
|
|
+ for(auto &fn : funcs) {
|
|
|
|
+ result = std::any_cast<function_type>(fn)();
|
|
|
|
+ }
|
|
|
|
+ return result;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/**
|
|
/**
|
|
@@ -67,13 +111,24 @@ namespace robotics {
|
|
* @param str_topic
|
|
* @param str_topic
|
|
* @param ...args
|
|
* @param ...args
|
|
*/
|
|
*/
|
|
- template<typename... _Args>
|
|
|
|
- void call(const std::string& str_topic, _Args ...args) {
|
|
|
|
- using function_type = std::function<void(_Args...)>;
|
|
|
|
|
|
+ template<typename _Ret,typename... _Args>
|
|
|
|
+ _Ret invoke(const std::string& str_topic, _Args ...args) {
|
|
|
|
+ using function_type = std::function<_Ret(_Args...)>;
|
|
std::string str_msg_type = str_topic + typeid(function_type).name();
|
|
std::string str_msg_type = str_topic + typeid(function_type).name();
|
|
- auto range = map_.equal_range(str_msg_type);
|
|
|
|
- for (Iterater it = range.first; it != range.second; ++it) {
|
|
|
|
- std::any_cast<function_type>(it->second)(args...);
|
|
|
|
|
|
+ auto funcs = message_bus_impl_->find(str_msg_type);
|
|
|
|
+ if constexpr(std::is_same<_Ret, void>::value) {
|
|
|
|
+ for(auto &fn : funcs) {
|
|
|
|
+ std::any_cast<function_type>(fn)(args...);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ else {
|
|
|
|
+ if(funcs.empty())
|
|
|
|
+ throw std::runtime_error("no function binded to topic " + str_topic);
|
|
|
|
+ _Ret result = _Ret{};
|
|
|
|
+ for (auto& fn : funcs) {
|
|
|
|
+ result = std::any_cast<function_type>(fn)(args...);
|
|
|
|
+ }
|
|
|
|
+ return result;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/**
|
|
/**
|
|
@@ -85,27 +140,34 @@ namespace robotics {
|
|
void remove(const std::string& str_topic) {
|
|
void remove(const std::string& str_topic) {
|
|
using function_type = std::function<void(_Args...)>;
|
|
using function_type = std::function<void(_Args...)>;
|
|
std::string str_msg_type = str_topic + typeid(function_type).name();
|
|
std::string str_msg_type = str_topic + typeid(function_type).name();
|
|
- auto range = map_.equal_range(str_msg_type);
|
|
|
|
- while (range.first != range.second) {
|
|
|
|
- range.first = map_.erase(range.first);
|
|
|
|
- ++range.first;
|
|
|
|
- }
|
|
|
|
|
|
+ message_bus_impl_->remove(str_msg_type);
|
|
}
|
|
}
|
|
private:
|
|
private:
|
|
/**
|
|
/**
|
|
- * @brief 添加
|
|
|
|
|
|
+ * @brief 多个添加
|
|
* @tparam _Fn
|
|
* @tparam _Fn
|
|
* @param str_topic
|
|
* @param str_topic
|
|
* @param f
|
|
* @param f
|
|
*/
|
|
*/
|
|
template<typename _Fn>
|
|
template<typename _Fn>
|
|
- void add(const std::string& str_topic, _Fn&& f) {
|
|
|
|
|
|
+ void add_multiple(const std::string& str_topic, _Fn&& f) {
|
|
|
|
+ std::string str_msg_type = str_topic + typeid(f).name();
|
|
|
|
+ message_bus_impl_->bind_multiple(str_msg_type, std::forward<_Fn>(f));
|
|
|
|
+ }
|
|
|
|
+ /**
|
|
|
|
+ * @brief 单个添加
|
|
|
|
+ * @tparam _Fn
|
|
|
|
+ * @param str_topic
|
|
|
|
+ * @param f
|
|
|
|
+ * @return
|
|
|
|
+ */
|
|
|
|
+ template<typename _Fn>
|
|
|
|
+ bool add(const std::string& str_topic, _Fn&& f) {
|
|
std::string str_msg_type = str_topic + typeid(f).name();
|
|
std::string str_msg_type = str_topic + typeid(f).name();
|
|
- map_.emplace(std::move(str_msg_type), std::forward<_Fn>(f));
|
|
|
|
|
|
+ return message_bus_impl_->bind(str_msg_type, std::forward<_Fn>(f));
|
|
}
|
|
}
|
|
private:
|
|
private:
|
|
- std::multimap<std::string, std::any> map_;
|
|
|
|
- typedef std::multimap<std::string, std::any>::iterator Iterater;
|
|
|
|
|
|
+ message_bus_impl* message_bus_impl_ = nullptr;
|
|
};
|
|
};
|
|
}
|
|
}
|
|
}
|
|
}
|