test_noticeCenter
1.test例程相关性:
- 分析test_tiemr,首先分析testNoticeCenter,再分析testEventPoller,最后分析test_timer;
- 其中testEventPoller还包含了Pipe和PipeWrap的内容;
- 因此本节先分析testNoticeCenter的例程;
2.程序运行结果:
- 运行环境:Ubuntu20.04 clion2023.1
/**
* 程序运行结果:
* ubuntu20.04
* /work/__code/ZLToolKit_202401201404/ZLToolKit/cmake-build-debug/bin/test_noticeCenter
2024-01-30 20:35:33.263 D [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:38 operator() | 1 b 3.14 d
2024-01-30 20:35:33.263 D [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:50 operator() | 1 b 3.14 d
2024-01-30 20:35:34.263 I [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:43 operator() | 2 b 3.14 d
2024-01-30 20:35:34.264 W [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:55 operator() | 2 b 3.14 d
2024-01-30 20:35:35.265 I [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:43 operator() | 3 b 3.14 d
2024-01-30 20:35:35.265 W [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:55 operator() | 3 b 3.14 d
2024-01-30 20:35:36.265 I [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:43 operator() | 4 b 3.14 d
2024-01-30 20:35:36.265 W [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:55 operator() | 4 b 3.14 d
2024-01-30 20:35:37.267 I [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:43 operator() | 5 b 3.14 d
2024-01-30 20:35:37.267 W [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:55 operator() | 5 b 3.14 d
2024-01-30 20:35:38.269 I [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:43 operator() | 6 b 3.14 d
2024-01-30 20:35:38.269 W [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:55 operator() | 6 b 3.14 d
2024-01-30 20:35:39.271 I [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:43 operator() | 7 b 3.14 d
2024-01-30 20:35:39.271 W [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:55 operator() | 7 b 3.14 d
2024-01-30 20:35:40.271 I [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:43 operator() | 8 b 3.14 d
2024-01-30 20:35:40.271 W [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:55 operator() | 8 b 3.14 d
2024-01-30 20:35:41.272 I [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:43 operator() | 9 b 3.14 d
2024-01-30 20:35:41.272 W [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:55 operator() | 9 b 3.14 d
2024-01-30 20:35:42.274 I [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:43 operator() | 10 b 3.14 d
2024-01-30 20:35:42.274 W [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:55 operator() | 10 b 3.14 d
2024-01-30 20:35:43.275 I [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:43 operator() | 11 b 3.14 d
2024-01-30 20:35:43.275 W [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:55 operator() | 11 b 3.14 d
2024-01-30 20:35:44.276 I [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:43 operator() | 12 b 3.14 d
2024-01-30 20:35:44.276 W [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:55 operator() | 12 b 3.14 d
2024-01-30 20:35:45.278 I [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:43 operator() | 13 b 3.14 d
2024-01-30 20:35:45.278 W [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:55 operator() | 13 b 3.14 d
2024-01-30 20:35:46.280 I [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:43 operator() | 14 b 3.14 d
2024-01-30 20:35:46.280 W [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:55 operator() | 14 b 3.14 d
2024-01-30 20:35:47.283 I [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:43 operator() | 15 b 3.14 d
2024-01-30 20:35:47.283 W [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:55 operator() | 15 b 3.14 d
2024-01-30 20:35:48.285 I [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:43 operator() | 16 b 3.14 d
2024-01-30 20:35:48.285 W [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:55 operator() | 16 b 3.14 d
2024-01-30 20:35:49.288 I [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:43 operator() | 17 b 3.14 d
2024-01-30 20:35:49.288 W [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:55 operator() | 17 b 3.14 d
2024-01-30 20:35:50.291 I [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:43 operator() | 18 b 3.14 d
2024-01-30 20:35:50.291 W [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:55 operator() | 18 b 3.14 d
2024-01-30 20:35:51.293 I [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:43 operator() | 19 b 3.14 d
2024-01-30 20:35:51.293 W [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:55 operator() | 19 b 3.14 d
2024-01-30 20:35:52.295 I [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:43 operator() | 20 b 3.14 d
2024-01-30 20:35:52.295 W [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:55 operator() | 20 b 3.14 d
2024-01-30 20:35:53.296 I [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:43 operator() | 21 b 3.14 d
2024-01-30 20:35:53.296 W [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:55 operator() | 21 b 3.14 d
2024-01-30 20:35:54.297 I [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:43 operator() | 22 b 3.14 d
2024-01-30 20:35:54.297 W [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:55 operator() | 22 b 3.14 d
2024-01-30 20:35:55.299 I [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:43 operator() | 23 b 3.14 d
2024-01-30 20:35:55.300 W [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:55 operator() | 23 b 3.14 d
2024-01-30 20:35:56.302 I [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:43 operator() | 24 b 3.14 d
2024-01-30 20:35:56.302 W [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:55 operator() | 24 b 3.14 d
2024-01-30 20:35:57.303 I [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:43 operator() | 25 b 3.14 d
2024-01-30 20:35:57.303 W [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:55 operator() | 25 b 3.14 d
2024-01-30 20:35:58.305 I [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:43 operator() | 26 b 3.14 d
2024-01-30 20:35:58.305 W [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:55 operator() | 26 b 3.14 d
2024-01-30 20:35:59.306 I [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:43 operator() | 27 b 3.14 d
2024-01-30 20:35:59.306 W [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:55 operator() | 27 b 3.14 d
2024-01-30 20:36:00.307 I [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:43 operator() | 28 b 3.14 d
2024-01-30 20:36:00.307 W [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:55 operator() | 28 b 3.14 d
2024-01-30 20:36:01.309 I [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:43 operator() | 29 b 3.14 d
2024-01-30 20:36:01.309 W [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:55 operator() | 29 b 3.14 d
2024-01-30 20:36:02.310 I [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:43 operator() | 30 b 3.14 d
2024-01-30 20:36:02.310 W [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:55 operator() | 30 b 3.14 d
2024-01-30 20:36:03.311 I [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:43 operator() | 31 b 3.14 d
2024-01-30 20:36:03.311 W [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:55 operator() | 31 b 3.14 d
2024-01-30 20:36:04.313 I [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:43 operator() | 32 b 3.14 d
2024-01-30 20:36:04.313 W [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:55 operator() | 32 b 3.14 d
2024-01-30 20:36:05.314 I [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:43 operator() | 33 b 3.14 d
2024-01-30 20:36:05.314 W [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:55 operator() | 33 b 3.14 d
2024-01-30 20:36:06.315 I [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:43 operator() | 34 b 3.14 d
2024-01-30 20:36:06.315 W [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:55 operator() | 34 b 3.14 d
2024-01-30 20:36:07.318 I [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:43 operator() | 35 b 3.14 d
2024-01-30 20:36:07.318 W [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:55 operator() | 35 b 3.14 d
2024-01-30 20:36:08.320 I [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:43 operator() | 36 b 3.14 d
2024-01-30 20:36:08.320 W [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:55 operator() | 36 b 3.14 d
2024-01-30 20:36:09.321 I [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:43 operator() | 37 b 3.14 d
2024-01-30 20:36:09.321 W [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:55 operator() | 37 b 3.14 d
2024-01-30 20:36:10.322 I [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:43 operator() | 38 b 3.14 d
2024-01-30 20:36:10.322 W [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:55 operator() | 38 b 3.14 d
2024-01-30 20:36:11.324 I [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:43 operator() | 39 b 3.14 d
2024-01-30 20:36:11.324 W [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:55 operator() | 39 b 3.14 d
2024-01-30 20:36:12.325 I [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:43 operator() | 40 b 3.14 d
2024-01-30 20:36:12.325 W [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:55 operator() | 40 b 3.14 d
2024-01-30 20:36:13.326 I [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:43 operator() | 41 b 3.14 d
2024-01-30 20:36:13.326 W [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:55 operator() | 41 b 3.14 d
2024-01-30 20:36:14.326 I [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:43 operator() | 42 b 3.14 d
2024-01-30 20:36:14.326 W [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:55 operator() | 42 b 3.14 d
2024-01-30 20:36:15.328 I [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:43 operator() | 43 b 3.14 d
2024-01-30 20:36:15.329 W [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:55 operator() | 43 b 3.14 d
2024-01-30 20:36:16.330 I [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:43 operator() | 44 b 3.14 d
2024-01-30 20:36:16.330 W [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:55 operator() | 44 b 3.14 d
2024-01-30 20:36:17.330 I [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:43 operator() | 45 b 3.14 d
2024-01-30 20:36:17.331 W [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:55 operator() | 45 b 3.14 d
2024-01-30 20:36:18.332 I [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:43 operator() | 46 b 3.14 d
2024-01-30 20:36:18.333 W [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:55 operator() | 46 b 3.14 d
2024-01-30 20:36:19.334 I [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:43 operator() | 47 b 3.14 d
2024-01-30 20:36:19.334 W [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:55 operator() | 47 b 3.14 d
2024-01-30 20:36:20.336 I [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:43 operator() | 48 b 3.14 d
2024-01-30 20:36:20.336 W [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:55 operator() | 48 b 3.14 d
2024-01-30 20:36:21.339 I [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:43 operator() | 49 b 3.14 d
2024-01-30 20:36:21.339 W [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:55 operator() | 49 b 3.14 d
2024-01-30 20:36:22.341 I [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:43 operator() | 50 b 3.14 d
2024-01-30 20:36:22.341 W [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:55 operator() | 50 b 3.14 d
2024-01-30 20:36:23.341 I [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:43 operator() | 51 b 3.14 d
2024-01-30 20:36:23.342 W [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:55 operator() | 51 b 3.14 d
2024-01-30 20:36:24.343 I [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:43 operator() | 52 b 3.14 d
2024-01-30 20:36:24.343 W [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:55 operator() | 52 b 3.14 d
2024-01-30 20:36:25.345 I [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:43 operator() | 53 b 3.14 d
2024-01-30 20:36:25.345 W [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:55 operator() | 53 b 3.14 d
2024-01-30 20:36:26.345 I [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:43 operator() | 54 b 3.14 d
2024-01-30 20:36:26.345 W [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:55 operator() | 54 b 3.14 d
2024-01-30 20:36:27.347 I [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:43 operator() | 55 b 3.14 d
2024-01-30 20:36:27.347 W [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:55 operator() | 55 b 3.14 d
2024-01-30 20:36:28.348 I [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:43 operator() | 56 b 3.14 d
2024-01-30 20:36:28.348 W [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:55 operator() | 56 b 3.14 d
2024-01-30 20:36:29.349 I [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:43 operator() | 57 b 3.14 d
2024-01-30 20:36:29.349 W [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:55 operator() | 57 b 3.14 d
2024-01-30 20:36:30.351 I [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:43 operator() | 58 b 3.14 d
2024-01-30 20:36:30.351 W [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:55 operator() | 58 b 3.14 d
2024-01-30 20:36:31.352 I [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:43 operator() | 59 b 3.14 d
2024-01-30 20:36:31.352 W [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:55 operator() | 59 b 3.14 d
2024-01-30 20:36:32.353 I [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:43 operator() | 60 b 3.14 d
2024-01-30 20:36:32.354 W [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:55 operator() | 60 b 3.14 d
进程已结束,退出代码143 (interrupted by signal 15: SIGTERM)
*/
看到console输出的结果:
开始是38行(debug)和50行(debug),后面一直是43行(info)、55行(waring)的内容一直循环打印;
3.代码分析
3.1 逻辑简析
//对事件NOTICE_NAME1新增一个监听
//addListener方法第一个参数是标签,用来删除监听时使用
//需要注意的是监听回调的参数列表个数类型需要与emitEvent广播时的完全一致,否则会有无法预知的错误
// liu [1] addListener
NoticeCenter::Instance().addListener(0,NOTICE_NAME1, // addListerner(1)
[](int &a,const char * &b,double &c,string &d){
DebugL << a << " " << b << " " << c << " " << d;
// liu [2] delListener
NoticeCenter::Instance().delListener(0,NOTICE_NAME1);
NoticeCenter::Instance().addListener(0,NOTICE_NAME1, // addListerner(2)
[](int &a,const char * &b,double &c,string &d){
InfoL << a << " " << b << " " << c << " " << d;
});
});
代码逻辑简析:
addListerner(0,NOTICE_NAME1){ // addListerner(1)
DebugL...
delListerner(0,NOTICE_NAME1);
addListerner(0,NOTICE_NAME1){ //addListerner(2)
InfoL...
}
}
说明:
addListerner(1)中内部套了一个addListerner(2),
但在 addListerner(2)之前先 delListener(0,NOTICE_NAME1),先删除了Listenner(1);
3.2 解析NoticeCenter::Instance().addListener
- 注意:
- NoticeCenter类和Eventdispatcher类都有addListener,其中NoticeCenter类还是EventDispatcher类的友元类;
- addListener的关系是:
NoticeCenter.getInstance().addListener{
EventDispatcher.addListener...
}
/**
* [1.1] 单例,调用构造函数,NoticeCenter::Instance()
* [1.2] addListerner函数
*/
NoticeCenter::Instance().addListener(0,NOTICE_NAME1, // addListerner(2)
[](int &a,const char * &b,double &c,string &d){
InfoL << a << " " << b << " " << c << " " << d;
});
3.2.1 [1.1] 单例,调用构造函数,NoticeCenter::Instance()
NoticeCenter::Instance()
调用宏(NoticeCenter.cpp):
INSTANCE_IMP(NoticeCenter)
接着调用(Utils.h),最后返回一个NoticeCenter的shard_ptr智能指针
其中调用了NoticeCenter的构造函数;
///liu 创建实例,返回引用
#define INSTANCE_IMP(class_name, ...) \
class_name &class_name::Instance() { \
static std::shared_ptr<class_name> s_instance(new class_name(__VA_ARGS__)); \
static class_name &s_instance_ref = *s_instance; \
return s_instance_ref; \
}
查看构造函数: 调用的默认构造函数和析构函数;
3.2.2 [1.2] addListerner函数
该函数属于 NoticeCenter类
NoticeCenter::Instance().addListener(0,NOTICE_NAME1, // addListerner(2)
[](int &a,const char * &b,double &c,string &d){
InfoL << a << " " << b << " " << c << " " << d;
});
// 函数源码:
/**
* liu
* @tparam FUNC
* @param tag 标签,用来删除监听时使用 【实参】0
* @param event 被监听的事件,String类型 【实参】NOTICE_NAME1
* @param func 监听的事件执行的函数功能 【实参】lamda函数体
*/
template <typename FUNC>
void addListener(void *tag, const std::string &event, FUNC &&func) {
// liu [1.2.1] getDispatcher
// liu [1.2.2] addListerner,调用EventDispathcher类的addListener函数
getDispatcher(event, true)->addListener(tag, std::forward<FUNC>(func));
}
***liu [1.2.1] getDispatcher ***
源码(NoticeCenter.h) 该函数属于NoticeCenter类,但是private权限;
/**
* liu
* 根据event在_mapListener中查找对应的dispatcher并且返回,
* 如果之前没有创建该dispatcher实例,则创建一个新的dispatcher实例,并且放入到_mapListener中;
* liu 实参: NOTICE_NAME1 , create = true
*/
EventDispatcher::Ptr getDispatcher(const std::string &event, bool create = false) {
std::lock_guard<std::recursive_mutex> lck(_mtxListener);
auto it = _mapListener.find(event);
if (it != _mapListener.end()) {
return it->second;
}
if (create) {
// 如果为空则创建一个
EventDispatcher::Ptr dispatcher(new EventDispatcher());
_mapListener.emplace(event, dispatcher);
return dispatcher;
}
return nullptr;
}
test_noticeCenter中的_mapListener 为空,find(evnet)执行没有结果;
create 为true,则创建一个新的dispatcher实例,key是event(NOTICE_NAME1),value是dispatcher(这里是新创建的dispatcher),绑定后保存到__mapListener(该map属于NoticeCenter类)中,并返回该dispatcher实例;此时完成了event事件和对应的dispatcher分发器的绑定,存放到了NoticeCenter类的__mapListener中
liu [1.2.2] addListerner (NoticeCenter.h)
该函数属于 EventDispatcher类 的成员函数
template <typename FUNC>
void addListener(void *tag, FUNC &&func) {
// liu [1.2.2.1] function_traits 解析
using stl_func = typename function_traits<typename std::remove_reference<FUNC>::type>::stl_function_type;
Any listener;
// liu [1.2.2.2] 实参:func:<lanbda>&&, listener:toolkit::Any
listener.set<stl_func>(std::forward<FUNC>(func));
std::lock_guard<std::recursive_mutex> lck(_mtxListener);
_mapListener.emplace(tag, listener);
}
说明: NoticeCenter类是EventDispatcher类的友元类;
friend class NoticeCenter;
NoticeCenter类可以访问EventDispatcher的类的private权限的成员变量和函数
// liu [1.2.2.1] function_traits 解析
using stl_func = typename function_traits<typename std::remove_reference<FUNC>::type>::stl_function_type;
//liu 参考内容: 深入应用c++11代码优化与工程级应用 3.3.6
源码位置:function_traits.h
功能:
typename std::remove_reference::type 去除FUNC的引用特性
最后返回函数类型
*** 知识点 begin ***
std::remove_reference
参考文章:https://blog.csdn.net/qq_44132777/article/details/130888752
如果输入的类型T是一个引用类型,即T存在引用特性,则std::remove_reference
std::remove_reference是C++标准库 <type_traits> 头文件中的一个类型萃取工具,用于从一个类型中移除引用(Reference)特性。
它返回一个新的类型,该类型是从原始类型中移除了引用特性后得到的。
具体来说,如果输入的类型T是一个引用类型,即T存在引用特性,
则std::remove_reference
*** 知识点 end ***
liu [1.2.2.2] listener.set<stl_func>... 解析
// liu [1.2.2.2] 实参:func:<lanbda>&&, listener:toolkit::Any
listener.set<stl_func>(std::forward<FUNC>(func));
在Any类中存在重载模板函数set...
// liu set1
template <typename T, typename... ArgsType>
void set(ArgsType &&...args) {
_type = &typeid(T);
_data.reset(new T(std::forward<ArgsType>(args)...), [](void *ptr) { delete (T *)ptr; });
}
// liu set2
template <typename T>
void set(std::shared_ptr<T> data) {
if (data) {
_type = &typeid(T);
_data = std::move(data);
} else {
reset();
}
}
经过debug,test_noticeCenter例程调用set1形式;
对应的lambda函数:
[](int &a,const char * &b,double &c,string &d){
InfoL << a << " " << b << " " << c << " " << d;
}
debug调试看到的值是:
this={toolkit::Anyconst}0x7fffffffd750
_type={const std::type_info}0x555555581b18
_data={std::shared_ptr
get()={void*}0x555555596280
此时将lambda函数 以函数对象的形式 封装进了Any 类的对象 listener中;
接着将tag和listener,分别以key和value的形式绑定发放入到
_mapListener.emplace(tag, listener);
此时放入_mapListener的尾部,tag是null,listener就是刚才封装的Any实例listener,即dispatcher要分发的event事件所对应的执行任务/函数;
至此完成tag和listener的绑定,其实就是放到了以key-value形式放到了std::unordered_multimap中存放
-
总结:
-
在NoticeCenter类中,
1.1 绑定了event和dispatcher关系,存放在了NoticeCenter类的__mapListener;
定义为:
-
std::unordered_map<std::string, EventDispatcher::Ptr> _mapListener
1.2 调用方法:
template <typename FUNC>
void addListener(void *tag, const std::string &event, FUNC &&func) {
getDispatcher(event, true)->addListener(tag, std::forward<FUNC>(func));
}
-
在EventDispatcher类中
2.1 绑定了tag和Event要执行的任务/函数的关系,存放在了EventDispatcher类的 _mapListener中;
定义为:
using MapType = std::unordered_multimap<void *, Any>;
MapType _mapListener;
2.2 调用方法:
template <typename FUNC>
void addListener(void *tag, FUNC &&func) {
using stl_func = typename function_traits<typename std::remove_reference<FUNC>::type>::stl_function_type;
Any listener;
listener.set<stl_func>(std::forward<FUNC>(func));
std::lock_guard<std::recursive_mutex> lck(_mtxListener);
_mapListener.emplace(tag, listener);
}
3.3 解析 [2]NoticeCenter::Instance().delListener(0,NOTICE_NAME1)
void delListener(void *tag, const std::string &event) {
// liu 首先获取对应event事件的Dispatcher,不存在则直接返回;
auto dispatcher = getDispatcher(event);
if (!dispatcher) {
// 不存在该事件
return;
}
bool empty;
// liu [2.1] EventDispatcher类中,
// 根据tag,删除_mapListener中的tag-Any的绑定关系; empty 默认是false
dispatcher->delListener(tag, empty);
if (empty) {
// liu [2.2]
delDispatcher(event, dispatcher);
}
}
- 首先获取对应event事件的Dispatcher,不存在则直接返回;
- EventDispatcher类中,根据tag,删除_mapListener中的tag-Any的绑定关系; empty 默认是false;
- 最后,NoticeCenter类中,根据event和 dispatcher对应的 ,该event事件对应的dispatcher分发器;
3.3.1 // liu [2.1] dispatcher->delListener(tag, empty);
void delListener(void *tag, bool &empty) {
std::lock_guard<std::recursive_mutex> lck(_mtxListener);
_mapListener.erase(tag);
empty = _mapListener.empty();
}
参考文章:https://zh.cppreference.com/w/cpp/container/unordered_multimap/erase
std::unordered_multimap<Key,T,Hash,KeyEqual,Allocator>::erase
size_type erase( const Key& key );
移除键等价于 key 的所有元素。
属于EventDispatcher类,根据tag,删除_mapListener中所有等于key的所有元素;即删除等于tag的所有的tag-Any的绑定关系;
using MapType = std::unordered_multimap<void *, Any>;
MapType _mapListener;
empty 默认是false;属于输出值;如果该EventDispatcher类的_mapListener,删除该tag对应的元素为空后,则设置标志值empty为false;则继续删除该noticeCenter类中的该event对应的Dispatcher;
-
【总结】
因为EventDispatcher中,_mapListener已经为空,则说明不存在tag和Any关系,说明该event对应的dispatcher、tag、Any(任务/函数)已经不再使用了;
所以在NoticeCenter类中的也需要删除该event和对应的dispatcher的关系;
解除该event对应的所有的dispatcher、tag和Any的关系;
3.3.2 // liu [2.2] delDispatcher(event, dispatcher);
void delDispatcher(const std::string &event, const EventDispatcher::Ptr &dispatcher) {
std::lock_guard<std::recursive_mutex> lck(_mtxListener);
auto it = _mapListener.find(event);
if (it != _mapListener.end() && dispatcher == it->second) {
// 两者相同则删除
_mapListener.erase(it);
}
}
NoticeCenter类中,根据event查找_mapListener中的对应的pair,再次判断是否是event事件对应的dispatcher分发器,如果是,则删除该pair;
3.4 解析 NoticeCenter::Instance().emitEvent
int a = 0;
while(!g_bExitFlag){
const char *b = "b";
double c = 3.14;
string d("d");
//每隔1秒广播一次事件,如果无法确定参数类型,可加强制转换
NoticeCenter::Instance().emitEvent(NOTICE_NAME1,++a,(const char *)"b",c,d);
NoticeCenter::Instance().emitEvent(NOTICE_NAME2,d,c,b,a);
sleep(1); // sleep 1 second
}
分别设置了参数:
a:main函数内的局部变量,类型为:整型,值为0;
b:字符指针,类型为char*,值为“b”;
c:双精度浮点类型,类型为double,值为“c”;
d:string 类型,值为“d”;
NoticeCenter::Instance().emitEvent(NOTICE_NAME1,++a,(const char *)"b",c,d);
发送事件,事件名称(const std::string &event)是NOTICE_NAME1,后续的参数是可变参数,
NoticeCenter::Instance().emitEvent(NOTICE_NAME2,d,c,b,a);
发送事件,事件名称(const std::string &event)是NOTICE_NAME2,后续的参数是可变参数,
-
注意:
为什么?emitEvent发送的事件分别为NOTICE_NAME1 和NOTICE_NAME2的 ,但是传入的可变参数的顺序不同,但是console打印的输出信息是一致的?
2024-01-30 20:35:34.263 I [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:43 operator() |
2 b 3.14 d
2024-01-30 20:35:34.264 W [test_noticeCenter] [23473-test_noticeCent] test_noticeCenter.cpp:55 operator() |2 b 3.14 d
3.4.1 解析 NoticeCenter::Instance().emitEvent
//NoticeCenter类函数
template <typename... ArgsType>
int emitEvent(const std::string &event, ArgsType &&...args) {
return emitEvent_l(false, event, std::forward<ArgsType>(args)...);
}
接着调用了函数emitEvent_l,属于NoticeCenter类的private权限函数,属于内部函数:
// NoticeCenter类函数:
template <typename... ArgsType>
int emitEvent_l(bool safe, const std::string &event, ArgsType &&...args) {
auto dispatcher = getDispatcher(event);
if (!dispatcher) {
// 该事件无人监听
return 0;
}
return dispatcher->emitEvent(safe, std::forward<ArgsType>(args)...);
}
传递的参数:safe:默认false; std::forward
(args) 首先根据event事件获取到对应的dispatche分发器,如果之前没有注册该event-dispatcher绑定关系,则直接返回;
否则,继续调用EventDispatcher类的 emitEvent函数,执行事件的分发;
接着调用:
// EvenetDispatcher类函数:
template <typename... ArgsType>
int emitEvent(bool safe, ArgsType &&...args) {
using stl_func = std::function<void(decltype(std::forward<ArgsType>(args))...)>;
decltype(_mapListener) copy;
{
// 先拷贝(开销比较小),目的是防止在触发回调时还是上锁状态从而导致交叉互锁
std::lock_guard<std::recursive_mutex> lck(_mtxListener);
copy = _mapListener;
}
int ret = 0;
for (auto &pr : copy) {
try {
pr.second.get<stl_func>(safe)(std::forward<ArgsType>(args)...);
++ret;
} catch (InterruptException &) {
++ret;
break;
}
}
return ret;
}
在Ubuntu下使用debug调试,在test_noticeCenter的main函数的while循环中打断点:
单步F7调试进入到调用函数EventDispatcher的emitEvent函数内:
看到 get函数是调用Any类的函数:get
template <typename T>
T &get(bool safe = true) {
if (!_data) {
throw std::invalid_argument("Any is empty");
}
if (safe && !is<T>()) {
throw std::invalid_argument("Any::get(): " + demangle(_type->name()) + " unable cast to " + demangle(typeid(T).name()));
}
return *((T *)_data.get());
}
第一部分,获取到 返回存储的_data指针。
shared_ptr 可能在存储指向一个对象的指针时共享另一对象的所有权。 get() 返回存储的指针,而非被管理指针。(T *)_data.get():
第二部分,将获取的对象指针进行(T)强转,改变为T 类型;
最后将该对象的地址return 返回出去;
*** 即:直接执行该函数对象;因此看到了最后的打印的结果:***
4.下面是参考Any类的分析:
分析2.1:Any类
// 可以保存任意的对象
class Any {
public:
using Ptr = std::shared_ptr<Any>;
Any() = default;
~Any() = default;
...
private:
const std::type_info* _type = nullptr;
std::shared_ptr<void> _data;
};
分析:
Any 存储任何对象,主要的构成是_type和_data;_type:是std::type_info类型的常量const指针,即可以在执行期间查询的任意对象类型;
_data:是任何类型的void值;
***知识点std::type_info ***
类 type_info 保有一个类型的实现指定信息,包括类型的名称和比较二个类型相等的方法或相对顺序。
参考文章2:
https://www.cppblog.com/tommy/archive/2006/02/06/3080.html
std::type_info类可以在执行期间查询对象型别
进一步深入查看Any类set函数:
// 函数1
template <typename T, typename... ArgsType>
void set(ArgsType &&...args) {
_type = &typeid(T);
_data.reset(new T(std::forward<ArgsType>(args)...), [](void *ptr) { delete (T *)ptr; });
}
函数1分析:
*** 知识点:std::shard_ptr.reset()***
参考文章:https://zh.cppreference.com/w/cpp/memory/shared_ptr/reset
使用的函数形式:
- std::shard_ptr.reset()
以 ptr 所指向的对象替换被管理对象。能可选地提供删除器 d ,
之后在无 shared_ptr 对象占有该对象时以之销毁新对象。
默认以 delete 表达式为删除器。
始终选择对应提供类型的 delete 表达式,这是函数以使用分离的形参 Y 的模板实现的理由。
- template< class Y, class Deleter >
void reset( Y* ptr, Deleter d );
以指定的删除器 d 为删除器。
Deleter 必须对 T 类型可调用,即 d(ptr)必须为良构,拥有良好定义行为且不抛任何异常。
Deleter 必须可复制构造 (CopyConstructible) ,且其复制构造函数和析构函数必须不抛异常。
等价于 shared_ptr
分析 函数1的_type和_data
_type = &typeid(T);
_type 的值就是获取T的类型,并且返回了取址;因为__type本身是常量const指针,即可以在执行期间查询的任意对象类型;
_data.reset(new T(std::forward<ArgsType>(args)...), [](void *ptr) { delete (T *)ptr; });
_data 的值是 new T的 对象实例,并且传入的参数是args;
并且提供了默认delete函数;
函数2分析:
// 函数2
template <typename T>
void set(std::shared_ptr<T> data) {
if (data) {
_type = &typeid(T);
_data = std::move(data);
} else {
reset();
}
}
分析 函数2的_type和_data
_type = &typeid(T);
_type 的值就是获取T的类型,并且返回了取址;因为__type本身是常量const指针,即可以在执行期间查询的任意对象类型;
_data = std::move(data);
_data 的值是 new T的 对象实例,并且传入的参数是args;
并且提供了默认delete函数;
两个函数是重载关系,怎么选择?
函数1,_data的实例化选择是类,并且实例化具有传入参数;
函数2,单纯的是利用地址,将左值变为右值,没有重新构造对象;
再次说明:Any类只保留了两个成员变量,_type保留类型,_data 保留类的实例对象;
分析2.2 return *((T *)_data.get());
return *((T *)_data.get());
分解拆开看:
_dada.get():
参考文章:https://zh.cppreference.com/w/cpp/memory/shared_ptr/get
第一部分,获取到 返回存储的_data指针。
shared_ptr 可能在存储指向一个对象的指针时共享另一对象的所有权。 get() 返回存储的指针,而非被管理指针。
(T *)_data.get():
第二部分,将获取的对象指针进行(T)强转,改变为T 类型;
最后将该对象的地址return 返回出去;
5.总结:
5.1 关键
主要使用的思想还是异步控制,NoticeCenter类是主动发起类,发起注册(addListener),发起emit的事件分发;
EventDispatcher类是执行类,负责数据的存储add_listerner,负责事件的分发emit。
注册和事件的分发不再同一时刻,都是先将两个绑定关系都先存储到map中;
当需要emit的时候,再通过event查找dispatcher,再通过dispatcher找到对应的Any;
大致的执行过程:
NoticeCenter.add--> noticeCenter和EvnetDispatche存储事件event、事件分发器dispatcher、tag、函数执行函数Any---------
.......若干时间后........
NoticeCenter.emit-->顺着evnet查找dispatcher,进而找到Any并执行;
5.2 绑定关系
理解清楚两个绑定关系大致的脉络就很明了;