/** * @file XNThreadManager.cpp * @author jinchao * @brief 线程管理器类源文件 * @version 1.0 * @date 2024-11-07 * * @copyright Copyright (c) 2024 XN * */ #include "XNThreadManager.h" #include "XNThreadManager_p.h" #include "XNFramework.h" #include "XNModelManager.h" // 默认构造函数 XNThreadManager::XNThreadManager(QObject *parent) : XNBaseFrameObject(*new XNThreadManagerPrivate(this), parent) { setUniqueId(3); setObjectName("XNThreadManager"); } XNThreadManager::~XNThreadManager() { } XNThreadManager::XNThreadManager(XNThreadManagerPrivate &dd, QObject *parent) : XNBaseFrameObject(dd, parent) { } // 初始化函数 void XNThreadManager::OnInitialize() { Q_D(XNThreadManager); d->_eRunStatus = RunStatus::NotStart; LOG_INFO("XNThreadManager Initialize Success!"); d->_status = XNFrameObjectStatus::Initialized; emit Initialize(); } // 开始控制 void XNThreadManager::OnStart() { Q_D(XNThreadManager); // 如果当前状态是未开始状态 if (d->_eRunStatus == RunStatus::NotStart) { // 状态切换为正在运行 d->_eRunStatus = RunStatus::Runing; } } // 停止控制 void XNThreadManager::OnAbort() { Q_D(XNThreadManager); // 如果当前状态不是停止状态 if (d->_eRunStatus != RunStatus::Aborted) { // 状态切换为停止 d->_eRunStatus = RunStatus::Aborted; } } // 暂停控制 void XNThreadManager::OnPause() { Q_D(XNThreadManager); // 如果当前是正在运行状态 if (d->_eRunStatus == RunStatus::Runing) { // 状态切换为暂停 d->_eRunStatus = RunStatus::Suspend; } } // 继续控制 void XNThreadManager::OnContinue() { Q_D(XNThreadManager); // 如果当前是暂停状态 if (d->_eRunStatus == RunStatus::Suspend) { //TODO 这里需要重新设置一下时间信息,不然启动后会加速运行至设定的时间 // 状态切换为正在运行 d->_eRunStatus = RunStatus::Runing; } } // 获取当前运行状态 RunStatus XNThreadManager::GetStatus() { Q_D(XNThreadManager); return d->_eRunStatus; } // 添加周期性函数 void XNThreadManager::OnRegisterFunction(quint32 id, XNCallBack fun, quint32 freqGroup, quint32 RunPos, quint32 RunPriorty) { Q_D(XNThreadManager); // 如果周期性函数校验通过 if (IsFunParamRight(id, freqGroup, RunPos)) { // 存储提交的函数 funInfoPtr sFunInfo = funInfoPtr::create(); sFunInfo->fun = fun; sFunInfo->freqGroup = freqGroup; sFunInfo->RunPos = RunPos; sFunInfo->RunPriority = RunPriorty; d->funList[id].push_back(sFunInfo); // 加入线程任务池 auto threadPool = this->findChildren(); for (auto thread : threadPool) { if ((quint32)thread->GetRunFrequecy() == freqGroup) { thread->AddFunction(fun, (FreqLevel)freqGroup, RunPos, RunPriorty); break; } } LOG_INFO("Model [ %1] register periodic function success! Run node: %2-%3 Priority: %4", id, freqGroup, RunPos, RunPriorty); } } // 注册函数校验 bool XNThreadManager::IsFunParamRight(quint32 id, quint32 freqGroup, quint32 RunPos) { quint32 ufreq = freqGroup; // 检查提交的函数是否符合规定 if (ufreq < 0 || ufreq > 5) { // 如果频率分组不是0~5 LOG_WARNING("0x2170 The submitted function's run frequency group of Model [ %1 ] is not " "between 0 and 5, registration failed!", id); return false; } else if (RunPos > pow(2, freqGroup)) { // 如果运行节点不符合要求 LOG_WARNING("0x2171 The run node submitted for registration by model [ %1 ] exceeds the " "maximum node count for the frequency group, registration failed!", id); return false; } return true; } // 仿真运行前做最后处理 void XNThreadManager::OnPrepareForExecute() { Q_D(XNThreadManager); PERIOD_INFO pinfo; clock_gettime(CLOCK_MONOTONIC, &(pinfo.next_period)); emit SetStartTime(pinfo.next_period); // 所有线程初始化 LOG_INFO("XNThreadManager is preparing..."); auto threadPool = this->findChildren(); for (auto &thread : threadPool) { bool bRet = thread->Initialize(); if (!bRet) { emit PrepareForExecuteFailed(); return; } } d->_status = XNFrameObjectStatus::Ready; // 通知模型管理器进行最后准备 LOG_INFO("XNThreadManager is prepared!"); emit PrepareForExecute(); } // 添加线程 void XNThreadManager::OnAddThreadPool(QString name, FreqLevel freq, quint32 priority, quint32 CPUAff, double RunInter) { Q_D(XNThreadManager); // 创建线程对象 XNThread *thread = new XNThread(this, name, freq, priority, CPUAff, RunInter); // 连接信号和槽 //connect(this, &XNThreadManager::SetRunInter, thread, &XNThread::SetRunInter); connect(this, &XNThreadManager::SetStartTime, thread, &XNThread::OnSetStartTime); connect(this, &XNThreadManager::SimControl, thread, &XNThread::OnSimControl); thread->SetThreadID(AllocateThreadID()); LOG_INFO("Add Thread Success, Frequency: %1 Hz, Interval: %2 ns.", d->dRunFreq / pow(2, (quint32)freq), RunInter); d->threadCount++; } void XNThreadManager::OnSimControl(quint32 objectId, SimControlCmd cmd) { if (objectId == 0) { switch (cmd) { case SimControlCmd::Start: OnStart(); break; case SimControlCmd::Abort: OnAbort(); break; case SimControlCmd::Continue: OnContinue(); break; case SimControlCmd::Suspend: OnPause(); break; } } emit SimControl(objectId, cmd); } // 设置模型运行基频 void XNThreadManager::OnSetBaseFreq(const double &dBaseFreq) { Q_D(XNThreadManager); d->dRunFreq = dBaseFreq; d->dRunInter = 1.0e9 / dBaseFreq; //emit SetRunInter(d->dRunInter); LOG_INFO("Set engine base run frequency to %1 Hz, interval: %2 ns.", d->dRunFreq, d->dRunInter); } // 获得模型运行基频 const double &XNThreadManager::GetBaseFreq() { Q_D(XNThreadManager); return d->dRunFreq; } // 获得模型运行基础间隔 const double &XNThreadManager::GetBaseInter() { Q_D(XNThreadManager); return d->dRunInter; } // 通过运行间隔设置基频 void XNThreadManager::SetBaseFreqByInter(const double &dBaseInter) { Q_D(XNThreadManager); d->dRunFreq = 1.0e9 / dBaseInter; d->dRunInter = dBaseInter; LOG_INFO("Set engine base run frequency to %1 Hz, interval: %2 ns.", d->dRunFreq, d->dRunInter); } // 获取线程数量 quint32 XNThreadManager::GetThreadCount() { Q_D(XNThreadManager); return d->threadCount; } // 分配线程ID quint32 XNThreadManager::AllocateThreadID() { Q_D(XNThreadManager); //从5000到9999分配线程ID static quint32 threadID = 5000; while (d->threadIDMap.contains(threadID)) { threadID++; } d->threadIDMap.insert(threadID); return threadID; }