返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >C++利用模板实现消息订阅和分发功能
  • 228
分享到

C++利用模板实现消息订阅和分发功能

C++实现消息订阅分发C++消息订阅C++消息分发C++消息 2022-12-20 15:12:26 228人浏览 安东尼
摘要

解耦是编写程序所遵循的基本原则之一,多态是提高程序灵活性的重要方法。c++语言支持重载,模板,虚函数等特性,为编写高性能可扩展的程序提供了利器。编写大型项目时,免不了需要各个模块之间

解耦是编写程序所遵循的基本原则之一,多态是提高程序灵活性的重要方法。c++语言支持重载,模板,虚函数等特性,为编写高性能可扩展的程序提供了利器。编写大型项目时,免不了需要各个模块之间相互调用,从而产生了模块之间的耦合。不同模块之间的关系称之为耦合,耦合程度由高到底可以分为以下几类:

1. 内容耦合

内容耦合常见情形如下:

1)一个模块直接访问另一个模块的内容

2)一个模块不通过正常入口转到另一个模块

3)两个模块有部分程序代码重叠,常见在汇编语言中

4)一个模块有多个入口

2. 公共耦合

若模块都访问同一个公共数据环境,则称他们是公共耦合。

3. 外部耦合

模块通过非参数传递的方式访问同一个全局变量,则称之为外部耦合。C语言中的extern类型变量就是一种外部耦合。

4. 控制耦合

一个模块通过传送参数和控制信息来选择控制另一个模块的功能,就是控制耦合。控制耦合最常见的方式就是接口调用。

5. 标记耦合

6. 数据耦合

7. 非直接耦合

订阅分发是程序编写常用的设计模式,回调,Qt中的信号槽本质都是订阅模式。两个模块之间可以直接交互,也可以借助第三者来实现交互。下面将展示一种借助第三者来实现模块之间的交互。

messager.hpp

#ifndef _SELF_MAMESSAGE__
#define _SELF_MAMESSAGE__
 
#include <map>
#include <unordered_map>
#include <functional>
#include <string>
#include <vector>
#include <mutex>
#include <atomic>
#include <thread>
#include <condition_variable>
 
class RWLock {
    std::mutex _mutex;				
    std::condition_variable _readcv, _writecv;
    std::atomic_bool _iswritting;	
    std::atomic_int _readcount;	
 
public:
    RWLock() : _iswritting(false) , _readcount(0) {}
    void lockr() {
        if(_iswritting)
        {
            _mutex.lock();
        }
        _readcount++;
    }
 
    void unlockr() {
        _readcount--;
        if(_readcount == 0)
        {
            _mutex.unlock();
        }
    }
 
    void lockw() {
        if(_iswritting || _readcount != 0)
        {
            _mutex.lock();
        }
        _iswritting = true;
    }
 
    void unlockw() {
        _iswritting = false;
        _mutex.unlock();
    }
};
 
class SelfMessager {
public:
    SelfMessager() = delete;
    static void subcribe(const std::string &key, std::function<void()> func) {
        getpubsub_mutex().lockw();
        auto &messager_map = get_messager_map();
        auto &funcs = messager_map[key];
        funcs.push_back(func);
        getpubsub_mutex().unlockw();
    }
 
    template<typename T>
    static void subcribe(const std::string &key, std::function<void(const T &)> func) {
        getpubsub_mutex_p1().lockw();
        auto &messager_map = get_messager_map<T>();
        auto &funcs = messager_map[key];
        funcs.push_back(func);
        getpubsub_mutex_p1().unlockw();
    }
 
    template<typename T0, typename T1>
    static void subcribe(const std::string &key, std::function<void(const T0 &, const T1 &)> func) {
        getpubsub_mutex_p2().lockw();
        auto &messager_map = get_messager_map<T0, T1>();
        auto &funcs = messager_map[key];
        funcs.push_back(func);
        getpubsub_mutex_p2().unlockw();
    }
 
    template<typename T0, typename T1, typename T2>
    static void subcribe(const std::string &key, std::function<void(const T0 &, const T1 &, const T2 &)> func) {
        getpubsub_mutex_p3().lockw();
        auto &messager_map = get_messager_map<T0, T1, T2>();
        auto &funcs = messager_map[key];
        funcs.push_back(func);
        getpubsub_mutex_p3().unlockw();
    }
 
    template<typename T0, typename T1, typename T2>
    static void subcribe(const std::string &key, std::function<void(const T0 &, const T1 &, T2 &)> func) {
        getpubsub_mutex_p3().lockw();
        auto &messager_map = get_messager_map<T0, T1, T2>();
        auto &funcs = messager_map[key];
        funcs.push_back(func);
        getpubsub_mutex_p3().unlockw();
    }
 
    template<typename T0, typename T1, typename T2, typename T3>
    static void
    subcribe(const std::string &key, std::function<void(const T0 &, const T1 &, const T2 &, const T3 &)> func) {
        getpubsub_mutex_p4().lockw();
        auto &messager_map = get_messager_map<T0, T1, T2, T3>();
        auto &funcs = messager_map[key];
        funcs.push_back(func);
        getpubsub_mutex_p4().unlockw();
    }
 
    template<typename T0, typename T1, typename T2, typename T3, typename T4>
    static void subcribe(const std::string &key,
                         std::function<void(const T0 &, const T1 &, const T2 &, const T3 &, const T4 &)> func) {
        getpubsub_mutex_p5().lockw();
        auto &messager_map = get_messager_map<T0, T1, T2, T3, T4>();
        auto &funcs = messager_map[key];
        funcs.push_back(func);
        getpubsub_mutex_p5().unlockw();
    }
 
    static void publish(const std::string &key) {
        getpubsub_mutex().lockr();
        auto &messager_map = get_messager_map();
        if(messager_map.find(key) == messager_map.end()) {
            return;
        }
        auto &funcs = messager_map[key];
        for (const auto &func : funcs) {
            func();
        }
        getpubsub_mutex().unlockr();
    }
 
    template<typename T>
    static void publish(const std::string &key, const T &value) {
        getpubsub_mutex_p1().lockr();
        auto &messager_map = get_messager_map<T>();
        if(messager_map.find(key) == messager_map.end()) {
            return;
        }
        auto &funcs = messager_map[key];
        for (const auto &func : funcs) {
            func(value);
        }
        getpubsub_mutex_p1().unlockr();
    }
 
    template<typename T0, typename T1>
    static void publish(const std::string &key, const T0 &value0, const T1 &value1) {
        getpubsub_mutex_p2().lockr();
        auto &messager_map = get_messager_map<T0, T1>();
        if(messager_map.find(key) == messager_map.end()) {
            return;
        }
        auto &funcs = messager_map[key];
        for (const auto &func : funcs) {
            func(value0, value1);
        }
        getpubsub_mutex_p2().unlockr();
    }
 
    template<typename T0, typename T1, typename T2>
    static void publish(const std::string &key, const T0 &value0, const T1 &value1, const T2 &value2) {
        getpubsub_mutex_p3().lockr();
        auto &messager_map = get_messager_map<T0, T1, T2>();
        if(messager_map.find(key) == messager_map.end()) {
            return;
        }
        auto &funcs = messager_map[key];
        for (const auto &func : funcs) {
            func(value0, value1, value2);
        }
        getpubsub_mutex_p3().unlockr();
    }
 
    template<typename T0, typename T1, typename T2, typename T3>
    static void
    publish(const std::string &key, const T0 &value0, const T1 &value1, const T2 &value2, const T3 &value3) {
        getpubsub_mutex_p4().lockr();
        auto &messager_map = get_messager_map<T0, T1, T2, T3>();
        if(messager_map.find(key) == messager_map.end()) {
            return;
        }
        auto &funcs = messager_map[key];
        for (const auto &func : funcs) {
            func(value0, value1, value2, value3);
        }
        getpubsub_mutex_p4().unlockr();
    }
 
    template<typename T0, typename T1, typename T2, typename T3, typename T4>
    static void publish(const std::string &key, const T0 &value0, const T1 &value1, const T2 &value2, const T3 &value3,
                        const T4 &value4) {
        getpubsub_mutex_p5().lockr();
        auto &messager_map = get_messager_map<T0, T1, T2, T3, T4>();
        if(messager_map.find(key) == messager_map.end()) {
            return;
        }
        auto &funcs = messager_map[key];
        for (const auto &func : funcs) {
            func(value0, value1, value2, value3, value4);
        }
        getpubsub_mutex_p5().unlockr();
    }
 
    template<typename T>
    static void add_server_func(const std::string &key, std::function<T> func) {
        getserverfunc_mutex().lockw();
        auto &server_func = get_server_func<T>(key);
        if (server_func){
             publish("log_fatal", "server_func is already exists, key: " + key);
             throw std::bad_exception();
        }
        server_func = func;
        getserverfunc_mutex().unlockw();
    }
 
    template<typename T>
    static bool has_server(const std::string &key) {
        auto &server_func = get_server_func<T>(key);
        if (server_func){
            return true;
        } else {
            return false;
        }
    }
 
    template<typename T>
    static void remove_server_func(const std::string &key) {
        auto &server_func = get_server_func<T>(key);
        server_func = std::function<T>();
    }
 
    template<typename T>
    static std::function<T> &get_server_func(const std::string &key) {
        getserverfunc_mutex().lockr();
        auto & server_func_map = get_server_map<T>();
        getserverfunc_mutex().unlockr();
        return server_func_map[key];
    }
 
public:
 
    static RWLock& getpubsub_mutex() {
        static RWLock _pubsubmutex;
        return _pubsubmutex;
    }
 
    static RWLock& getpubsub_mutex_p1() {
        static RWLock _pubsubmutex;
        return _pubsubmutex;
    }
 
    static RWLock& getpubsub_mutex_p2() {
        static RWLock _pubsubmutex;
        return _pubsubmutex;
    }
 
    static RWLock& getpubsub_mutex_p3() {
        static RWLock _pubsubmutex;
        return _pubsubmutex;
    }
 
    static RWLock& getpubsub_mutex_p4() {
        static RWLock _pubsubmutex;
        return _pubsubmutex;
    }
 
    static RWLock& getpubsub_mutex_p5() {
        static RWLock _pubsubmutex;
        return _pubsubmutex;
    }
 
    static RWLock& getserverfunc_mutex() {
        static RWLock _serverfuncmutex;
        return _serverfuncmutex;
    }
 
 
    template<typename T>
    static void reGISter_server_map() {
        get_server_map<T>();
    }
 
    static void register_data_map() {
        get_messager_map();
    }
 
    template<typename T>
    static void register_data_map() {
        get_messager_map<T>();
    }
 
    template<typename T0, typename T1>
    static void register_data_map() {
        get_messager_map<T0, T1>();
    }
 
    template<typename T0, typename T1, typename T2>
    static void register_data_map() {
        get_messager_map<T0, T1, T2>();
    }
 
    template<typename T0, typename T1, typename T2, typename T3>
    static void register_data_map() {
        get_messager_map<T0, T1, T2, T3>();
    }
 
    template<typename T0, typename T1, typename T2, typename T3, typename T4>
    static void register_data_map() {
        get_messager_map<T0, T1, T2, T3, T4>();
    }
 
    template<typename T>
    static std::vector<std::string> get_server_list() {
        std::vector<std::string> keys;
        auto& server_map = get_server_map<T>();
        for (auto& server : server_map){
            if (server.second){
                keys.push_back(server.first);
            }
        }
        return keys;
    }
 
private:
    template<typename T>
    static std::unordered_map<std::string, std::function<T>> &get_server_map() {
        static std::unordered_map<std::string, std::function<T>> server_func_map;
        return server_func_map;
    }
 
    static std::unordered_map<std::string, std::vector<std::function<void()>>> &get_messager_map() {
        static std::unordered_map<std::string, std::vector<std::function<void()>>> messager_map;
        return messager_map;
    }
 
    template<typename T>
    static std::unordered_map<std::string, std::vector<std::function<void(const T &)>>> &get_messager_map() {
        static std::unordered_map<std::string, std::vector<std::function<void(const T &)>>> messager_map;
        return messager_map;
    }
 
    template<typename T0, typename T1>
    static std::unordered_map<std::string, std::vector<std::function<void(const T0 &, const T1 &)>>> &get_messager_map() {
        static std::unordered_map<std::string, std::vector<std::function<void(const T0 &, const T1 &)>>> messager_map;
        return messager_map;
    }
 
    template<typename T0, typename T1, typename T2>
    static std::unordered_map<std::string, std::vector<std::function<void(const T0 &, const T1 &, const T2 &)>>> &
    get_messager_map() {
        static std::unordered_map<std::string, std::vector<std::function<void(const T0 &, const T1 &, const T2 &)>>> messager_map;
        return messager_map;
    }
 
    template<typename T0, typename T1, typename T2, typename T3>
    static std::unordered_map<std::string, std::vector<std::function<void(const T0 &, const T1 &, const T2 &, const T3 &)>>> &
    get_messager_map() {
        static std::unordered_map<std::string, std::vector<std::function<void(const T0 &, const T1 &, const T2 &,
                                                                    const T3 &)>>> messager_map;
        return messager_map;
    }
 
    template<typename T0, typename T1, typename T2, typename T3, typename T4>
    static std::unordered_map<std::string, std::vector<std::function<void(const T0 &, const T1 &, const T2 &, const T3 &,
                                                                const T4 &)>>> &
    get_messager_map() {
        static std::unordered_map<std::string, std::vector<std::function<void(const T0 &, const T1 &, const T2 &, const T3 &,
                                                                    const T4 &)>>> messager_map;
        return messager_map;
    }
};
 
 
#endif

test_messager.cpp 

#include <iOStream>
#include <string>
#include <memory>
 
#include "messager.hpp"
 
using namespace std;
 
#define MESSAGE_SHOW_RESULR         "show_result"
#define MESSAGE_ADD_INT_NUMBER      "add_number"
 
struct TData {
    std::string str;
    int   iCount;
    double dPercent;
};
 
// 消息处理者1
class DataDealerOne {
public:
    static DataDealerOne *GetInstance() {
        static DataDealerOne s_instande;
        return &s_instande;
    }
    virtual ~DataDealerOne() {}
    void subcribeMessage() {
        SelfMessager::subcribe<TData>(
            MESSAGE_SHOW_RESULR, 
            [this](const TData &data) {
            auto data_info = std::make_shared<TData>();
            *data_info = data;
            std::cout << data_info->str << " "
                      << data_info->iCount << " "
                      << data_info->dPercent << std::endl;
        });
    }
 
private:
    DataDealerOne() {
    }
};
 
// 消息处理者2
class DataDealerTwo {
public:
    static DataDealerTwo *GetInstance() {
        static DataDealerTwo s_instande;
        return &s_instande;
    }
    virtual ~DataDealerTwo() {}
    void subcribeMessage() {
        SelfMessager::subcribe<int, int>(
            MESSAGE_ADD_INT_NUMBER, 
            [this](const int &a, const int &b) {
                int result = a + b;
                std::cout << a << " + " << b << " = " << result<< std::endl;
        });
    }
 
private:
    DataDealerTwo() {
    }
};
 
class Invoker {
public:
    static Invoker *GetInstance() {
        static Invoker s_instande;
        return &s_instande;
    }
 
    void CallOther(const std::string& message) {
        if (message == MESSAGE_SHOW_RESULR) {
            //发布消息1
            TData data = {"hello world !", 110, 1.234};
            SelfMessager::publish(MESSAGE_SHOW_RESULR, data);
        }
        else if (message == MESSAGE_ADD_INT_NUMBER) {
            //发布消息2
            int num = 0;
            SelfMessager::publish(MESSAGE_ADD_INT_NUMBER, 111, 222);
            std::cout << num << std::endl;
        }
    }
 
private:
    Invoker() {}
};
 
int main(int arGC, char* argv[]) {
    //订阅消息
    DataDealerOne::GetInstance()->subcribeMessage();
    DataDealerTwo::GetInstance()->subcribeMessage();
 
    //调用
    Invoker::GetInstance()->CallOther(MESSAGE_SHOW_RESULR);
    Invoker::GetInstance()->CallOther(MESSAGE_ADD_INT_NUMBER);
 
    return 0;
}

运行效果如下:

到此这篇关于C++利用模板实现消息订阅和分发功能的文章就介绍到这了,更多相关C++消息订阅分发内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: C++利用模板实现消息订阅和分发功能

本文链接: https://lsjlt.com/news/175356.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • C++利用模板实现消息订阅和分发功能
    解耦是编写程序所遵循的基本原则之一,多态是提高程序灵活性的重要方法。C++语言支持重载,模板,虚函数等特性,为编写高性能可扩展的程序提供了利器。编写大型项目时,免不了需要各个模块之间...
    99+
    2022-12-20
    C++实现消息订阅分发 C++ 消息订阅 C++消息分发 C++消息
  • 如何利用Redis和C++实现消息订阅功能
    如何利用Redis和C++实现消息订阅功能消息订阅是现代应用程序开发中常见的一种通信模式,它可以实现实时消息推送和数据更新通知。Redis是一个高性能的内存数据库,它支持发布-订阅模式,并且提供了丰富的功能和API,使得在C++中使用Red...
    99+
    2023-10-22
    C++ redis 消息订阅
  • 利用Redis实现分布式消息发布订阅
    利用Redis实现分布式消息发布订阅在分布式系统中,消息的发布和订阅是常用的通信模式。在这个模式下,消息发布者将消息发送给一个或多个主题,订阅者则订阅感兴趣的主题,并接收相应的消息。为了实现这个模式,我们可以借助Redis这个高性能的内存数...
    99+
    2023-11-07
    分布式 redis 消息订阅
  • Kafka如何实现消息的发布和订阅功能
    Kafka 是一个分布式的消息系统,它实现了消息的发布和订阅功能。在 Kafka 中,消息的发布和订阅是通过 Producer 和 ...
    99+
    2024-03-06
    Kafka
  • 如何利用Redis和C++实现发布-订阅功能
    如何利用Redis和C++实现发布-订阅功能,需要具体代码示例引言:Redis是一种开源的高性能键值存储系统,它支持多种数据结构,并提供了一系列的客户端库,适用于各种编程语言。Redis的发布-订阅功能是其最常用的功能之一,可以实现消息的发...
    99+
    2023-10-22
    C++ redis 发布订阅
  • C#用RabbitMQ实现消息订阅与发布
    目录Fanout交换机模型RabbitMQ控制台操作新增两个队列绑定fanout交换机示例效果图核心代码消息发布消息订阅Fanout交换机模型 扇形交换机,采用广播模式,根据绑定的...
    99+
    2024-04-02
  • 如何利用Redis实现分布式消息发布与订阅
    如何利用Redis实现分布式消息发布与订阅引言:在分布式系统中,消息发布与订阅是一种常见的通信模式,可以实现不同模块之间的解耦。Redis作为一种高性能的键值对存储系统,可以用来实现分布式消息发布与订阅功能。本文将介绍如何使用Redis来实...
    99+
    2023-11-07
    分布式 redis 消息发布
  • 如何使用Redis和Lua开发实时消息订阅功能
    如何使用Redis和Lua开发实时消息订阅功能随着互联网的快速发展,实时消息订阅功能在Web应用中的重要性日益凸显。无论是即时聊天应用、在线协作平台还是实时股票行情等,都需要实时更新消息,以保证用户能够及时获取最新的信息。在开发这类实时功能...
    99+
    2023-10-22
    redis lua 实时消息订阅
  • 小程序发送模板消息给用户 —— 一次性模板实现“长期订阅”
    大家好!我是我玩亚索我会C,在写小程序时,我们会有向用户发送消息的需求,比如发送提醒通知,或者是一些重要通知来形成一个服务的闭环。这就要用到微信的发送消息功能了,下面我使用Java语言来详细演示下如何使用一次性订阅消息发送消息给用户。 ...
    99+
    2023-08-17
    微信小程序 javascript java 小程序 开发语言
  • C#如何用RabbitMQ实现消息订阅与发布
    这篇文章给大家分享的是有关C#如何用RabbitMQ实现消息订阅与发布的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。Fanout交换机模型扇形交换机,采用广播模式,根据绑定的交换机,路由到与之对应的所有队列。一个...
    99+
    2023-06-15
  • 如何利用Redis和C++开发发布-订阅功能
    如何利用Redis和C++开发发布-订阅功能在开发大规模实时系统时,发布-订阅模式被广泛应用于消息传递和事件驱动机制中。Redis是一个高性能的键值存储系统,通过其提供的发布-订阅功能,可以方便地实现实时通信和数据传递。本文将介绍如何利用R...
    99+
    2023-10-22
    C++ redis 发布订阅
  • 使用Spring Boot和Kafka实现消息发送和订阅
    文章目录 一,新建Spring Boot1,Maven配置2,无法识别为SpringBoot项目3,无效的源发行版4,无法访问SpringApplication5,运行直接Finish6,服务...
    99+
    2023-09-05
    spring boot kafka 后端 订阅 消息队列
  • Redis实现消息的发布订阅原理分析
    目录一、什么是发布和订阅二、Redis的发布和订阅三、redis 发布订阅常用命令四、命令实战1、基本使用2、订阅符合要求的频道3、查看活跃频道五、发布订阅原理1、订阅频道原理2、发布信息原理3、退订信息原理一、什么是发...
    99+
    2022-07-25
    Redis消息发布 Redis消息订阅
  • 微信小程序如何实现订阅消息功能
    这篇文章将为大家详细讲解有关微信小程序如何实现订阅消息功能,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。小程序模板消息即将被废弃掉,于是有了新接口wx.requestSu...
    99+
    2024-04-02
  • C++委托和消息反馈模板怎么实现
    本篇内容介绍了“C++委托和消息反馈模板怎么实现”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!继承+多态乍一看是理所当然的选择,库中的类把响...
    99+
    2023-06-17
  • springboot整合netty-mqtt-client实现Mqtt消息的订阅和发布示例
    目录1.添加依赖2.源码3.运行测试1.添加依赖 <dependency> <groupId>org.jetlinks</groupId>...
    99+
    2024-04-02
  • 利用Socket.io 实现消息实时推送功能
    项目背景介绍最近在写的项目中存在着社交模块,需要实现这样的一个功能:当发生了用户被点赞、评论、关注等操作时,需要由服务器向用户实时地推送一条消息。最终完成的项目地址为:https://github.com/noiron/socket-mes...
    99+
    2023-05-30
    socket.io 消息 推送
  • 怎么用redis发布订阅方式实现简易的消息系统
    这篇文章主要讲解了“怎么用redis发布订阅方式实现简易的消息系统”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么用redis发布订阅方式实现简易的消息系统”吧!I. 基本使用1. 配置我...
    99+
    2023-06-19
  • C#模拟实现鼠标自动点击与消息发送功能
    目录实现功能开发环境实现代码实现效果一个简单的实现版本,没有去Hook键鼠等操作,事先录制好操作步骤(将鼠标移动到需要操作的位置,按下热键执行相应动作),点击运行即可。 主要还是用w...
    99+
    2024-04-02
  • 如何利用Redis和Python开发分布式消息推送功能
    如何利用Redis和Python开发分布式消息推送功能一、简介随着互联网的快速发展,实时消息推送功能成为了现代应用中非常重要的一部分。为了实现高并发和分布式的消息推送功能,我们可以利用Redis和Python来实现。二、Redis简介Red...
    99+
    2023-10-22
    Python 分布式 redis 消息推送
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作