轻量级消息总线实现 (C++)

轻量级消息总线实现 (C++)

消息总线是一种用于组件间通信的架构模式,它允许系统中的不同部分通过发布/订阅机制进行松耦合的交互。下面是一个轻量级的C++消息总线实现。

基本实现

1. 消息总线核心类

#include <functional>
#include <map>
#include <vector>
#include <memory>
#include <mutex>
#include <any>

class MessageBus {
public:
    using Handler = std::function<void(const std::any&)>;
    
    // 订阅消息
    template <typename MessageType>
    void subscribe(std::function<void(const MessageType&)> handler) {
        std::lock_guard<std::mutex> lock(mutex_);
        std::type_index typeIndex(typeid(MessageType));
        handlers_[typeIndex].emplace_back(
            [handler](const std::any& message) {
                handler(std::any_cast<MessageType>(message));
            });
    }
    
    // 发布消息
    template <typename MessageType>
    void publish(const MessageType& message) {
        std::lock_guard<std::mutex> lock(mutex_);
        std::type_index typeIndex(typeid(MessageType));
        auto it = handlers_.find(typeIndex);
        if (it != handlers_.end()) {
            for (auto& handler : it->second) {
                handler(message);
            }
        }
    }
    
private:
    std::map<std::type_index, std::vector<Handler>> handlers_;
    std::mutex mutex_;
};

2. 使用示例

#include <iostream>
#include <string>

// 定义消息类型
struct TestMessage {
    int id;
    std::string content;
};

struct AnotherMessage {
    float value;
};

int main() {
    MessageBus bus;
    
    // 订阅TestMessage
    bus.subscribe<TestMessage>([](const TestMessage& msg) {
        std::cout << "Received TestMessage: " << msg.id 
                  << ", " << msg.content << std::endl;
    });
    
    // 订阅AnotherMessage
    bus.subscribe<AnotherMessage>([](const AnotherMessage& msg) {
        std::cout << "Received AnotherMessage: " << msg.value << std::endl;
    });
    
    // 发布消息
    bus.publish(TestMessage{1, "Hello"});
    bus.publish(AnotherMessage{3.14f});
    
    return 0;
}

高级特性实现

1. 线程安全的单例模式

class MessageBus {
public:
    // 获取单例实例
    static MessageBus& instance() {
        static MessageBus instance;
        return instance;
    }
    
    // 删除拷贝构造函数和赋值运算符
    MessageBus(const MessageBus&) = delete;
    MessageBus& operator=(const MessageBus&) = delete;
    
    // ... 其他成员函数同上 ...
    
private:
    MessageBus() = default;
    ~MessageBus() = default;
    
    // ... 其他成员变量同上 ...
};

2. 支持取消订阅

class MessageBus {
public:
    using HandlerId = size_t;
    
    template <typename MessageType>
    HandlerId subscribe(std::function<void(const MessageType&)> handler) {
        std::lock_guard<std::mutex> lock(mutex_);
        std::type_index typeIndex(typeid(MessageType));
        HandlerId id = nextHandlerId_++;
        handlers_[typeIndex].emplace_back(
            id,
            [handler](const std::any& message) {
                handler(std::any_cast<MessageType>(message));
            });
        return id;
    }
    
    void unsubscribe(std::type_index typeIndex, HandlerId id) {
        std::lock_guard<std::mutex> lock(mutex_);
        auto it = handlers_.find(typeIndex);
        if (it != handlers_.end()) {
            auto& handlers = it->second;
            handlers.erase(
                std::remove_if(handlers.begin(), handlers.end(),
                    [id](const auto& pair) { return pair.first == id; }),
                handlers.end());
        }
    }
    
private:
    std::map<std::type_index, std::vector<std::pair<HandlerId, Handler>>> handlers_;
    HandlerId nextHandlerId_ = 0;
    // ... 其他成员变量 ...
};

3. 异步消息处理

#include <future>
#include <queue>

class MessageBus {
public:
    // 异步发布消息
    template <typename MessageType>
    std::future<void> publishAsync(const MessageType& message) {
        return std::async(std::launch::async, [this, message] {
            this->publish(message);
        });
    }
    
    // 处理消息队列
    void processQueue() {
        while (!messageQueue_.empty()) {
            auto task = std::move(messageQueue_.front());
            messageQueue_.pop();
            task();
        }
    }
    
    // 延迟发布
    template <typename MessageType>
    void publishDelayed(const MessageType& message) {
        std::lock_guard<std::mutex> lock(queueMutex_);
        messageQueue_.emplace([this, message] {
            this->publish(message);
        });
    }
    
private:
    std::queue<std::function<void()>> messageQueue_;
    std::mutex queueMutex_;
};

性能优化建议

  1. 使用对象池:对于频繁创建销毁的消息对象,可以使用对象池减少内存分配开销

  2. 类型擦除优化:使用更高效的类型擦除技术替代std::any

  3. 无锁队列:在高并发场景下,考虑使用无锁队列替代互斥锁

  4. 批量处理:支持批量消息发布以减少锁竞争

完整实现示例

#include <functional>
#include <map>
#include <vector>
#include <memory>
#include <mutex>
#include <any>
#include <typeindex>
#include <queue>
#include <future>

class MessageBus {
public:
    using HandlerId = size_t;
    using Handler = std::function<void(const std::any&)>;
    
    // 获取单例实例
    static MessageBus& instance() {
        static MessageBus instance;
        return instance;
    }
    
    // 订阅消息
    template <typename MessageType>
    HandlerId subscribe(std::function<void(const MessageType&)> handler) {
        std::lock_guard<std::mutex> lock(mutex_);
        std::type_index typeIndex(typeid(MessageType));
        HandlerId id = nextHandlerId_++;
        handlers_[typeIndex].emplace_back(
            id,
            [handler](const std::any& message) {
                handler(std::any_cast<MessageType>(message));
            });
        return id;
    }
    
    // 取消订阅
    void unsubscribe(std::type_index typeIndex, HandlerId id) {
        std::lock_guard<std::mutex> lock(mutex_);
        auto it = handlers_.find(typeIndex);
        if (it != handlers_.end()) {
            auto& handlers = it->second;
            handlers.erase(
                std::remove_if(handlers.begin(), handlers.end(),
                    [id](const auto& pair) { return pair.first == id; }),
                handlers.end());
        }
    }
    
    // 同步发布
    template <typename MessageType>
    void publish(const MessageType& message) {
        std::vector<Handler> handlersToCall;
        {
            std::lock_guard<std::mutex> lock(mutex_);
            std::type_index typeIndex(typeid(MessageType));
            auto it = handlers_.find(typeIndex);
            if (it != handlers_.end()) {
                for (auto& [id, handler] : it->second) {
                    handlersToCall.push_back(handler);
                }
            }
        }
        
        for (auto& handler : handlersToCall) {
            handler(message);
        }
    }
    
    // 异步发布
    template <typename MessageType>
    std::future<void> publishAsync(const MessageType& message) {
        return std::async(std::launch::async, [this, message] {
            this->publish(message);
        });
    }
    
    // 延迟发布
    template <typename MessageType>
    void publishDelayed(const MessageType& message) {
        std::lock_guard<std::mutex> lock(queueMutex_);
        messageQueue_.emplace([this, message] {
            this->publish(message);
        });
    }
    
    // 处理延迟队列
    void processQueue() {
        std::queue<std::function<void()>> queue;
        {
            std::lock_guard<std::mutex> lock(queueMutex_);
            queue.swap(messageQueue_);
        }
        
        while (!queue.empty()) {
            auto task = std::move(queue.front());
            queue.pop();
            task();
        }
    }
    
private:
    MessageBus() = default;
    ~MessageBus() = default;
    MessageBus(const MessageBus&) = delete;
    MessageBus& operator=(const MessageBus&) = delete;
    
    std::map<std::type_index, std::vector<std::pair<HandlerId, Handler>>> handlers_;
    std::queue<std::function<void()>> messageQueue_;
    std::mutex mutex_;
    std::mutex queueMutex_;
    HandlerId nextHandlerId_ = 0;
};

这个轻量级消息总线实现提供了:

  • 线程安全的发布/订阅机制

  • 同步和异步消息发布

  • 延迟消息处理

  • 单例模式访问

  • 取消订阅功能

可以根据具体需求进一步扩展或优化。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值