首页 > 其他分享 >test_noticeCenter

test_noticeCenter

时间:2024-02-04 18:02:36浏览次数:29  
标签:30 20 noticeCenter 3.14 cpp test

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);

  • 注意:
  • 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);

image-20240201142322340

此时放入_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的关系;

    image-20240202165309818

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关系

标签:30,20,noticeCenter,3.14,cpp,test
From: https://www.cnblogs.com/Oztaking/p/18006718

相关文章

  • AtCoder Beginner Contest 339
    基本情况A和C出的比较快但不能说秒了还是思考了几分钟的,然后B很奇怪我样例还有一些测试点都能过,但有些测试点就是过不了...A-TLD貌似没啥说的B-Langton'sTakahashi说实话现在还是不懂我的哪里错了很不科学啊,明明很多测试点都过了啊C-PerfectBus做题时的思路:要想求......
  • MSTest 导出报告
    youcanuse TRXER tooltogenerateHTMLreportsfromtrxfile.DownloadTrxerConsole.exefilefrom hereBuild/Rebuildtheprojecttocreate.dllfile.IfyourprojectnameisUnitTest1thenthe.dllfilenamewillbeUnitTest1.dll.Gotothelocationof......
  • Japan Registry Services (JPRS) Programming Contest 2024 (AtCoder Beginner Contes
    //这一场我感觉有了新的蜕变思考问题也变了多种,3题(✌)A-TLD思路:题目本意 Youaregivenastring S, Printthelastsubstringwhen S issplitby .s给你一个字符串输出最后的点的网址(类似)的后缀,入坑点没有,题意简单。思路方法:最后一个‘.’为停止符号,倒的字符串......
  • AtCoder Beginner Contest 339
    基本情况ABC秒了,D读错题卡了一段时间,还好爆搜强项,E感觉极其类似LIS,但是似乎又不能用二分DP来写。E感觉极其类似LIS,但是暴力DP肯定T,又知道不能用二分优化事实如此,确实类似LIS,但是通过线段树来维护区间最大值.暂时还没有熟练线段树,先用atc的库来平替.实现上就是将元素依次......
  • Atcoder Beginner Contest 339 解题报告
    AtcoderBeginnerContest339场评:B>C,D>E,F>G,中国选手最擅长的G,集体上分。A-TLDSimulate.strings;voidSolve(){ charc; while(cin>>c) { if(c=='.')s=""; elses+=c; } cout<<s;}B-Langton'sTakahashiSimulat......
  • AtCoder Beginner Contest 339
    A-TLD(abc339A)题目大意给一个网址,问它的后缀是多少。解题思路找到最后的'.'的位置,然后输出后面的字符串即可。python可以一行。神奇的代码print(input().split('.')[-1])B-Langton'sTakahashi(abc339B)题目大意二维网格,上下左右相连,左上原点。初始全部为......
  • 2020-2021 ICPC East Central North America Regional Contest (ECNA 2020)
    Preface队友C麻了我直接3h下班雀魂启动,如果时间多点感觉还有AK希望不过不得不说北美场难度都集中在模拟题上了,一般压轴都是数学或者几何,而这类题目遇到徐神祁神就是洒洒水了A.AllintheFamily出题人真是丧心病狂,不过这题只是看起来恶心实际写起来感觉还好做法本身由于树......
  • AtCoder Beginner Contest 333
    ABC334总结https://atcoder.jp/contests/abc333A-ThreeThrees翻译输入一个正整数\(n\),输出\(n\)遍这个正整数。\(1\len\le9\)。分析没啥好说的,直接输出就好了。code#include<bits/stdc++.h>usingnamespacestd;typedeflonglongll;intn;intmain()......
  • 【APP自动化进阶】pytest+appium多设备并发
    并发编程基础【Python进阶】并发编程方式APP自动化并发项目实战项目步骤获取设备信息并根据设备数量开启n个进程appium服务处理pytest前置处理开启appium服务pytest后置处理关闭appium服务pytest进行用例执行,并输出报告数据等待进程执行完毕生成每个设备的allure报告......
  • 2022-2023 ICPC East Central North America Regional Contest (ECNA 2022)
    Preface闲了两天没训练,今天又开始上班,结果唐得发昏后期也没题可写直接光速下班只能说感觉老外的题目难度跨度都好大,easy确实简单,hard确实难,medium确实少A.A-MazingPuzzle题目看起来很复杂,但仔细一想会发现有用的状态总数只有\(4n^2\)种即我们可以暴力记录下两个机器人的坐......