当前位置: 首页 > article >正文

FastDDS中Utils定义的那些数据结构(二)

1、constructor_macros.hpp

这个文件中定义的宏都是和C++编译器提供的默认函数相关的,这样做的目的有助于代码简洁,所有类的构造函数都适用。这个是可以复用的,自己的库也可以设计成这样的。代码如下:

#ifndef UTILS_CONSTRUCTOR_MACROS_HPP_
#define UTILS_CONSTRUCTOR_MACROS_HPP_

#ifndef FASTDDS_COPY_OPERATIONS
#define FASTDDS_COPY_OPERATIONS(ClassName, access) \
    ClassName(const ClassName&) = access; \
    ClassName& operator = (const ClassName&) = access
#endif // !FASTDDS_COPY_OPERATIONS

#ifndef FASTDDS_MOVE_OPERATIONS
#define FASTDDS_MOVE_OPERATIONS(ClassName, access) \
    ClassName(ClassName &&) = access; \
    ClassName& operator = (ClassName &&) = access
#endif // !FASTDDS_COPY_OPERATIONS

#ifndef FASTDDS_DEFAULT_COPY
#define FASTDDS_DEFAULT_COPY(ClassName) FASTDDS_COPY_OPERATIONS(ClassName, default)
#endif // !FASTDDS_DEFAULT_COPY

#ifndef FASTDDS_DELETED_COPY
#define FASTDDS_DELETED_COPY(ClassName) FASTDDS_COPY_OPERATIONS(ClassName, delete)
#endif // !FASTDDS_DELETED_COPY

#ifndef FASTDDS_DEFAULT_MOVE
#define FASTDDS_DEFAULT_MOVE(ClassName) FASTDDS_MOVE_OPERATIONS(ClassName, default)
#endif // !FASTDDS_DEFAULT_COPY

#ifndef FASTDDS_DELETED_MOVE
#define FASTDDS_DELETED_MOVE(ClassName) FASTDDS_MOVE_OPERATIONS(ClassName, delete)
#endif // !FASTDDS_DELETED_COPY

2、DBQueue双缓存队列

这个类是一个双缓存队列,生产者线程将生产的数据放到mForegroundQueue队列,消费者线程从mBackgroundQueue队列取数据。当mBackgroundQueue队列的数据空时,就会交换两个队列。核心代码如下:

//! Clears foreground queue and swaps queues.
// 这个函数一般在前缓冲区队列为空时调用,消费者没有数据可以继续消费了
void Swap()
{
    std::unique_lock<std::mutex> fgGuard(mForegroundMutex);
    std::unique_lock<std::mutex> bgGuard(mBackgroundMutex);

    // Clear the foreground queue.
    std::queue<T>().swap(*mForegroundQueue);

    auto* swap       = mBackgroundQueue;
    mBackgroundQueue = mForegroundQueue;
    mForegroundQueue = swap;
}

//! Pushes to the background queue. Copy constructor.
// 生产者将数据放入后缓冲区队列
void Push(
        const T& item)
{
    std::unique_lock<std::mutex> guard(mBackgroundMutex);
    mBackgroundQueue->push(item);
}

//! Pushes to the background queue. Move constructor.
void Push(
        T&& item)
{
    std::unique_lock<std::mutex> guard(mBackgroundMutex);
    mBackgroundQueue->push(std::move(item));
}

//! Returns a reference to the front element
//! in the foregrund queue.
// 消费者从前缓冲区队列取数据
T& Front()
{
    std::unique_lock<std::mutex> guard(mForegroundMutex);
    return mForegroundQueue->front();
}

3、IPFinder查找IP工具类

其实这个类的主要作用是提供接口,利用系统函数获取机器的ip地址和mac地址,然后再通过一些列的转换,将获取到的数据转化为DDS中存储ip的数据结构中。下面代码可以表示该类的核心作用,返回的数据结构是LocatorList_t*,getIPs函数中会一层一层的调用系统函数。

bool IPFinder::getAllIPAddress(
        LocatorList_t* locators)
{
    std::vector<info_IP> ip_names;
    if (IPFinder::getIPs(&ip_names))
    {
        locators->clear();
        for (auto it = ip_names.begin();
                it != ip_names.end(); ++it)
        {
            if (it->type == IP6)
            {
                locators->push_back(it->locator);
            }
            else if (it->type == IP4)
            {
                locators->push_back(it->locator);
            }
        }
        return true;
    }
    return false;
}

4、Host主机类和Semaphore类

Host主机类会获取两个id,一个是mac地址(48个字节),另一个是机器的ip地址(16个字节),FastDDS中是用这两个id唯一标识一台机器的。
Semaphore类是FastDDS自定义的信号量,代码并不难,但是有一个值得学习的点,那就是成员变量中的disable_。disable_ 变量用于控制信号量是否处于禁用状态,其主要作用是在某些情况下避免线程阻塞,比如:

  • 用于确保 Semaphore 在被销毁时不会造成死锁,在析构 Semaphore 之前,可以将 disable_ 设为 true,然后通知所有等待中的线程,以防止它们进入等待状态,导致程序死锁。
  • 避免在不安全的状态下调用 wait(),disable_ 可能会在某些异常情况下被设为 true,这样当 wait() 被调用时,可以直接返回,而不会让线程进入阻塞等待。
    代码如下:
class Semaphore
{
public:

    explicit Semaphore(
            size_t count = 0);
    Semaphore(
            const Semaphore&) = delete;
    Semaphore& operator =(
            const Semaphore&) = delete;

    void post();
    void wait();
    void disable();
    void enable();
    void post(
            int n);

private:

    size_t count_;
    std::mutex mutex_;
    std::condition_variable cv_;
    bool disable_;
};

5、SystemInfo系统信息类

这个类中主要是封装了一些获取系统信息的一些方法。比如获取进程id、主机ip、获取某个环境变量的值、获取当前进程属于哪个用户、文件是否存在、设置环境变量等方法。需要注意的是,在获取环境变量时,一般是先从配置文件中获取,当配置文件中找不到时,从环境变量中获取。该类中还提供这样一个接口,支持注册一些回调函数,这些回掉函数在监听的文件发生变化时调用,也支持取消监听文件的变化。

FileWatchHandle SystemInfo::watch_file(
        std::string filename,
        std::function<void()> callback,
        const fastdds::rtps::ThreadSettings& watch_thread_config,
        const fastdds::rtps::ThreadSettings& callback_thread_config)
{
#if defined(_WIN32) || defined(__unix__)
    // 次函数的实现是依赖于第3方库的。
    return FileWatchHandle (new filewatch::FileWatch<std::string>(filename,
                   [callback](const std::string& /*path*/, const filewatch::Event change_type)
                   {
                       switch (change_type)
                       {
                           case filewatch::Event::modified:
                               callback();
                               break;
                           default:
                               // No-op
                               break;
                       }
                   }, watch_thread_config, callback_thread_config));
#else // defined(_WIN32) || defined(__unix__)
    static_cast<void>(filename);
    static_cast<void>(callback);
    static_cast<void>(watch_thread_config);
    static_cast<void>(callback_thread_config);
    return FileWatchHandle();
#endif // defined(_WIN32) || defined(__unix__)
}
void SystemInfo::stop_watching_file(
        FileWatchHandle& handle)
{
#if defined(_WIN32) || defined(__unix__)
    handle.reset();
#endif // if defined(_WIN32) || defined(__unix__)
    static_cast<void>(handle);
}

6、time_t_helpers.hpp和TimeConversion.hpp

后面这个文件定义了一系列的时间转换函数,前面这个文件中主要定义了3个函数,都是用作时间转换,主要针对分数时间和计算unix时间。什么是分数时间、unix时间、utc时间、GPS时间呢?

  • 分数时间(Fractional Time):常用于高精度时间计算,特别是在 FastDDS、RTPS、NTP 等协议中。它将时间表示为秒的整数部分 + 小数部分,其中小数部分通常用 32 位无符号整数存储,表示秒的小数部分。例如,fraction = 0x80000000 对应 0.5 秒。这种表示方式能够提供纳秒级的时间精度。
  • UTC时间(Coordinated Universal Time,协调世界时):UTC 是当前全球使用的标准时间,基于 国际原子时(TAI),但会加入 闰秒 以保持与地球自转(UT1)同步。例如,2024 年 UTC = TAI - 37 秒,而未来如果有新的闰秒调整,这个差值可能会变化。UTC 被广泛应用于全球通信、金融、互联网等领域。
  • Unix时间(Unix Time / Epoch Time):Unix 时间是从 1970 年 1 月 1 日 00:00:00 UTC 开始计算的秒数(不包括闰秒)。例如,2025 年 1 月 1 日 00:00:00 UTC 的 Unix 时间戳是 1735689600。由于 Unix 时间不考虑闰秒,因此它与 UTC 在某些精确应用中可能存在偏差。
  • GPS时间(GPS Time):GPS 时间起始于 1980 年 1 月 6 日 00:00:00 UTC,并且不会受闰秒影响。它的计算方式为 GPS 时间 = TAI - 19 秒(固定值)。相比 UTC,GPS 时间更稳定,非常适用于高精度定位和授时系统。

http://www.kler.cn/a/582379.html

相关文章:

  • 【TMS570LC4357】之工程创建
  • UE5.5 Niagara 发射器粒子更新模块
  • 基于SpringBoot的租房管理系统实现与设计
  • 用C# Newtonsoft.Json库实现JSON数据中某个字段值的提取
  • LLM最新的模型微调技术有哪些
  • 爬虫一些基础知识的备忘录(需要自取)
  • 【Academy】SSRF ------ Server-side request forgery
  • 2025年是Matter智能家居至关重要的一年?
  • NetAssist 5.0.14网络助手基础使用及自动应答使用方案
  • 鸿蒙 Java 人工智能 嵌入式 测试运维简单分析
  • Android Retrofit 框架适配器模块深入源码分析(五)
  • windows版本的时序数据库TDengine安装以及可视化工具
  • 元宇宙:虚实融合中的消费新空间探析
  • 2025解决软件供应链安全,开源安全的版本答案:SCA+SBOM
  • Docker:容器化技术实战指南
  • 谈谈Error和Exception的区别
  • 【性能测试入门_01性能测试jmeter基础实操场景详解】
  • Linux中的基本指令(上)
  • Flutter 基础组件 Image 详解
  • 【抽奖项目】|第二篇