博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
(原创)一个轻量级、高性能的消息分发器的实现
阅读量:4952 次
发布时间:2019-06-11

本文共 2710 字,大约阅读时间需要 9 分钟。

一个消息分发器应该要具备以下几个特征:

  • 集中注册消息以及消息处理函数;
  • 可以处理任何类型的消息;
  • 根据消息选择正确的消息处理函数;
  • 能检测消息的正确性;

  要实现一个消息分发器的难点在如何能处理所有的消息,因为不同的消息的消息处理函数是不同的,有可能不同的消息处理函数的返回值、形参都不同,目前还没有一种容器能将所有的函数,诸如 void f(); void f1(int); int f2(double); double f3(int, double)等函数放到一个容器中。如果真的存在这种容器的话,那就可以将消息和消息函数作为一个pair存放到这个容器中,分发消息的时候就可以根据消息选择对应的消息处理函数了。所以关键是要实现一个能容纳所有函数的东西。

  能实现将不同类型存储起来目前有两种方法:第一种通过any,不过用any的话,取值时any_cast<T>需要具体的类型,即需要具体的消息处理函数,这不能实现消息的自动分发,因此不满足要求;第二种是通过tuple,因为tuple可以容纳任意个数和任意类型的元素。如果将消息放到一个tuple中,再将消息对应的处理函数放到另外一个tuple中,然后将这两个tuple合并成为一个新的tuple,这个新tuple中的元素是一个键值对,键为消息,值为处理函数,然后外面就可以根据这个消息实现消息的分发处理了。看看具体的实现吧:

 
#include 
namespace Cosmos{    namespace details    {        //tuple参数的索引序列        template
struct IndexTuple{}; template
struct MakeIndexes : MakeIndexes
{}; template
struct MakeIndexes<0, indexes...> { typedef IndexTuple
type; }; template
using pair_type = std::pair
::type, typename std::tuple_element
::type>; template
pair_type
pair(const T1& tup1, const T2& tup2) { return std::make_pair(std::get
(tup1), std::get
(tup2)); } template
auto pairs_helper(IndexTuple
, const T1& tup1, const T2& tup2) -> decltype(std::make_tuple(pair
(tup1, tup2)...)) { return std::make_tuple(pair
(tup1, tup2)...); } } // namespace details template
auto Zip(Tuple1 tup1, Tuple2 tup2) -> decltype(details::pairs_helper(typename details::MakeIndexes
::value>::type(), tup1, tup2)) { static_assert(std::tuple_size
::value == std::tuple_size
::value, "tuples should be the same size."); return details::pairs_helper(typename details::MakeIndexes
::value>::type(), tup1, tup2); } template
auto Apply(F&&f, Args&&... args)->decltype(f(args...)) { return std::forward
(f)(std::forward
(args)...); }}

测试代码:

void Call1(){    cout << "call1" << endl;}int Call2(int a){    return a;}enum EnumMessage{    Message1,    Message2};template
R Dispatch(Args... args){ auto tpkey = std::make_tuple(Message1, Message2); auto tpval = std::make_tuple(Call1, Call2); auto pairs = Cosmos::Zip(tpkey, tpval); return Cosmos::Apply(std::get
(pairs).second, args...);}int main(){ Dispatch
(); auto r = Dispatch
(1); cout << r << endl; return 0;}

输出结果:

call11

  这个分发器是在编译期生成的,分发也是在编译期完成的,所以分发效率很高。当消息和消息处理函数不匹配时,就会出现编译错误,保证在编译期就能检查消息是否是正确的。

  上例中实现了将不同的消息分发给不同的消息处理函数,而这些消息处理函数是各不相同的,不管这些消息处理函数的返回值是否相同,参数是否相同,都能实现分发。实现代码不过几十行,可以说是非常轻量级的分发器了。

 

如果你觉得这篇文章对你有用,可以点一下推荐,谢谢。

c++11 boost技术交流群:296561497,欢迎大家来交流技术。

转载于:https://www.cnblogs.com/qicosmos/p/3586129.html

你可能感兴趣的文章
JStrom的zk数据
查看>>
使用“dotconnect for oracle”绕过oracle客户端连接Oracle数据库
查看>>
CentOS/RHEL Linux安装EPEL第三方软件源
查看>>
redisson
查看>>
Weblogic集群
查看>>
HDU 5351 MZL's Border (多校联合第5场1009)
查看>>
js三种定义类的方法
查看>>
离线批量数据通道Tunnel的最佳实践及常见问题
查看>>
Struts2学习第2天--Struts2的Servlet的API的访问 Struts2的结果页面的配置 Struts2的数据的封装(包括复杂类型)...
查看>>
python3练习100题——044
查看>>
ORACLE1.5(上班前必须掌握-开项目的准备)
查看>>
正则表达式学习笔记(2)元字符和修饰符
查看>>
基础算法(四)——深度优先搜索
查看>>
PHP 内存泄漏分析定位(转载)
查看>>
Linux基础命令之文件过滤及内容编辑处理(一)
查看>>
iOS - HTTPS接口加密和身份认证
查看>>
Swift - LineChart绘制折线图
查看>>
线性表(java)
查看>>
转:Selenium Grid深入学习
查看>>
人脸识别完整项目实战(1):目录大纲篇
查看>>