XNSim/XNCore_Win/XNThreadManager/XNThreadManager.cpp

237 lines
6.5 KiB
C++
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 "XNFramework/XNFramework.h"
#include "XNModelManager/XNModelManager.h"
#include "XNThreadManager_p.h"
#include "XNThreadObject/XNThreadObject.h"
#include "XNTimeManager/XNTimeManager.h"
namespace XNSim {
// 默认构造函数
XNThreadManager::XNThreadManager()
: XNBaseFrameObject(new XNThreadManagerPrivate()) {
SetUniqueId(enumValue(XNCoreObjectID::ThreadManager));
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(XN_UINT32 id, XNCallBack fun,
XN_UINT32 threadID, XN_UINT32 freqGroup,
XN_UINT32 RunPos, XN_UINT32 RunPriorty) {
T_D();
// 如果周期性函数校验通过
if (IsFunParamRight(id, freqGroup, RunPos)) {
// 存储提交的函数
XNFunInfoPtr sFunInfo = std::make_shared<XNFunInfo>();
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);
}
}
}
// 注册函数校验
XN_BOOL XNThreadManager::IsFunParamRight(XN_UINT32 id, XN_UINT32 freqGroup,
XN_UINT32 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;
}
// 仿真运行前做最后处理
XN_BOOL XNThreadManager::PrepareForExecute() {
T_D();
PERIOD_INFO pinfo;
getCurrentRTTime(&(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) {
XN_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;
}
// 添加线程
XN_UINT32 XNThreadManager::AddThreadPool(XN_STRING name, XN_DOUBLE freq,
XN_UINT32 priority, XN_UINT32 CPUAff) {
T_D();
// 创建线程对象
XNThreadObjectPtr thread =
std::make_shared<XNThreadObject>(name, freq, priority, CPUAff);
thread->SetThreadID(AllocateThreadID());
thread->SetFramework(GetFramework());
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(XN_UINT32 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);
}
}
// 获取线程数量
XN_UINT32 XNThreadManager::GetThreadCount() {
T_D();
return d->_threadList.size();
}
// 分配线程ID
XN_UINT32 XNThreadManager::AllocateThreadID() {
T_D();
// 从5000到9999分配线程ID
static XN_UINT32 threadID = 5000;
while (d->_threadList.find(threadID) != d->_threadList.end()) {
threadID++;
}
d->_threadList[threadID] = nullptr;
return threadID;
}
void XNThreadManager::SetThreadFreqByID(XN_UINT32 threadID, XN_DOUBLE freq) {
T_D();
d->_threadList[threadID]->SetRunFrequecy(freq);
}
XN_DOUBLE XNThreadManager::GetThreadFreqByID(XN_UINT32 threadID) {
T_D();
return d->_threadList[threadID]->GetRunFrequecy();
}
} // namespace XNSim