XNSim/XNCore/XNThreadManager.cpp

228 lines
5.5 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("XNThreadManager Initialize Success!");
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("Model [ %1] register periodic function success! Run node: %2-%3 Priority: %4",
id, freqGroup, RunPos, RunPriorty);
} else {
LOG_ERROR("0x2172 The thread [ %1 ] does not exist, registration failed!", threadID);
}
}
}
// 注册函数校验
bool XNThreadManager::IsFunParamRight(uint32_t id, uint32_t freqGroup, uint32_t RunPos)
{
// 检查提交的函数是否符合规定
if (freqGroup < 0 || freqGroup > 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 > (1 << 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;
}
// 仿真运行前做最后处理
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("XNThreadManager is preparing...");
for (auto &thread : d->threadList) {
bool bRet = thread.second->Initialize();
if (!bRet) {
LOG_ERROR("Thread [ %1 ] PrepareForExecute Failed!", thread.first);
continue;
}
}
d->_status = XNFrameObjectStatus::Ready;
LOG_INFO("XNThreadManager is prepared!");
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());
LOG_INFO("Add Thread Success, Frequency: %1 Hz, Interval: %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;
}