/** * @file XNThreadManager.h * @author jinchao * @brief 线程管理器类头文件 * @version 1.0 * @date 2024-11-06 * * @copyright Copyright (c) 2024 XN * */ #pragma once #include "XNBaseFrameObject.h" class XNThreadManagerPrivate; /** * @brief 线程管理器类 * @details 主要负责创建、管理与控制模型调度线程,并向调度线程中添加需要调度执行的模型周期性函数 */ class XNThreadManager : public XNBaseFrameObject { Q_OBJECT Q_DECLARE_PRIVATE(XNThreadManager) Q_DISABLE_COPY(XNThreadManager) public: /** * @brief 线程管理器类默认构造函数 */ explicit XNThreadManager(QObject *parent = nullptr); /** * @brief 线程管理器类析构函数 */ virtual ~XNThreadManager(); protected: /** * @brief 线程管理器类带参构造函数 * @param dd:XNThreadManagerPrivate类型,私有结构体指针 * @param parent:QObject类型,父对象指针 * @details 子类构造时调用此构造函数,传入子类的私有结构体指针 */ XNThreadManager(XNThreadManagerPrivate &dd, QObject *parent = nullptr); signals: /** * @brief 设置仿真开始时间信号 * @param simTime: timespec结构体类型,用于线程纳秒睡眠计算的开始时间 * @details 通过设置统一的开始时间,使个线程能同步执行 */ void SetStartTime(const timespec &simTime); /** * @brief 设置线程运行间隔信号 * @param dRunInter: double类型,线程运行间隔,单位纳秒 */ void SetRunInter(const double &dRunInter); /** * @brief 仿真控制信号 * @param objectId: 对象ID * @param cmd: 仿真控制命令 */ void SimControl(quint32 objectId, SimControlCmd cmd); public slots: /** * @brief 开始控制 * @details 控制线程管理器开始运行接口 */ void OnStart(); /** * @brief 停止控制 * @details 控制线程管理器停止运行接口 */ void OnAbort(); /** * @brief 暂停控制 * @details 控制线程管理器暂停运行接口 */ void OnPause(); /** * @brief 继续控制 * @details 控制线程管理器继续运行接口 */ void OnContinue(); /** * @brief 初始化线程管理器 * @return true: 初始化成功 * @return false: 初始化失败 * @details 线程管理器的初始化接口函数 */ virtual void OnInitialize() override; /** * @brief 仿真运行前最后处理 * @note 线程管理器在所有线程开始执行前的准备工作 */ virtual void OnPrepareForExecute() override; /** * @brief 仿真控制 * @param objectId: 对象ID * @param cmd: 仿真控制命令 */ void OnSimControl(quint32 objectId, SimControlCmd cmd); /** * @brief 设置仿真系统运行基频 * @param dBaseFreq: double类型,频率值,单位Hz * @details 仿真系统所有线程以此基频的 1 或 1/2 或 1/4 或 1/8 或 1/16 或 1/32 倍运行 */ void OnSetBaseFreq(const double &dBaseFreq); public: /** * @brief 获取运行状态 * @return RunStatus: 枚举类,线程运行状态 * @details 获取线程管理器运行状态接口 */ RunStatus GetStatus(); /** * @brief 获得仿真系统运行基频 * @return const double&: 频率值,单位Hz */ const double &GetBaseFreq(); /** * @brief 获得仿真系统运行基础间隔 * @return const double&: 运行周期值,单位纳秒 * @details 模型基础运行间隔由基频计算获得 */ const double &GetBaseInter(); /** * @brief 通过运行间隔设置基频 * @param dBaseInter:double类型,运行周期值,单位纳秒 * @details 使用运行间隔计算得到基频并设置 */ void SetBaseFreqByInter(const double &dBaseInter); /** * @brief 获取线程数量 * @return quint32: 线程数量 */ quint32 GetThreadCount(); public slots: /** * @brief 添加一个线程 * @param name: XNString类型,线程名称 * @param freq: FreqLevel枚举类型,线程运行频率组 * @param priority: UINT32类型,线程运行优先级,99~0,优先级数值越大,优先级越高 * @param CPUAff: UINT32类型,线程的CPU亲和性掩码,按位表示某CPU核是否使用,从低到高,0表示不使用,1表示使用。 * 例如:0x00000003表示使用0,1号CPU * @param RunInter: double类型,线程的运行周期,单位纳秒 * @details 按照设置的参数创建线程 */ virtual void OnAddThreadPool(QString name, FreqLevel freq, quint32 priority, quint32 CPUAff, double RunInter); /** * @brief 向线程中添加周期性函数 * @param id: UINT32类型,模型全局唯一ID * @param fun: XNCallBack函数包装器类型,需要提交的函数的包装 * @param freqGroup: UINT32类型,提交的函数运行频率组,0为基频,1为半频,2为1/4频,3为1/8频,4为1/16频,5为1/32频 * @param RunPos: UINT32类型,提交的函数运行节点号,<2^(freqGroup) * @param RunPriorty: UINT32类型,提交的函数运行优先级,99~0,优先级数值越大,优先级越高 * @return true: 添加成功 * @return false: 添加失败 * @details 根据运行频率组和节点号向对应的线程中添加周期性函数 */ void OnRegisterFunction(quint32 id, XNCallBack fun, quint32 freqGroup, quint32 RunPos, quint32 RunPriorty); private: /** * @brief 注册函数校验 * @param freqGroup: UINT32类型,提交的函数运行频率组,0为基频,1为半频,2为1/4频,3为1/8频,4为1/16频,5为1/32频 * @param RunPos: UINT32类型,提交的函数运行节点号,<2^(freqGroup) * @return true:提交的函数频率与节点号符合规则 * @return false:提交的函数频率与节点号不符合规则 */ bool IsFunParamRight(quint32 ModelID, quint32 freqGroup, quint32 RunPos); quint32 AllocateThreadID(); };