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.


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

相关推荐

  1. C++/Qt 信号

    2024-07-09 19:00:03       22 阅读
  2. 仿QT信号的简易框架

    2024-07-09 19:00:03       53 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-09 19:00:03       67 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-09 19:00:03       72 阅读
  3. 在Django里面运行非项目文件

    2024-07-09 19:00:03       58 阅读
  4. Python语言-面向对象

    2024-07-09 19:00:03       69 阅读

热门阅读

  1. 柠檬水找零

    2024-07-09 19:00:03       21 阅读
  2. PCIe物理层IP和GT口的关系

    2024-07-09 19:00:03       23 阅读
  3. linux下php的psr.so扩展源码安装

    2024-07-09 19:00:03       19 阅读
  4. 工厂方法模式在金融业务中的应用及其框架实现

    2024-07-09 19:00:03       28 阅读
  5. 速盾:cdn转发ip

    2024-07-09 19:00:03       22 阅读
  6. 雷电模拟如何换ip地址 手机模拟器ip修改方法

    2024-07-09 19:00:03       26 阅读
  7. 深入理解Qt的隐式共享机制

    2024-07-09 19:00:03       55 阅读
  8. 每天10个vue面试题(二)

    2024-07-09 19:00:03       30 阅读