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::type将返回T去除引用特性后的类型;否则,返回的类型与T相同。

std::remove_reference是C++标准库 <type_traits> 头文件中的一个类型萃取工具,用于从一个类型中移除引用(Reference)特性。
它返回一个新的类型,该类型是从原始类型中移除了引用特性后得到的。

具体来说,如果输入的类型T是一个引用类型,即T存在引用特性,
则std::remove_reference::type将返回T去除引用特性后的类型;否则,返回的类型与T相同。

*** 知识点 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中存放


  • 总结

    1. 在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));
}
  1. 在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);
        }
    }
  1. 首先获取对应event事件的Dispatcher,不存在则直接返回;
  2. EventDispatcher类中,根据tag,删除_mapListener中的tag-Any的绑定关系; empty 默认是false;
  3. 最后,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循环中打断点:

image-20240204165301694

单步F7调试进入到调用函数EventDispatcher的emitEvent函数内:

image-20240204162400021

image-20240204162430013

看到 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 返回出去;

*** 即:直接执行该函数对象;因此看到了最后的打印的结果:***

image-20240204162820397

image-20240204163031053

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 ***

参考文章1:
https://zh.cppreference.com/w/cpp/types/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(ptr, d).swap(*this); 。

分析 函数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 绑定关系

理解清楚两个绑定关系大致的脉络就很明了;

noticeCenter与EventDispatcher的map关系

posted @ 2024-02-04 17:56  OzTaking  阅读(9)  评论(0编辑  收藏  举报