C++的阻塞式消息总线message_bus实现

一、概述

  • 本实现参考自一个通用的C++ 消息总线框架 ,代码位置:messagebus.h
  • 该消息总线主要是解决多个模块间的耦合问题,是阻塞式的。
  • 消息总线实现的基本原理如下:被通信对象向消息总线发布一个主题,这个主题包含消息主题和消息处理函数,消息主题标示某个特定的主题,消息处理函数用来响应该主题的某种消息类型。通信对象向消息总线发送某个特定主题和消息参数,总线就会根据消息主题和消息参数找到对应的消息处理函数处理该请求。
  • 最主要的是这个成员对象boost::unordered_multimap m_map;
    其它语言版本实现:
  • lua语言的消息总线的实现:lua简单消息总线实现,类似于C++ Qt的信号槽
  • python语言的消息总线的实现:python简单消息总线实现,类似于C++ Qt的信号槽

二、实现代码

  • messagebus.h ,需使用C++17,不含有boost的版本,用到了std::any。
#pragma once#include 
#include 
#include 
#include 
#include // 简单的消息分发机制
// ref:https://www.cnblogs.com/qicosmos/archive/2013/04/28/3048919.html
// 《深入应用C++11代码优化与工程级应用》第12章
class MessageBus
{
public:// regist messagetemplate< class... _Args, class _Func, class = typename std::enable_if<!std::is_member_function_pointer<_Func>::value>::type>void attach(std::string key, _Func && func){std::function<void(_Args...)> fn = [&](_Args... args) { return func(std::forward<_Args>(args)...); };m_map.insert(std::make_pair(key, std::move(fn)));}// non-const member functiontemplate<class... _Args, class _Class, class... _DeclareArgs, class _Object>void attach(std::string key, void(_Class::*func)(_DeclareArgs...), _Object & object){std::function<void(_Args...)> fn = [&, func](_Args... args) { return (object.*func)(std::forward<_Args>(args)...); };m_map.insert(std::make_pair(key, fn));}// const member functiontemplate<class... _Args, class _Class, class... _DeclareArgs, class _Object>void attach(std::string key, void(_Class::*func)(_DeclareArgs...) const, _Object & object){std::function<void(_Args...)> fn = [&, func](_Args... args) { return (object.*func)(std::forward<_Args>(args)...); };m_map.insert(std::make_pair(key, fn));}// Broadcast messages, call all the callback functionstemplate<typename... _Args>void sendMessage(std::string key, _Args... args){auto range = m_map.equal_range(key);for (auto it = range.first; it != range.second; it++){std::function<void(_Args...)> func = std::any_cast<std::function<void(_Args...)>>(it->second);func(args...);}}// remove messagetemplate<typename... _Args>void remove(std::string key){auto range = m_map.equal_range(key);m_map.erase(range.first, range.second);}public:MessageBus() = default;~MessageBus() = default;
private:MessageBus(const MessageBus&) = delete;MessageBus& operator=(const MessageBus&) = delete;static std::multimap<std::string, std::any> m_map;
};static MessageBus g_messagebus; // 全局消息总线
  • messagebus.h ,含有boost的版本
#pragma once#include 
#include 
#include 
#include #include 
#include // 简单的消息分发机制
// ref:https://www.cnblogs.com/qicosmos/archive/2013/04/28/3048919.html
// 《深入应用C++11代码优化与工程级应用》第12章
class MessageBus
{
public:// regist messagetemplate< class... _Args, class _Func, class = typename std::enable_if<!std::is_member_function_pointer<_Func>::value>::type>void attach(std::string key, _Func && func){std::function<void(_Args...)> fn = [&](_Args... args) { return func(std::forward<_Args>(args)...); };m_map.insert(std::make_pair(key, std::move(fn)));}// non-const member functiontemplate<class... _Args, class _Class, class... _DeclareArgs, class _Object>void attach(std::string key, void(_Class::*func)(_DeclareArgs...), _Object & object){std::function<void(_Args...)> fn = [&, func](_Args... args) { return (object.*func)(std::forward<_Args>(args)...); };m_map.insert(std::make_pair(key, fn));}// const member functiontemplate<class... _Args, class _Class, class... _DeclareArgs, class _Object>void attach(std::string key, void(_Class::*func)(_DeclareArgs...) const, _Object & object){std::function<void(_Args...)> fn = [&, func](_Args... args) { return (object.*func)(std::forward<_Args>(args)...); };m_map.insert(std::make_pair(key, fn));}// Broadcast messages, call all the callback functionstemplate<typename... _Args>void sendMessage(std::string key, _Args... args){auto range = m_map.equal_range(key);for (auto it = range.first; it != range.second; it++){std::function<void(_Args...)> func = boost::any_cast<std::function<void(_Args...)>>(it->second);func(args...);}}// remove messagetemplate<typename... _Args>void remove(std::string key){auto range = m_map.equal_range(key);m_map.erase(range.first, range.second);}public:MessageBus() = default;~MessageBus() = default;
private:MessageBus(const MessageBus&) = delete;MessageBus& operator=(const MessageBus&) = delete;static std::multimap<std::string, boost::any> m_map;
};static MessageBus g_messagebus; // 全局消息总线

三、使用方法

  • 在任意一cpp文件中实现m_map,比如main函数中;
  • 使用全局的g_messagebus在所需订阅模块中订阅感兴趣消息和回调函数;
  • 在需要发布消息的代码中填写sendMessage业务逻辑。
#include "messagebus.h"
#include 
std::multimap<std::string, std::any> MessageBus::m_map;
// 使用boost的使用 std::multimap MessageBus::m_map;class Test
{
public:void test(int, const char*) { std::cout<< "hit test" << std::endl; return;}
};
int main()
{Test t;std::string key = "test";// 订阅"test"消息,回调函数为Test::testg_messagebus.attach<int, const char*>(key, &Test::test, t); // 向订阅者发送消息,消息参数是 123 和 "abc",回调函数Test::test将会被执行g_messagebus.sendMessage<int, const char*>(key, 123, "abc"); // 移除订阅"test"g_messagebus.remove<int, const char*>(key); return 0;
}

四、非阻塞消息总线的实现

+请参考我的另一篇博客 : 使用C++11实现的非阻塞消息总线message_bus


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部