XNSim/XNCore/XNThreadManager.cpp

238 lines
5.8 KiB
C++
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* @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 "XNTimeManager.h"
#include "XNModelManager.h"
// 默认构造函数
XNThreadManager::XNThreadManager() : XNBaseFrameObject(new XNThreadManagerPrivate())
{
SetUniqueId(3);
SetObjectName("XNThreadManager");
}
XNThreadManager::~XNThreadManager()
{
}
XNThreadManager::XNThreadManager(PrivateType *p) : XNBaseFrameObject(p)
{
}
// 初始化函数
bool XNThreadManager::Initialize()
{
T_D();
d->_eRunStatus = RunStatus::NotStart;
d->threadList.clear();
d->funList.clear();
LOG_INFO("D01074001:线程管理器初始化成功!");
d->_status = XNFrameObjectStatus::Initialized;
return true;
}
// 开始控制
void XNThreadManager::Start()
{
T_D();
// 如果当前状态是未开始状态
if (d->_eRunStatus == RunStatus::NotStart) {
// 状态切换为正在运行
d->_eRunStatus = RunStatus::Runing;
}
}
// 停止控制
void XNThreadManager::Abort()
{
T_D();
// 如果当前状态不是停止状态
if (d->_eRunStatus != RunStatus::Aborted) {
// 状态切换为停止
d->_eRunStatus = RunStatus::Aborted;
}
}
// 暂停控制
void XNThreadManager::Pause()
{
T_D();
// 如果当前是正在运行状态
if (d->_eRunStatus == RunStatus::Runing) {
// 状态切换为暂停
d->_eRunStatus = RunStatus::Suspend;
}
}
// 继续控制
void XNThreadManager::Continue()
{
T_D();
// 如果当前是暂停状态
if (d->_eRunStatus == RunStatus::Suspend) {
//TODO 这里需要重新设置一下时间信息,不然启动后会加速运行至设定的时间
// 状态切换为正在运行
d->_eRunStatus = RunStatus::Runing;
}
}
// 获取当前运行状态
RunStatus XNThreadManager::GetStatus()
{
T_D();
return d->_eRunStatus;
}
// 添加周期性函数
void XNThreadManager::RegisterFunction(uint32_t id, XNCallBack fun, uint32_t threadID,
uint32_t freqGroup, uint32_t RunPos, uint32_t RunPriorty)
{
T_D();
// 如果周期性函数校验通过
if (IsFunParamRight(id, freqGroup, RunPos)) {
// 存储提交的函数
funInfoPtr sFunInfo = std::make_shared<funInfo>();
sFunInfo->fun = fun;
sFunInfo->threadID = threadID;
sFunInfo->freqGroup = freqGroup;
sFunInfo->RunPos = RunPos;
sFunInfo->RunPriority = RunPriorty;
d->funList[id].push_back(sFunInfo);
if (d->threadList.find(threadID) != d->threadList.end()) {
d->threadList[threadID]->AddFunction(fun, (FreqLevel)freqGroup, RunPos, RunPriorty);
LOG_INFO("D01074005:模型 [ %1 ] 注册周期性函数成功! 运行节点: %2-%3 优先级: %4", id,
freqGroup, RunPos, RunPriorty);
} else {
LOG_ERROR("B01072008:线程 [ %1 ] 不存在,模型 [ %2 ] 注册周期性函数失败!", threadID, id);
}
}
}
// 注册函数校验
bool XNThreadManager::IsFunParamRight(uint32_t id, uint32_t freqGroup, uint32_t RunPos)
{
// 检查提交的函数是否符合规定
if (freqGroup < 0 || freqGroup > 5) {
// 如果频率分组不是05
LOG_WARNING("A01073006:模型 [ %1 ] 的运行频率分组不在0~5之间,注册失败!", id);
return false;
} else if (RunPos > (1 << freqGroup)) {
// 如果运行节点不符合要求
LOG_WARNING("A01073007:模型 [ %1 ] 的运行节点 %2 超出当前频率分组最大节点数 %3,注册失败!",
id, RunPos, (1 << freqGroup));
return false;
}
return true;
}
// 仿真运行前做最后处理
bool XNThreadManager::PrepareForExecute()
{
T_D();
PERIOD_INFO pinfo;
clock_gettime(CLOCK_MONOTONIC, &(pinfo.next_period));
for (auto &thread : d->threadList) {
thread.second->SetStartTime(pinfo.next_period);
}
//设置开始事件
auto framework = GetFramework();
if (framework) {
auto timeManager = framework->GetTimeManager();
if (timeManager) {
timeManager->SetStartTime(pinfo.next_period);
}
}
// 所有线程初始化
LOG_INFO("D01074002:线程管理器正在初始化所有线程...");
for (auto &thread : d->threadList) {
bool bRet = thread.second->Initialize();
if (!bRet) {
LOG_ERROR("B01072009:线程 [ %1 ] 初始化失败!", thread.first);
continue;
}
}
d->_status = XNFrameObjectStatus::Ready;
LOG_INFO("D01074003:线程管理器准备就绪!");
return true;
}
// 添加线程
uint32_t XNThreadManager::AddThreadPool(std::string name, double freq, uint32_t priority,
uint32_t CPUAff)
{
T_D();
// 创建线程对象
XNThreadPtr thread = std::make_shared<XNThread>(name, freq, priority, CPUAff);
thread->SetThreadID(AllocateThreadID());
thread->SetFramework(GetFramework());
LOG_INFO("D01074004:添加线程成功,运行频率: %1 Hz,运行间隔: %2 ns.", freq, 1.0e9 / freq);
d->threadList[thread->GetThreadID()] = thread;
return thread->GetThreadID();
}
void XNThreadManager::SimControl(uint32_t objectId, SimControlCmd cmd)
{
T_D();
if (objectId == 0) {
switch (cmd) {
case SimControlCmd::Start:
Start();
break;
case SimControlCmd::Abort:
Abort();
break;
case SimControlCmd::Continue:
Continue();
break;
case SimControlCmd::Suspend:
Pause();
break;
}
}
for (auto &thread : d->threadList) {
thread.second->SimControl(objectId, cmd);
}
}
// 获取线程数量
uint32_t XNThreadManager::GetThreadCount()
{
T_D();
return d->threadList.size();
}
// 分配线程ID
uint32_t XNThreadManager::AllocateThreadID()
{
T_D();
//从5000到9999分配线程ID
static uint32_t threadID = 5000;
while (d->threadList.find(threadID) != d->threadList.end()) {
threadID++;
}
d->threadList[threadID] = nullptr;
return threadID;
}
void XNThreadManager::SetThreadFreqByID(uint32_t threadID, double freq)
{
T_D();
d->threadList[threadID]->SetRunFrequecy(freq);
}
double XNThreadManager::GetThreadFreqByID(uint32_t threadID)
{
T_D();
return d->threadList[threadID]->GetRunFrequecy();
}