首页 > 编程语言 >C++编程:通过简单实现理解CyberRT的DataVisitor和DataDispatcher

C++编程:通过简单实现理解CyberRT的DataVisitor和DataDispatcher

时间:2024-12-01 14:02:14浏览次数:8  
标签:std DataDispatcher CyberRT DataVisitor shared include data ptr

文章目录

0. 引言

本文简单实现类似 CyberRT 的 DataVisitorDataDispatcher ,使得数据能够被分发给多个订阅者(访客)。

1. 定义 DataVisitor 接口

DataVisitor 是一个接口(抽象基类),定义了所有具体访客需要实现的 Visit 方法。这个方法将用于处理分发的数据。

// DataVisitor.h
#ifndef DATA_VISITOR_H
#define DATA_VISITOR_H

#include <memory>

// 定义一个通用的数据类型,您可以根据需求进行扩展
struct Data {
   int id;
   std::string content;
};

class DataVisitor {
public:
   virtual ~DataVisitor() = default;
   
   // 处理数据的方法
   virtual void Visit(const std::shared_ptr<Data>& data) = 0;
};

#endif // DATA_VISITOR_H

2. 实现 DataDispatcher

DataDispatcher 负责管理多个 DataVisitor,并在有新数据时将其分发给所有注册的访客。

// DataDispatcher.h
#ifndef DATA_DISPATCHER_H
#define DATA_DISPATCHER_H

#include "DataVisitor.h"
#include <vector>
#include <memory>
#include <mutex>

class DataDispatcher {
public:
   // 添加一个访客
   void AddVisitor(const std::shared_ptr<DataVisitor>& visitor) {
       std::lock_guard<std::mutex> lock(mutex_);
       visitors_.emplace_back(visitor);
   }

   // 移除一个访客
   void RemoveVisitor(const std::shared_ptr<DataVisitor>& visitor) {
       std::lock_guard<std::mutex> lock(mutex_);
       visitors_.erase(
           std::remove(visitors_.begin(), visitors_.end(), visitor),
           visitors_.end()
       );
   }

   // 分发数据给所有访客
   void Dispatch(const std::shared_ptr<Data>& data) {
       std::lock_guard<std::mutex> lock(mutex_);
       for (auto& visitor : visitors_) {
           if (visitor) {
               visitor->Visit(data);
           }
       }
   }

private:
   std::vector<std::shared_ptr<DataVisitor>> visitors_;
   std::mutex mutex_; // 保护 visitors_ 的线程安全
};

#endif // DATA_DISPATCHER_H

3. 创建具体的 DataVisitor

实现具体的 DataVisitor,例如 LoggingVisitor,用于记录接收到的数据。

// LoggingVisitor.h
#ifndef LOGGING_VISITOR_H
#define LOGGING_VISITOR_H

#include "DataVisitor.h"
#include <iostream>

class LoggingVisitor : public DataVisitor {
public:
   void Visit(const std::shared_ptr<Data>& data) override {
       std::cout << "LoggingVisitor received data: ID=" 
                 << data->id << ", Content=\"" 
                 << data->content << "\"" << std::endl;
   }
};

#endif // LOGGING_VISITOR_H

另一个示例,ProcessingVisitor,用于处理数据。

// ProcessingVisitor.h
#ifndef PROCESSING_VISITOR_H
#define PROCESSING_VISITOR_H

#include "DataVisitor.h"

class ProcessingVisitor : public DataVisitor {
public:
   void Visit(const std::shared_ptr<Data>& data) override {
       // 简单示例:打印数据长度
       std::cout << "ProcessingVisitor processed data ID=" 
                 << data->id << ", Length=" 
                 << data->content.length() << std::endl;
   }
};

#endif // PROCESSING_VISITOR_H

4. 类关系图

这个类关系图展示了 DataDispatcherDataVisitor 之间的继承与关联关系,以及具体的访客类。

管理 1 * 分发 Data +int id +std::string content «abstract» DataVisitor +Visit(std::shared_ptr<data> data) LoggingVisitor +Visit(std::shared_ptr<data> data) ProcessingVisitor +Visit(std::shared_ptr<data> data) DataDispatcher -std::vector> visitors -std::mutex mutex +AddVisitor(std::shared_ptr visitor) +RemoveVisitor(std::shared_ptr visitor) +Dispatch(std::shared_ptr<data> data)

5. 测试示例

// main.cpp
#include "DataDispatcher.h"
#include "LoggingVisitor.h"
#include "ProcessingVisitor.h"
#include <memory>

int main() {
   // 创建 DataDispatcher
   DataDispatcher dispatcher;

   // 创建并注册访客
   auto logger = std::make_shared<LoggingVisitor>();
   auto processor = std::make_shared<ProcessingVisitor>();
   dispatcher.AddVisitor(logger);
   dispatcher.AddVisitor(processor);

   // 创建一些数据并分发
   auto data1 = std::make_shared<Data>();
   data1->id = 1;
   data1->content = "Hello, CyberRT!";
   
   dispatcher.Dispatch(data1);

   // 移除一个访客
   dispatcher.RemoveVisitor(logger);

   // 分发另一个数据
   auto data2 = std::make_shared<Data>();
   data2->id = 2;
   data2->content = "Another data packet.";
   
   dispatcher.Dispatch(data2);

   return 0;
}

6. 编译和运行

确保所有头文件和源文件位于正确的位置,并使用以下命令进行编译(假设所有文件在同一目录下):

g++ -std=c++14 main.cpp -o dispatcher

运行程序后,您将看到类似如下的输出:

LoggingVisitor received data: ID=1, Content="Hello, CyberRT!"
ProcessingVisitor processed data ID=1, Length=14
ProcessingVisitor processed data ID=2, Length=19

注意,第二次分发时,LoggingVisitor 已被移除,因此只 ProcessingVisitor 会处理 data2

标签:std,DataDispatcher,CyberRT,DataVisitor,shared,include,data,ptr
From: https://blog.csdn.net/stallion5632/article/details/144168832

相关文章

  • CyberRT_不同的启动方式的源码解读
    源码解读componentnodereader/writerservice/clientparameterscheduletransportapollo/cyber/cyber.ccCreateNode(){returnstd::unique_ptr<Node>(newNode(node_name,name_space))}apollo/cyber/init.ccInit() OnShutdown()apollo/cyber......
  • CyberRT_record解析代码走读
    共享内存共享内存可以说是最有用的进程间通信方式,也是最快的IPC形式。两个不同进程A、B共享内存的意思是,同一块物理内存被映射到进程A、B各自的进程地址空间。进程A可以即时看到进程B对共享内存中数据的更新,反之亦然。由于多个进程共享同一块内存区域,必然需要某种同步机......
  • CyberRT_概念组件以及基本流程
    CyberRT两大功能任务调度数据通信基本组件componentnodechannelreader/writersevice/clientTaskroutine通信1.通信的方式:01.intras-process02.sharedMemory 03.socket--fastRTPSDDS也是采用发布/订阅机制进行网络通讯通过抽象出DDS接口,让RO......
  • CyberRT_数据解析和处理
    CyberRT01.数据传输Apollo项目CyberRT主要包括下面三个方面:通信性能优化去中心化网络拓扑数据兼容性扩展ROS系统中,使用msg描述文件定义模块间的消息接口Apollo选择了Google的ProtocolBuffers格式数据 数据进行传输的时候,是一个......
  • 中间件_ROS2和CyberRT
    中间件中间件的主要任务,是负责各类应用软件模块之间的通信以及对系统资源的调度。进程间通信的机制(IPC:inter-processcommuniction)内容都是与具体应用逻辑无关的,包括数据通信、通信安全、系统资源调度等1.Ros2.iceoryx「冰羚」RouDi的名称由来是’‘Rou’‘ting和......