C++ 仿QT信号槽二

// 实现原理
// 每个signal映射到bitset位,全集
// 每个slot做为signal的bitset子集
// signal全集触发,标志位有效
// flip将触发事件队列前置
// slot检测智能指针全集触发的标志位,主动运行子集绑定的函数
// 下一帧对bitset全集进行触发清空,防止slot一直检测到signal触发

#include <any>
#include <iostream>

#include "blinker.h"

void testMatch() {
    blinker::SignalTrie<1024> trie;
    trie.Put("ab.cd.ef", 1);
    trie.Put("ab.cd.kk", 2);
    trie.Put("ab.xy.zz", 3);
    trie.Put("tt.xx", 4);
    trie.Put("ab.cd", 5);

    auto m1 = trie.Match("ab.cd.ef");
    //REQUIRE(m1.count() == 1);
    //REQUIRE(m1[1]);

    auto m2 = trie.Match("ab.cd.kk");
    //REQUIRE(m2.count() == 1);
    //REQUIRE(m2[2]);

    auto m3 = trie.Match("ab.xy.zz");
    //REQUIRE(m3.count() == 1);
    //REQUIRE(m3[3]);

    auto m4 = trie.Match("ab.not.found");
    //REQUIRE(m4.count() == 0);

    auto m5 = trie.Match("ab.*");
    //REQUIRE(m5.count() == 4);
    //REQUIRE(m5[1]);
    //REQUIRE(m5[2]);
    //REQUIRE(m5[3]);
    //REQUIRE(m5[5]);

    auto m6 = trie.Match("*");
    //REQUIRE(m6.count() == 5);
    //REQUIRE(m6[1]);
    //REQUIRE(m6[2]);
    //REQUIRE(m6[3]);
    //REQUIRE(m6[4]);
    //REQUIRE(m6[5]);

    auto m7 = trie.Match("ab.cd.*");
    //REQUIRE(m7.count() == 2);
    //REQUIRE(m7[1]);
    //REQUIRE(m7[2]);

    auto m8 = trie.Match("tt.xx.");
    //REQUIRE(m8.count() == 0);

    auto m9 = trie.Match("tt.xx.*");
    //REQUIRE(m9.count() == 0);

    auto m10 = trie.Match("ab.cd");
    //REQUIRE(m10.count() == 1);
    //REQUIRE(m10[5]);
}

void testValue() {
    struct Data {
        int value = 1;
        Data(int value) : value(value) {}
    };

    blinker::Board board;

    auto signal1 = board.NewSignal("ab.cd");
    auto signal2 = board.NewSignal("ab.ef");
    auto signal3 = board.NewSignal("xy.zk");

    auto conn1 = board.Connect("ab.*");
    auto conn2 = board.Connect("ab.cd");
    auto conn3 = board.Connect("ab.ef");
    auto conn4 = board.Connect("xy.zk");
    auto conn5 = board.Connect("*");

    bool conn1CallbackCalled = false;
    bool conn2CallbackCalled = false;
    bool conn3CallbackCalled = false;
    bool conn4CallbackCalled = false;
    bool conn5CallbackCalled = false;

    auto tick = [&]() {
        signal1->Emit(std::make_shared<Data>(1));
        signal2->Emit(std::make_shared<Data>(2));
        signal3->Emit(std::make_shared<Data>(3));

        // signal1 and signal2
        conn1->Poll([&](const blinker::SignalId id, std::any data) {
            conn1CallbackCalled = true;
            auto p = std::any_cast<std::shared_ptr<Data>>(data);
            if (id == signal1->Id())
                std::cout << "value: " << p->value << std::endl;
            else if (id == signal2->Id())
                std::cout << "value: " << p->value << std::endl;
            else
                std::cout << "value error!" << std::endl;
            });

        // signal1
        conn2->Poll([&](const blinker::SignalId id, std::any data) {
            conn2CallbackCalled = true;
            auto p = std::any_cast<std::shared_ptr<Data>>(data);
            if (id == signal1->Id())
                std::cout << "value: " << p->value << std::endl;
            else
                std::cout << "value error!" << std::endl;
            });

        // signal2
        conn3->Poll([&](const blinker::SignalId id, std::any data) {
            conn3CallbackCalled = true;
            auto p = std::any_cast<std::shared_ptr<Data>>(data);
            if (id == signal2->Id())
                std::cout << "value: " << p->value << std::endl;
            else
                std::cout << "value error!" << std::endl;
            });

        // signal3
        conn4->Poll([&](const blinker::SignalId id, std::any data) {
            conn4CallbackCalled = true;
            auto p = std::any_cast<std::shared_ptr<Data>>(data);
            if (id == signal3->Id())
                std::cout << "value: " << p->value << std::endl;
            else                
                std::cout << "value error!" << std::endl;
            });

        // all signals
        conn5->Poll([&](const blinker::SignalId id, std::any data) {
            conn5CallbackCalled = true;
            auto p = std::any_cast<std::shared_ptr<Data>>(data);
            if (id == signal1->Id())
                std::cout << "value: " << p->value << std::endl;
            else if (id == signal2->Id())
                std::cout << "value: " << p->value << std::endl;
            else if (id == signal3->Id())
                std::cout << "value: " << p->value << std::endl;
            else
                std::cout << "value error!" << std::endl;
            });

        board.Flip();
        };

    tick();
    // still not called.
    tick();
    // called after flip
}

int testLoops() {
    // Creates a board.
    blinker::Board board;

    // Creates signals.
    auto taskStarted = board.NewSignal("task.started");
    auto taskEnded = board.NewSignal("task.ended");
    auto actionStarted = board.NewSignal("action.started");

    // Creates connection to match some signals.
    auto connection = board.Connect("task.*");

    // Callback to be called on signal fire.
    auto callback = [&](const blinker::SignalId id, std::any data) {
        if (id == taskStarted->Id())
            std::cout << "signal taskStarted:";
        else if (id == taskEnded->Id())
            std::cout << "signal taskEnded:";
        else if (id == actionStarted->Id())
            std::cout << "signal actionStarted-:";
        std::cout << std::any_cast<int>(data) << std::endl;
        };

    // Assuming your main tick function here.
    for (int i = 0; i < 10; i++) {
        // Emit some signals (to backend).
        taskStarted->Emit(i);
        taskEnded->Emit(i);
        actionStarted->Emit(i);

        // Poll from frontend.
        connection->Poll(callback);

        // Flip double buffers.
        board.Flip();
    }

    return 0;
}

void test() {
    testMatch();
    testValue();
    testLoops();
}

输出

value: 1
value: 2
value: 1
value: 2
value: 3
value: 1
value: 2
value: 3
signal taskStarted:0
signal taskEnded:0
signal taskStarted:1
signal taskEnded:1
signal taskStarted:2
signal taskEnded:2
signal taskStarted:3
signal taskEnded:3
signal taskStarted:4
signal taskEnded:4
signal taskStarted:5
signal taskEnded:5
signal taskStarted:6
signal taskEnded:6
signal taskStarted:7
signal taskEnded:7
signal taskStarted:8
signal taskEnded:8

参考

GitHub - hit9/blinker.h: A lightweight signal/event library for C++, similar to Python's blinker, but designed to work with ticking loops.


创作不易,小小的支持一下吧!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/774876.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

CUDA编程基础

文章目录 1、GPU介绍2、CUDA程序进行编译3、CUDA线程模型3.1、一维网格一维线程块3.2、二维网格二维线程块3.3、三维网格三维线程块3.3、不同组合形式 4、nvcc编译流程5、CUDA程序基本架构6、错误检测函数6.1、运行时API错误代码6.2、检查核函数 7、CUDA记时7.1、记时代码7.2、…

基于Python爬虫的城市二手房数据分析可视化

基于Python爬虫的城市二手房数据分析可视化 一、前言二、数据采集(爬虫,附完整代码)三、数据可视化(附完整代码)3.1 房源面积-总价散点图3.2 各行政区均价3.3 均价最高的10个小区3.4 均价最高的10个地段3.5 户型分布3.6 词云图四、如何更换城市一、前言 二手房具有价格普…

博途通讯笔记1:1200与1200之间S7通讯

目录 一、添加子网连接二、创建PUT GET三、各个参数的意义 一、添加子网连接 二、创建PUT GET 三、各个参数的意义

换根dp,CF 633F - The Chocolate Spree

一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 633F - The Chocolate Spree 二、解题报告 1、思路分析 2600的题&#xff0c;但是不算很困难。 先考虑暴力做法&#xff0c;如何得到两条不相交的路径&#xff1f; 枚举删除的边&#xff0c;得到两棵子树…

鼠标自动点击器怎么用?鼠标连点器入门教程!

鼠标自动点击器是适用于Windows电脑的自动执行鼠标点击操作的工具&#xff0c;主要用于模拟鼠标点击操作&#xff0c;实现鼠标高速点击的操作。通过模拟鼠标点击&#xff0c;可以在用户设定的位置、频率和次数下自动执行点击动作。 鼠标自动点击器主要的应用场景&#xff1a; …

数据操作10-15题(30 天 Pandas 挑战)

数据操作 1. 相关知识点1.12 分组与连表1.13 排名 2. 题目2.10 第N高的薪水2.11 第二高的薪水2.12 部门工资最高的员工2.13 分数排名2.14 删除重复的电子邮箱2.15 每个产品在不同商店的价格 1. 相关知识点 1.12 分组与连表 分组max_salaryemployee.groupby(departmentId)[sal…

超简易SpringBoot工程构建与部署 ( 图解 - 零基础专属 )

目录 简单了解MVC架构 模型&#xff08;Model&#xff09; 视图&#xff08;View&#xff09; 控制器&#xff08;Controller&#xff09; 基本环境准备 MYSQL建库建表 创库创表 智能生成数据 创建SpringBoot项目 配置pox.xml 代码提供 补充(IDEA的Maven要配置正确…

用kimi和claude自动生成时间轴图表

做时间轴图表并不难&#xff0c;但是很麻烦&#xff0c;先要大量收集相关事件&#xff0c;然后在一些图表软件中反复调整操作。现在借助AI工具&#xff0c;可以自动生成了。 首先&#xff0c;在kimi中输入提示词来获取某个企业的大事记&#xff1a; 联网检索&#xff0c;元语…

前后端数据交互流程

一、前言 用户在浏览器访问一个网站时&#xff0c;会有前后端数据交互的过程&#xff0c;前后端数据交互也有几种的情况&#xff0c;一下就简单的来说明一下 二、原理 介绍前后端交互前先来了解一下浏览器的功能&#xff0c;浏览器通过渲染引擎和 JavaScript 引擎协同工作&am…

uboot ethernet初始化

在Board_r.c 使用initr_net,先初始化phy,然后初始化gmac,driver/net/gmacv300/gmac.c实现管脚复用和gmac设备注册 Board_r.c #ifdef CONFIG_CMD_NETstatic int initr_net(void){puts("Net: ");eth_initialize();#if defined(CONFIG_RESET_PHY_R)debug("Reset…

计算机视觉 图像融合技术概览

在许多计算机视觉应用中(例如机器人运动和医学成像),需要将来自多幅图像的相关信息集成到一幅图像中。这种图像融合将提供更高的可靠性、准确性和数据质量。 多视图融合可以提高图像的分辨率,同时恢复场景的 3D 表示。多模态融合结合了来自不同传感器的图像,称为多传感器融…

短视频文案提取神器怎么提取抖音视频文案!

很多编导以及视频内容创作者为了提高自己的工作效率还会使用视频转文字提取神器&#xff0c;我们都清楚短视频领域每个平台人群熟悉都有所不同&#xff0c;在分发内容的时候也会调整内容已符合平台属性。 短视频文案提取神器怎么提取抖音视频文案 短视频常见的平台有抖音、西瓜…

SpringBoot实战:轻松实现XSS攻击防御(注解和过滤器)

文章目录 引言一、XSS攻击概述1.1 XSS攻击的定义1.2 XSS攻击的类型1.3 XSS攻击的攻击原理及示例 二、Spring Boot中的XSS防御手段2.1 使用注解进行XSS防御2.1.1 引入相关依赖2.1.2 使用XSS注解进行参数校验2.1.3 实现自定义注解处理器2.1.4 使用注解 2.2 使用过滤器进行XSS防御…

现在这个行情怎么理解股票期权?一个守住底线的工具!

今天带你了解现在这个行情怎么理解股票期权&#xff1f;一个守住底线的工具&#xff01;股票期权是一种金融衍生品&#xff0c;给予持有者在未来特定时间以特定价格购买或出售股票的权利。 行情看down可以买入看跌期权&#xff0c;看跌期权的买方是因为预计行情的价格会在近期…

imx6ull/linux应用编程学习(11)CAN应用编程基础

关于裸机的can通信&#xff0c;会在其他文章发&#xff0c;这里主要讲讲linux上的can通信。 与I2C,SPI等同步通讯方式不同&#xff0c;CAN通讯是异步通讯&#xff0c;也就是没有时钟信号线来保持信号接收同步&#xff0c;也就是所说的半双工&#xff0c;无法同时发送与接收&…

【python】PyQt5控件尺寸大小位置,内容边距等API调用方法实战解析

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

小(微)间距P1.538COB渠道现货销售将加速全面升级替换SMD产品。

COB&#xff08;Chip on Board&#xff09;技术&#xff0c;如一颗璀璨的星辰&#xff0c;在上世纪60年代的科技夜空中悄然升起。它巧妙地将LED芯片镶嵌在PCB电路板的怀抱中&#xff0c;再用特种树脂为其披上一层坚韧的外衣&#xff0c;宛如一位精心雕琢的艺术家在创作一幅完美…

【Python机器学习】处理文本数据——用tf-idf缩放数据

为了按照我们预计的特征信息量大小来缩放特征&#xff0c;而不是舍弃那些认为不重要的特征&#xff0c;最常见的一种做法就是使用词频-逆向文档频率&#xff08;tf-idf&#xff09;。这一方法对某个特定文档中经常出现的术语给与很高的权重&#xff0c;但是堆在语料库的许多文档…

【UE5.1】Chaos物理系统基础——04 事件驱动粒子效果

目录 效果 步骤 一、炸开时的烟雾效果 二、炸开时的碎片效果 效果 步骤 一、炸开时的烟雾效果 1. 选中场景中的几何体集&#xff0c;勾选“通知中断”&#xff0c;这样当几何体集解体时就能产生一个事件&#xff1b;勾选“通知碰撞”&#xff0c;当几何体集检测到碰撞也能…