123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161 |
- /**
- *
- * @file message_bus.hpp
- * @author zxw
- * Copyright 2024, yjrobotics. All rights reserved.
- *
- * robotics
- *
- */
- #pragma once
- //stl
- #include <map>
- #include <any>
- #include <string>
- #include <functional>
- //boost
- #include <boost/noncopyable.hpp>
- //robotics
- #include "function_traits.hpp"
- #include "message_bus_impl.h"
- namespace robotics {
- namespace v3 {
- class message_bus :boost::noncopyable {
- public:
- /**
- * @brief 构造
- */
- message_bus() {
- message_bus_impl_ = message_bus_impl::instance();
- }
- /**
- * @brief 析构
- */
- ~message_bus() {
- }
- /**
- * @brief 注册消息
- * @tparam _Fn
- * @param str_topic
- * @param observer 观察者
- * @param f
- * @return
- */
- template<typename _Fn>
- bool bind(const std::string& str_topic, bool observer, _Fn&& f) {
- auto func = v3::to_function(std::forward<_Fn>(f));
- return add(str_topic, observer, std::move(func));
- }
- /**
- * @brief 注册消息
- * @tparam _Fn
- * @tparam _Obj
- * @param str_topic
- * @param observer 观察者
- * @param f
- * @param obj
- * @return
- */
- template<typename _Fn, typename _Obj>
- bool bind(const std::string& str_topic, bool observer, _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, observer, std::move(func));
- }
- /**
- * @brief 发送消息
- * @param str_topic
- */
- template<typename _Ret,bool _BCast = false>
- _Ret invoke(const std::string& str_topic) {
- using function_type = std::function<_Ret()>;
- std::string str_msg_type = str_topic + typeid(function_type).name();
- auto funcs = message_bus_impl_->find(str_msg_type);
- if constexpr (!_BCast) {
- if (std::find_if(funcs.begin(), funcs.end(), [](auto it) {return !it.first; }) == funcs.end()) {
- throw std::runtime_error("no function binded to topic " + str_topic);
- }
- }
- if constexpr (std::is_same<_Ret, void>::value) {
- for (auto& fn : funcs) {
- std::any_cast<function_type>(fn.second)();
- }
- }
- else {
- _Ret result = _Ret{};
- for (auto& fn : funcs) {
- if (!fn.first) {
- result = std::any_cast<function_type>(fn.second)();
- }
- else {
- std::any_cast<function_type>(fn.second)();
- }
- }
- return result;
- }
- }
- /**
- * @brief 发送消息
- * @tparam ..._Args
- * @param str_topic
- * @param ...args
- */
- template<typename _Ret, bool _BCast = false,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();
- auto funcs = message_bus_impl_->find(str_msg_type);
- if constexpr (!_BCast) {
- if (std::find_if(funcs.begin(), funcs.end(), [](auto it) {return !it.first; }) == funcs.end()) {
- throw std::runtime_error("no function binded to topic " + str_topic);
- }
- }
- if constexpr(std::is_same<_Ret, void>::value) {
- for(auto &fn : funcs) {
- std::any_cast<function_type>(fn.second)(args...);
- }
- }
- else {
- if(funcs.empty())
- throw std::runtime_error("no function binded to topic " + str_topic);
- _Ret result = _Ret{};
- for (auto& fn : funcs) {
- if (!fn.first) {
- result = std::any_cast<function_type>(fn.second)(args...);
- }
- else {
- std::any_cast<function_type>(fn.second)(args...);
- }
- }
- return result;
- }
- }
- /**
- * @brief 移除某个主题,需要主题和消息类型
- * @tparam ...Args
- * @param strTopic
- */
- template<typename..._Args>
- void remove(const std::string& str_topic) {
- using function_type = std::function<void(_Args...)>;
- std::string str_msg_type = str_topic + typeid(function_type).name();
- message_bus_impl_->remove(str_msg_type);
- }
- private:
- /**
- * @brief 单个添加
- * @tparam _Fn
- * @param str_topic
- * @param f
- * @return
- */
- template<typename _Fn>
- bool add(const std::string& str_topic, bool observer, _Fn&& f) {
- std::string str_msg_type = str_topic + typeid(f).name();
- return message_bus_impl_->bind(str_msg_type, observer, std::forward<_Fn>(f));
- }
- private:
- message_bus_impl* message_bus_impl_ = nullptr;
- };
- }
- }
|