日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

C++利用模板實現消息訂閱和分發功能_C 語言

作者:hsy12342611 ? 更新時間: 2023-01-20 編程語言

解耦是編寫程序所遵循的基本原則之一,多態是提高程序靈活性的重要方法。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;
}

運行效果如下:

原文鏈接:https://blog.csdn.net/hsy12342611/article/details/128376383

欄目分類
最近更新