XNSim/XNCore/XNThreadManager.cpp

256 lines
6.5 KiB
C++
Raw Normal View History

2025-04-28 12:25:20 +08:00
/**
* @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<XNThread *>();
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) {
// 如果频率分组不是05
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<XNThread *>();
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;
}