先上传一下抽象层代码
This commit is contained in:
parent
66b91c7aba
commit
033951ef60
149
XNCore_Win/CMakeLists.txt
Normal file
149
XNCore_Win/CMakeLists.txt
Normal file
@ -0,0 +1,149 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
project(XNCore LANGUAGES CXX)
|
||||
|
||||
# 第三方库路径(需要根据实际情况修改)
|
||||
set(THIRD_PARTY_DIR "I:/MyPrj/XNSim/ThirdPart")
|
||||
|
||||
# Windows平台设置32位编译
|
||||
if(WIN32)
|
||||
set(CMAKE_GENERATOR_PLATFORM "Win32" CACHE STRING "Target platform" FORCE)
|
||||
set(CMAKE_VS_PLATFORM_NAME "Win32" CACHE STRING "Win32/x64 build." FORCE)
|
||||
set_property(GLOBAL PROPERTY FIND_LIBRARY_USE_LIB32_PATHS TRUE)
|
||||
set_property(GLOBAL PROPERTY FIND_LIBRARY_USE_LIB64_PATHS FALSE)
|
||||
|
||||
set(CMAKE_SIZEOF_VOID_P 4)
|
||||
|
||||
add_definitions(-DWIN32 -D_WINDOWS)
|
||||
|
||||
|
||||
endif()
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
if(WIN32)
|
||||
# 设置OpenSSL路径(使用缓存变量)
|
||||
set(OPENSSL_ROOT_DIR "${THIRD_PARTY_DIR}/openssl" CACHE PATH "OpenSSL root directory")
|
||||
set(OPENSSL_INCLUDE_DIR "${OPENSSL_ROOT_DIR}/include" CACHE PATH "OpenSSL include directory")
|
||||
set(OPENSSL_LIBRARIES "${OPENSSL_ROOT_DIR}/lib" CACHE PATH "OpenSSL library directory")
|
||||
set(OPENSSL_CRYPTO_LIBRARY "${OPENSSL_ROOT_DIR}/lib/libcrypto.lib" CACHE FILEPATH "OpenSSL crypto library")
|
||||
set(OPENSSL_SSL_LIBRARY "${OPENSSL_ROOT_DIR}/lib/libssl.lib" CACHE FILEPATH "OpenSSL ssl library")
|
||||
|
||||
# 验证OpenSSL目录
|
||||
if(NOT EXISTS "${OPENSSL_INCLUDE_DIR}/openssl/ssl.h")
|
||||
message(FATAL_ERROR "OpenSSL headers not found in ${OPENSSL_INCLUDE_DIR}")
|
||||
endif()
|
||||
|
||||
# 设置SQLite3路径
|
||||
set(SQLITE3_ROOT_DIR "${THIRD_PARTY_DIR}/sqlite3/")
|
||||
set(SQLITE3_INCLUDE_DIR "${SQLITE3_ROOT_DIR}/include")
|
||||
set(SQLITE3_LIBRARIE "${SQLITE3_ROOT_DIR}/lib/sqlite3.lib")
|
||||
|
||||
# 设置tinyxml2路径
|
||||
set(TINYXML2_INCLUDE_DIR "${THIRD_PARTY_DIR}/tinyxml2-6.0.0/")
|
||||
file(GLOB TINYXML2_SOURCES "${THIRD_PARTY_DIR}/tinyxml2-6.0.0/*.cpp")
|
||||
else()
|
||||
find_package(nlohmann_json REQUIRED)
|
||||
find_package(Threads REQUIRED)
|
||||
find_package(SQLite3 REQUIRED)
|
||||
endif()
|
||||
|
||||
find_package(OpenSSL REQUIRED)
|
||||
if(NOT fastcdr_FOUND)
|
||||
find_package(fastcdr 2 REQUIRED)
|
||||
endif()
|
||||
if(NOT fastdds_FOUND)
|
||||
find_package(fastdds 3 REQUIRED)
|
||||
endif()
|
||||
|
||||
set(XNCORE_SOURCES "")
|
||||
|
||||
add_subdirectory(XNBaseFrameObject)
|
||||
add_subdirectory(XNDDSInterface)
|
||||
add_subdirectory(XNDDSManager)
|
||||
add_subdirectory(XNEventManager)
|
||||
add_subdirectory(XNFramework)
|
||||
add_subdirectory(XNGlobalDefine)
|
||||
add_subdirectory(XNLogger)
|
||||
add_subdirectory(XNModelManager)
|
||||
add_subdirectory(XNModelObject)
|
||||
add_subdirectory(XNObject)
|
||||
add_subdirectory(XNConfigManager)
|
||||
add_subdirectory(XNServiceManager)
|
||||
add_subdirectory(XNServiceObject)
|
||||
add_subdirectory(XNThreadManager)
|
||||
add_subdirectory(XNThreadObject)
|
||||
add_subdirectory(XNTimeManager)
|
||||
add_subdirectory(XNIDL)
|
||||
|
||||
if(WIN32)
|
||||
add_library(XNCore SHARED
|
||||
${XNCORE_SOURCES}
|
||||
${XNCORE_IDL_SOURCES}
|
||||
${TINYXML2_SOURCES}
|
||||
${THIRD_PARTY_DIR}/nlohmann/json.hpp
|
||||
)
|
||||
|
||||
target_include_directories(XNCore PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${OPENSSL_INCLUDE_DIR}
|
||||
${SQLITE3_INCLUDE_DIR}
|
||||
${TINYXML2_INCLUDE_DIR}
|
||||
${THIRD_PARTY_DIR}
|
||||
)
|
||||
else()
|
||||
add_library(XNCore SHARED
|
||||
${XNCORE_SOURCES}
|
||||
${XNCORE_IDL_SOURCES}
|
||||
)
|
||||
target_include_directories(XNCore PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
)
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
target_link_libraries(XNCore PRIVATE
|
||||
${CMAKE_THREAD_LIBS_INIT}
|
||||
fastcdr
|
||||
fastdds
|
||||
OpenSSL::SSL
|
||||
OpenSSL::Crypto
|
||||
${SQLITE3_LIBRARIE}
|
||||
)
|
||||
else()
|
||||
target_link_libraries(XNCore PRIVATE
|
||||
${CMAKE_THREAD_LIBS_INIT}
|
||||
fastcdr
|
||||
fastdds
|
||||
pthread
|
||||
OpenSSL::SSL
|
||||
OpenSSL::Crypto
|
||||
nlohmann_json
|
||||
sqlite3
|
||||
tinyxml2
|
||||
dl
|
||||
)
|
||||
endif()
|
||||
|
||||
target_compile_definitions(XNCore PRIVATE XNCORE_LIBRARY)
|
||||
|
||||
# Check if CMAKE_INSTALL_PREFIX is set to its default value
|
||||
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
|
||||
set(CMAKE_INSTALL_PREFIX "${CMAKE_SOURCE_DIR}/../Release" CACHE PATH "Install path prefix" FORCE)
|
||||
endif()
|
||||
|
||||
include(GNUInstallDirs)
|
||||
install(TARGETS XNCore
|
||||
BUNDLE DESTINATION .
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION .
|
||||
)
|
||||
|
||||
# 使用 install 命令在安装时拷贝头文件
|
||||
file(GLOB_RECURSE ALL_HEADERS "*.h")
|
||||
install(FILES ${ALL_HEADERS} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/XNCore)
|
||||
|
||||
file(GLOB IDL_FILES "XNIDL/*")
|
||||
install(FILES ${IDL_FILES} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/XNIDL)
|
7
XNCore_Win/XNBaseFrameObject/CMakeLists.txt
Normal file
7
XNCore_Win/XNBaseFrameObject/CMakeLists.txt
Normal file
@ -0,0 +1,7 @@
|
||||
set(XNBASEFRAMEOBJECT_SOURCES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XNBaseFrameObject.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XNBaseFrameObject_p.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XNBaseFrameObject.cpp
|
||||
)
|
||||
|
||||
set(XNCORE_SOURCES ${XNCORE_SOURCES} ${XNBASEFRAMEOBJECT_SOURCES} PARENT_SCOPE)
|
26
XNCore_Win/XNBaseFrameObject/XNBaseFrameObject.cpp
Normal file
26
XNCore_Win/XNBaseFrameObject/XNBaseFrameObject.cpp
Normal file
@ -0,0 +1,26 @@
|
||||
#include "XNBaseFrameObject.h"
|
||||
#include "XNBaseFrameObject_p.h"
|
||||
|
||||
namespace XNSim {
|
||||
XNBaseFrameObject::XNBaseFrameObject()
|
||||
: XNObject(new XNBaseFrameObjectPrivate()) {}
|
||||
|
||||
XNBaseFrameObject::~XNBaseFrameObject() {}
|
||||
|
||||
XNBaseFrameObject::XNBaseFrameObject(PrivateType *p) : XNObject(p) {}
|
||||
|
||||
XNFrameObjectStatus XNBaseFrameObject::GetFrameObjectStatus() {
|
||||
T_D();
|
||||
return d->_status;
|
||||
}
|
||||
|
||||
XNFrameworkPtr XNBaseFrameObject::GetFramework() {
|
||||
T_D();
|
||||
return d->_framework;
|
||||
}
|
||||
|
||||
void XNBaseFrameObject::SetFramework(XNFrameworkPtr framework) {
|
||||
T_D();
|
||||
d->_framework = framework;
|
||||
}
|
||||
} // namespace XNSim
|
81
XNCore_Win/XNBaseFrameObject/XNBaseFrameObject.h
Normal file
81
XNCore_Win/XNBaseFrameObject/XNBaseFrameObject.h
Normal file
@ -0,0 +1,81 @@
|
||||
/**
|
||||
* @file XNBaseFrameObject.h
|
||||
* @author jinchao
|
||||
* @brief 框架对象基类
|
||||
* @version 1.0
|
||||
* @date 2025-01-08
|
||||
*
|
||||
* @copyright Copyright (c) 2025 COMAC
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <XNObject/XNObject.h>
|
||||
|
||||
namespace XNSim {
|
||||
struct XNBaseFrameObjectPrivate;
|
||||
|
||||
/**
|
||||
* @brief 框架对象基类
|
||||
*/
|
||||
class XNCORE_EXPORT XNBaseFrameObject : public XNObject {
|
||||
/**
|
||||
* @brief 宏定义,用于禁用拷贝构造函数
|
||||
*/
|
||||
XN_METATYPE(XNBaseFrameObject, XNObject)
|
||||
|
||||
/**
|
||||
* @brief 宏定义,用于声明私有数据成员
|
||||
*/
|
||||
XN_DECLARE_PRIVATE(XNBaseFrameObject)
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief 构造函数
|
||||
* @param parent 父对象
|
||||
*/
|
||||
XNBaseFrameObject();
|
||||
|
||||
/**
|
||||
* @brief 析构函数
|
||||
*/
|
||||
virtual ~XNBaseFrameObject();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief 构造函数
|
||||
* @param dd 私有数据成员
|
||||
* @param parent 父对象
|
||||
*/
|
||||
XNBaseFrameObject(PrivateType *p);
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief 初始化
|
||||
*/
|
||||
virtual XN_BOOL Initialize() = 0;
|
||||
|
||||
/**
|
||||
* @brief 准备执行
|
||||
*/
|
||||
virtual XN_BOOL PrepareForExecute() = 0;
|
||||
|
||||
/**
|
||||
* @brief 获取框架对象状态
|
||||
* @return 框架对象状态
|
||||
*/
|
||||
XNFrameObjectStatus GetFrameObjectStatus();
|
||||
|
||||
/**
|
||||
* @brief 获取框架对象
|
||||
* @return 框架对象
|
||||
*/
|
||||
XNFrameworkPtr GetFramework();
|
||||
|
||||
/**
|
||||
* @brief 设置框架对象
|
||||
* @param framework 框架对象
|
||||
*/
|
||||
void SetFramework(XNFrameworkPtr framework);
|
||||
};
|
||||
} // namespace XNSim
|
30
XNCore_Win/XNBaseFrameObject/XNBaseFrameObject_p.h
Normal file
30
XNCore_Win/XNBaseFrameObject/XNBaseFrameObject_p.h
Normal file
@ -0,0 +1,30 @@
|
||||
/**
|
||||
* @file XNBaseFrameObject_p.h
|
||||
* @author jinchao
|
||||
* @brief 框架对象基类的私有数据成员
|
||||
* @version 1.0
|
||||
* @date 2025-01-08
|
||||
*
|
||||
* @copyright Copyright (c) 2025 COMAC
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <XNObject/XNObject_p.h>
|
||||
|
||||
namespace XNSim {
|
||||
/**
|
||||
* @brief 框架对象基类的私有数据成员
|
||||
*/
|
||||
struct XNBaseFrameObjectPrivate : public XNObjectPrivate {
|
||||
/**
|
||||
* @brief 框架对象状态
|
||||
*/
|
||||
XNFrameObjectStatus _status = XNFrameObjectStatus::NotReady;
|
||||
/**
|
||||
* @brief 框架对象
|
||||
*/
|
||||
XNFrameworkPtr _framework;
|
||||
};
|
||||
} // namespace XNSim
|
7
XNCore_Win/XNConfigManager/CMakeLists.txt
Normal file
7
XNCore_Win/XNConfigManager/CMakeLists.txt
Normal file
@ -0,0 +1,7 @@
|
||||
set(XNCONFIGMANAGER_SOURCES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XNConfigManager.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XNConfigManager_p.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XNConfigManager.cpp
|
||||
)
|
||||
|
||||
set(XNCORE_SOURCES ${XNCORE_SOURCES} ${XNCONFIGMANAGER_SOURCES} PARENT_SCOPE)
|
408
XNCore_Win/XNConfigManager/XNConfigManager.cpp
Normal file
408
XNCore_Win/XNConfigManager/XNConfigManager.cpp
Normal file
@ -0,0 +1,408 @@
|
||||
/**
|
||||
* @file XNScenarioManager.cpp
|
||||
* @author jinchao
|
||||
* @brief 运行环境描述管理器类源文件
|
||||
* @version 1.0
|
||||
* @date 2024-11-07
|
||||
*
|
||||
* @copyright Copyright (c) 2024 XN
|
||||
*
|
||||
*/
|
||||
#include "XNScenarioManager.h"
|
||||
#include "XNScenarioManager_p.h"
|
||||
#include "XNFramework.h"
|
||||
#include "XNDDSManager.h"
|
||||
#include "XNThreadManager.h"
|
||||
#include "XNModelManager.h"
|
||||
#include "XNServiceManager.h"
|
||||
#include <fstream>
|
||||
#include <streambuf>
|
||||
#include <cerrno>
|
||||
#include <tinyxml2.h>
|
||||
|
||||
// 默认构造函数
|
||||
XNScenarioManager::XNScenarioManager() : XNBaseFrameObject(new XNScenarioManagerPrivate())
|
||||
{
|
||||
SetUniqueId(5);
|
||||
SetObjectName("XNScenarioManager");
|
||||
}
|
||||
|
||||
XNScenarioManager::~XNScenarioManager()
|
||||
{
|
||||
}
|
||||
|
||||
XNScenarioManager::XNScenarioManager(PrivateType *p) : XNBaseFrameObject(p)
|
||||
{
|
||||
}
|
||||
|
||||
// 获取运行环境名称
|
||||
const std::string &XNScenarioManager::GetSimName()
|
||||
{
|
||||
T_D();
|
||||
return d->_ScenarioName;
|
||||
}
|
||||
|
||||
// 设置运行环境名称
|
||||
void XNScenarioManager::SetSimName(const std::string &simName)
|
||||
{
|
||||
T_D();
|
||||
d->_ScenarioName = simName;
|
||||
}
|
||||
|
||||
// 初始化
|
||||
bool XNScenarioManager::Initialize()
|
||||
{
|
||||
T_D();
|
||||
LOG_INFO("XNScenarioManager Initialize Success!");
|
||||
d->_status = XNFrameObjectStatus::Initialized;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool XNScenarioManager::PrepareForExecute()
|
||||
{
|
||||
T_D();
|
||||
d->_status = XNFrameObjectStatus::Ready;
|
||||
LOG_INFO("XNScenarioManager is prepared!");
|
||||
return true;
|
||||
}
|
||||
|
||||
// 运行环境配置文件解析
|
||||
bool XNScenarioManager::AnalysisScenarioXml(const std::string &XmlPath, uint32_t initialType)
|
||||
{
|
||||
T_D();
|
||||
if (initialType == 0) {
|
||||
return ParseScenarioXml(XmlPath);
|
||||
} else {
|
||||
return ParseConfig(XmlPath);
|
||||
}
|
||||
}
|
||||
|
||||
// 解析运行环境描述文件
|
||||
bool XNScenarioManager::ParseScenarioXml(const std::string &XmlPath)
|
||||
{
|
||||
T_D();
|
||||
std::ifstream file(XmlPath);
|
||||
if (!file.is_open()) {
|
||||
LOG_ERROR("0x2100 打开运行环境描述文件: %1出错,错误信息: %2", XmlPath, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
tinyxml2::XMLDocument doc;
|
||||
if (doc.LoadFile(XmlPath.c_str()) != tinyxml2::XML_SUCCESS) {
|
||||
LOG_ERROR("0x2100 解析XML文件: %1 失败", XmlPath);
|
||||
file.close();
|
||||
return false;
|
||||
}
|
||||
tinyxml2::XMLElement *root = doc.FirstChildElement("Scenario");
|
||||
// 读取环境信息
|
||||
tinyxml2::XMLElement *envInfo = root->FirstChildElement("Environment");
|
||||
std::string OSName = envInfo->Attribute("OSName");
|
||||
std::string version = envInfo->Attribute("Version");
|
||||
std::string kernel = envInfo->Attribute("RTXVersion");
|
||||
std::string planeName = envInfo->Attribute("PlaneName");
|
||||
// 设置工作目录
|
||||
std::string rootPath = envInfo->Attribute("WorkPath");
|
||||
GetFramework()->SetWorkPath(rootPath);
|
||||
// 设置模型库目录
|
||||
std::string modelPath = rootPath + envInfo->Attribute("ModelsPath");
|
||||
GetFramework()->SetModelPath(modelPath);
|
||||
// 设置服务库目录
|
||||
std::string servicePath = rootPath + envInfo->Attribute("ServicesPath");
|
||||
GetFramework()->SetServicePath(servicePath);
|
||||
// 设置域ID
|
||||
uint32_t domainID = std::stoul(envInfo->Attribute("DomainID"));
|
||||
GetFramework()->GetDDSManager()->SetDomainID(domainID);
|
||||
// 读取CPU亲和性
|
||||
std::string cpuAff = envInfo->Attribute("CPUAffinity");
|
||||
std::vector<std::string> cpuAffList = XNSim::split(cpuAff, ",");
|
||||
|
||||
//读取服务列表
|
||||
tinyxml2::XMLElement *serviceList = root->FirstChildElement("ServicesList");
|
||||
if (serviceList) {
|
||||
tinyxml2::XMLElement *service = serviceList->FirstChildElement("Service");
|
||||
while (service) {
|
||||
std::string serviceName = service->Attribute("Name");
|
||||
std::string libName = service->Attribute("ClassName");
|
||||
std::string serviceVersion = service->Attribute("Version");
|
||||
libName = XNSim::getFileNameWithoutExt(libName);
|
||||
std::string dynamicLibName = servicePath + "/lib" + libName + ".so." + serviceVersion;
|
||||
// 加载动态库
|
||||
GetFramework()->GetServiceManager()->LoadService(dynamicLibName, libName,
|
||||
serviceVersion, 0);
|
||||
service = service->NextSiblingElement("Service");
|
||||
}
|
||||
}
|
||||
|
||||
// 读取模型分组
|
||||
tinyxml2::XMLElement *modelGroup = root->FirstChildElement("ModelGroup");
|
||||
while (modelGroup) {
|
||||
// 读取模型分组名称
|
||||
std::string modelGroupName = modelGroup->Attribute("Name");
|
||||
// 读取模型分组频率
|
||||
double modelGroupFreq = std::stod(modelGroup->Attribute("Freq"));
|
||||
// 读取模型分组优先级
|
||||
int modelGroupPriority = XNSim::safe_stoi(modelGroup->Attribute("Priority"));
|
||||
if (modelGroupPriority > 99 || modelGroupPriority < 0) {
|
||||
LOG_ERROR("0x2100 模型分组优先级设置错误,优先级值:%d", modelGroupPriority);
|
||||
return false;
|
||||
}
|
||||
// 读取模型分组CPU亲和性
|
||||
std::string modelGroupCPUAff = modelGroup->Attribute("CPUAff");
|
||||
std::vector<std::string> modelGroupCPUAffList = XNSim::split(modelGroupCPUAff, ",");
|
||||
|
||||
// 验证CPU亲和性
|
||||
for (const auto &cpu : modelGroupCPUAffList) {
|
||||
if (std::find(cpuAffList.begin(), cpuAffList.end(), cpu) == cpuAffList.end()) {
|
||||
LOG_ERROR("0x2100 模型分组CPU亲和性设置错误,CPU亲和性值:%s,进程CPU亲和性值:%s",
|
||||
cpu.c_str(), cpuAff.c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int ThreadCpuAffinity = 0;
|
||||
for (const auto &cpu : modelGroupCPUAffList) {
|
||||
auto it = std::find(cpuAffList.begin(), cpuAffList.end(), cpu);
|
||||
if (it != cpuAffList.end()) {
|
||||
ThreadCpuAffinity |= 1 << std::distance(cpuAffList.begin(), it);
|
||||
}
|
||||
}
|
||||
|
||||
// 添加线程池
|
||||
uint32_t threadID = GetFramework()->GetThreadManager()->AddThreadPool(
|
||||
modelGroupName, modelGroupFreq, modelGroupPriority, ThreadCpuAffinity);
|
||||
|
||||
// 读取模型列表
|
||||
tinyxml2::XMLElement *model = modelGroup->FirstChildElement("Model");
|
||||
while (model) {
|
||||
std::string modelName = model->Attribute("Name");
|
||||
std::string libName = model->Attribute("ClassName");
|
||||
std::string modelVersion = model->Attribute("Version");
|
||||
libName = XNSim::getFileNameWithoutExt(libName);
|
||||
std::string dynamicLibName = modelPath + "/lib" + libName + ".so." + modelVersion;
|
||||
// 加载动态库
|
||||
GetFramework()->GetModelManager()->LoadModel(dynamicLibName, libName, modelVersion,
|
||||
planeName, 0, threadID);
|
||||
model = model->NextSiblingElement("Model");
|
||||
}
|
||||
|
||||
modelGroup = modelGroup->NextSiblingElement("ModelGroup");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// 解析构型配置文件
|
||||
bool XNScenarioManager::ParseConfig(const std::string &ConfigID)
|
||||
{
|
||||
T_D();
|
||||
// 获取数据库路径
|
||||
std::string XNCorePath = std::getenv("XNCore");
|
||||
if (XNCorePath.empty()) {
|
||||
LOG_ERROR("0x1015 未设置XNCore环境变量, 引擎将退出!");
|
||||
return false;
|
||||
}
|
||||
std::string dbPath = XNCorePath + "/database/XNSim.db";
|
||||
|
||||
// 打开数据库
|
||||
sqlite3 *db;
|
||||
if (sqlite3_open(dbPath.c_str(), &db) != SQLITE_OK) {
|
||||
LOG_ERROR("0x1016 打开数据库失败: %1", sqlite3_errmsg(db));
|
||||
return false;
|
||||
}
|
||||
|
||||
// 准备SQL语句
|
||||
std::string sql = "SELECT * FROM Configuration WHERE ConfID = ?";
|
||||
sqlite3_stmt *stmt;
|
||||
if (sqlite3_prepare_v2(db, sql.c_str(), -1, &stmt, nullptr) != SQLITE_OK) {
|
||||
LOG_ERROR("0x1017 准备SQL语句失败: %1", sqlite3_errmsg(db));
|
||||
sqlite3_close(db);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 绑定参数
|
||||
int configIdInt = XNSim::safe_stoi(ConfigID);
|
||||
if (sqlite3_bind_int(stmt, 1, configIdInt) != SQLITE_OK) {
|
||||
LOG_ERROR("0x1018 绑定参数失败: %1", sqlite3_errmsg(db));
|
||||
sqlite3_finalize(stmt);
|
||||
sqlite3_close(db);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 执行查询
|
||||
if (sqlite3_step(stmt) != SQLITE_ROW) {
|
||||
LOG_ERROR("0x1019 未找到配置ID为%1的记录", ConfigID);
|
||||
sqlite3_finalize(stmt);
|
||||
sqlite3_close(db);
|
||||
return false;
|
||||
}
|
||||
std::string planeName = XNSim::getStringFromSqlite3(stmt, 1);
|
||||
std::string osName = XNSim::getStringFromSqlite3(stmt, 3);
|
||||
std::string version = XNSim::getStringFromSqlite3(stmt, 4);
|
||||
std::string kernel = XNSim::getStringFromSqlite3(stmt, 5);
|
||||
std::string rootPath = XNSim::getStringFromSqlite3(stmt, 7);
|
||||
if (rootPath.empty()) {
|
||||
LOG_WARNING("0x1020 未设置工作目录,使用默认工作目录: %1", XNCorePath);
|
||||
rootPath = XNCorePath;
|
||||
}
|
||||
GetFramework()->SetWorkPath(rootPath);
|
||||
// 设置模型库目录
|
||||
std::string modelPath = rootPath + XNSim::getStringFromSqlite3(stmt, 8);
|
||||
if (modelPath.empty()) {
|
||||
LOG_WARNING("0x1020 未设置模型库目录,使用默认模型库目录: %1/Models", XNCorePath);
|
||||
modelPath = XNCorePath + "/Models";
|
||||
}
|
||||
GetFramework()->SetModelPath(modelPath);
|
||||
// 设置服务库目录
|
||||
std::string servicePath = rootPath + XNSim::getStringFromSqlite3(stmt, 9);
|
||||
if (servicePath.empty()) {
|
||||
LOG_WARNING("0x1020 未设置服务库目录,使用默认服务库目录: %1/Services", XNCorePath);
|
||||
servicePath = XNCorePath + "/Services";
|
||||
}
|
||||
GetFramework()->SetServicePath(servicePath);
|
||||
// 设置域ID
|
||||
uint32_t domainID = std::stoul(XNSim::getStringFromSqlite3(stmt, 10));
|
||||
if (domainID == 0 || domainID > 225) {
|
||||
LOG_WARNING("0x1020 域ID设置错误,使用默认域ID: 10");
|
||||
domainID = 10;
|
||||
}
|
||||
GetFramework()->GetDDSManager()->SetDomainID(domainID);
|
||||
// 读取CPU亲和性
|
||||
std::string cpuAff = XNSim::getStringFromSqlite3(stmt, 6);
|
||||
std::vector<std::string> cpuAffList = XNSim::split(cpuAff, ",");
|
||||
|
||||
//查询LoadServices表读取服务信息
|
||||
std::string servicesSql = "SELECT * FROM LoadServices WHERE ConfID = ?";
|
||||
sqlite3_stmt *servicesStmt;
|
||||
if (sqlite3_prepare_v2(db, servicesSql.c_str(), -1, &servicesStmt, nullptr) != SQLITE_OK) {
|
||||
LOG_ERROR("0x1020 准备LoadServices查询语句失败: %1", sqlite3_errmsg(db));
|
||||
sqlite3_finalize(stmt);
|
||||
sqlite3_close(db);
|
||||
return false;
|
||||
}
|
||||
// 绑定参数
|
||||
if (sqlite3_bind_int(servicesStmt, 1, configIdInt) != SQLITE_OK) {
|
||||
LOG_ERROR("0x1021 绑定LoadServices参数失败: %1", sqlite3_errmsg(db));
|
||||
sqlite3_finalize(servicesStmt);
|
||||
sqlite3_finalize(stmt);
|
||||
sqlite3_close(db);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 执行查询并处理结果
|
||||
while (sqlite3_step(servicesStmt) == SQLITE_ROW) {
|
||||
// 获取服务信息
|
||||
std::string ClassName = XNSim::getStringFromSqlite3(servicesStmt, 1);
|
||||
std::string ServiceVersion = XNSim::getStringFromSqlite3(servicesStmt, 2);
|
||||
std::string ServiceName = XNSim::getStringFromSqlite3(servicesStmt, 3);
|
||||
|
||||
ClassName = XNSim::getFileNameWithoutExt(ClassName);
|
||||
std::string dynamicLibName = servicePath + "/lib" + ClassName + ".so." + ServiceVersion;
|
||||
// 加载动态库
|
||||
GetFramework()->GetServiceManager()->LoadService(dynamicLibName, ClassName, ServiceVersion,
|
||||
1);
|
||||
}
|
||||
|
||||
// 查询LoadModelGroups表读取模型组信息
|
||||
std::string modelGroupsSql = "SELECT * FROM LoadModelGroups WHERE ConfID = ?";
|
||||
sqlite3_stmt *modelGroupsStmt;
|
||||
if (sqlite3_prepare_v2(db, modelGroupsSql.c_str(), -1, &modelGroupsStmt, nullptr)
|
||||
!= SQLITE_OK) {
|
||||
LOG_ERROR("0x1020 准备LoadModelGroups查询语句失败: %1", sqlite3_errmsg(db));
|
||||
sqlite3_finalize(servicesStmt);
|
||||
sqlite3_finalize(stmt);
|
||||
sqlite3_close(db);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 绑定参数
|
||||
if (sqlite3_bind_int(modelGroupsStmt, 1, configIdInt) != SQLITE_OK) {
|
||||
LOG_ERROR("0x1021 绑定LoadModelGroups参数失败: %1", sqlite3_errmsg(db));
|
||||
sqlite3_finalize(modelGroupsStmt);
|
||||
sqlite3_finalize(servicesStmt);
|
||||
sqlite3_finalize(stmt);
|
||||
sqlite3_close(db);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 执行查询并处理结果
|
||||
while (sqlite3_step(modelGroupsStmt) == SQLITE_ROW) {
|
||||
// 获取模型组信息
|
||||
std::string GroupID = XNSim::getStringFromSqlite3(modelGroupsStmt, 1);
|
||||
std::string GroupName = XNSim::getStringFromSqlite3(modelGroupsStmt, 2);
|
||||
double GroupFreq = std::stod(XNSim::getStringFromSqlite3(modelGroupsStmt, 3));
|
||||
uint32_t GroupPriority = XNSim::safe_stoi(XNSim::getStringFromSqlite3(modelGroupsStmt, 4));
|
||||
std::string GroupCPUAff = XNSim::getStringFromSqlite3(modelGroupsStmt, 5);
|
||||
std::vector<std::string> GroupCPUAffList = XNSim::split(GroupCPUAff, ",");
|
||||
|
||||
// 验证CPU亲和性
|
||||
for (const auto &cpu : GroupCPUAffList) {
|
||||
if (std::find(cpuAffList.begin(), cpuAffList.end(), cpu) == cpuAffList.end()) {
|
||||
LOG_ERROR("0x2100 模型分组CPU亲和性设置错误,CPU亲和性值:%s,进程CPU亲和性值:%s",
|
||||
cpu.c_str(), cpuAff.c_str());
|
||||
sqlite3_finalize(modelGroupsStmt);
|
||||
sqlite3_finalize(servicesStmt);
|
||||
sqlite3_finalize(stmt);
|
||||
sqlite3_close(db);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int ThreadCpuAffinity = 0;
|
||||
for (const auto &cpu : GroupCPUAffList) {
|
||||
auto it = std::find(cpuAffList.begin(), cpuAffList.end(), cpu);
|
||||
if (it != cpuAffList.end()) {
|
||||
ThreadCpuAffinity |= 1 << std::distance(cpuAffList.begin(), it);
|
||||
}
|
||||
}
|
||||
LOG_INFO("0x1021 添加线程池: %1", GroupName);
|
||||
// 添加线程池
|
||||
uint32_t threadID = GetFramework()->GetThreadManager()->AddThreadPool(
|
||||
GroupName, GroupFreq, GroupPriority, ThreadCpuAffinity);
|
||||
|
||||
// 准备查询LoadModels表的SQL语句
|
||||
std::string modelsSql = "SELECT * FROM LoadModels WHERE GroupID = ?";
|
||||
sqlite3_stmt *modelsStmt = nullptr;
|
||||
if (sqlite3_prepare_v2(db, modelsSql.c_str(), -1, &modelsStmt, nullptr) != SQLITE_OK) {
|
||||
LOG_ERROR("0x1022 准备LoadModels查询语句失败: %1", sqlite3_errmsg(db));
|
||||
sqlite3_finalize(modelGroupsStmt);
|
||||
sqlite3_finalize(servicesStmt);
|
||||
sqlite3_finalize(stmt);
|
||||
sqlite3_close(db);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 绑定参数
|
||||
if (sqlite3_bind_int(modelsStmt, 1, XNSim::safe_stoi(GroupID)) != SQLITE_OK) {
|
||||
LOG_ERROR("0x1023 绑定LoadModels参数失败: %1", sqlite3_errmsg(db));
|
||||
sqlite3_finalize(modelsStmt);
|
||||
sqlite3_finalize(modelGroupsStmt);
|
||||
sqlite3_finalize(servicesStmt);
|
||||
sqlite3_finalize(stmt);
|
||||
sqlite3_close(db);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 执行查询并处理结果
|
||||
while (sqlite3_step(modelsStmt) == SQLITE_ROW) {
|
||||
// 获取模型信息
|
||||
std::string ClassName = XNSim::getStringFromSqlite3(modelsStmt, 1);
|
||||
std::string ModelVersion = XNSim::getStringFromSqlite3(modelsStmt, 2);
|
||||
std::string ModelName = XNSim::getStringFromSqlite3(modelsStmt, 3);
|
||||
|
||||
ClassName = XNSim::getFileNameWithoutExt(ClassName);
|
||||
std::string dynamicLibName = modelPath + "/lib" + ClassName + ".so." + ModelVersion;
|
||||
// 加载动态库
|
||||
LOG_INFO("0x1021 加载模型: %1", dynamicLibName);
|
||||
GetFramework()->GetModelManager()->LoadModel(dynamicLibName, ClassName, ModelVersion,
|
||||
planeName, 1, threadID);
|
||||
}
|
||||
// 清理资源
|
||||
sqlite3_finalize(modelsStmt);
|
||||
}
|
||||
|
||||
// 清理资源
|
||||
sqlite3_finalize(modelGroupsStmt);
|
||||
sqlite3_finalize(servicesStmt);
|
||||
sqlite3_finalize(stmt);
|
||||
sqlite3_close(db);
|
||||
return true;
|
||||
}
|
98
XNCore_Win/XNConfigManager/XNConfigManager.h
Normal file
98
XNCore_Win/XNConfigManager/XNConfigManager.h
Normal file
@ -0,0 +1,98 @@
|
||||
/**
|
||||
* @file XNScenarioDescriptor.h
|
||||
* @author jinchao
|
||||
* @brief 运行环境描述管理器类头文件
|
||||
* @version 1.0
|
||||
* @date 2024-11-07
|
||||
*
|
||||
* @copyright Copyright (c) 2024 XN
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
#include <XNBaseFrameObject/XNBaseFrameObject.h>
|
||||
|
||||
namespace XNSim {
|
||||
struct XNConfigManagerPrivate;
|
||||
|
||||
/**
|
||||
* @brief 构型管理器类
|
||||
* @details 主要负责解析构型配置来设置系统运行参数。
|
||||
*/
|
||||
class XNConfigManager : public XNBaseFrameObject {
|
||||
XN_METATYPE(XNConfigManager, XNBaseFrameObject)
|
||||
XN_DECLARE_PRIVATE(XNConfigManager)
|
||||
public:
|
||||
/**
|
||||
* @brief 构型管理器类默认构造函数
|
||||
*/
|
||||
XNConfigManager();
|
||||
|
||||
/**
|
||||
* @brief 构型管理器类析构函数
|
||||
*/
|
||||
virtual ~XNConfigManager();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief 构型管理器类带参构造函数
|
||||
* @param p:私有结构体指针
|
||||
* @details 子类构造时调用此构造函数,传入子类的私有结构体指针
|
||||
*/
|
||||
XNConfigManager(PrivateType *p);
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief 获取构型名称
|
||||
* @return const XNString&: 构型名称
|
||||
*/
|
||||
const XN_STRING &GetSimName();
|
||||
|
||||
/**
|
||||
* @brief 设置构型名称
|
||||
* @param simName: XNString类型,构型名称
|
||||
*/
|
||||
void SetSimName(const XN_STRING &simName);
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief 初始化构型管理器
|
||||
* @return true: 初始化成功
|
||||
* @return false: 初始化失败
|
||||
* @details 构型管理器的初始化接口函数
|
||||
*/
|
||||
virtual XN_BOOL Initialize() override;
|
||||
|
||||
/**
|
||||
* @brief 仿真运行前最后处理
|
||||
* @note 构型管理器在系统运行开始前的准备工作
|
||||
*/
|
||||
virtual XN_BOOL PrepareForExecute() override;
|
||||
|
||||
/**
|
||||
* @brief 构型配置文件解析
|
||||
* @param XmlPath: std::string类型,构型配置文件解析路径
|
||||
* @param initialType: uint32_t类型,初始化类型
|
||||
* @return true: 解析成功
|
||||
* @return false: 解析失败
|
||||
*/
|
||||
virtual XN_BOOL AnalysisScenarioXml(const XN_STRING &XmlPath,
|
||||
XN_UINT32 initialType);
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief 解析构型配置文件
|
||||
* @param XmlPath: std::string类型,构型配置文件解析路径
|
||||
* @return true: 解析成功
|
||||
* @return false: 解析失败
|
||||
*/
|
||||
XN_BOOL ParseScenarioXml(const XN_STRING &XmlPath);
|
||||
|
||||
/**
|
||||
* @brief 解析构型配置文件
|
||||
* @param ConfigID: std::string类型,构型配置文件在数据库中的ID
|
||||
* @return true: 解析成功
|
||||
* @return false: 解析失败
|
||||
*/
|
||||
XN_BOOL ParseConfig(const XN_STRING &ConfigID);
|
||||
};
|
||||
} // namespace XNSim
|
24
XNCore_Win/XNConfigManager/XNConfigManager_p.h
Normal file
24
XNCore_Win/XNConfigManager/XNConfigManager_p.h
Normal file
@ -0,0 +1,24 @@
|
||||
/**
|
||||
* @file XNScenarioDescriptor_p.h
|
||||
* @author jinchao
|
||||
* @brief 运行环境描述管理器类私有头文件
|
||||
* @version 1.0
|
||||
* @date 2024-11-07
|
||||
*
|
||||
* @copyright Copyright (c) 2024 XN
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
#include <XNBaseFrameObject/XNBaseFrameObject_p.h>
|
||||
|
||||
namespace XNSim {
|
||||
/**
|
||||
* @brief 运行环境描述管理器类私有结构体
|
||||
*/
|
||||
struct XNScenarioManagerPrivate : public XNBaseFrameObjectPrivate {
|
||||
/**
|
||||
* @brief 运行环境名称
|
||||
*/
|
||||
XN_STRING _ConfigName;
|
||||
};
|
||||
} // namespace XNSim
|
6
XNCore_Win/XNDDSInterface/CMakeLists.txt
Normal file
6
XNCore_Win/XNDDSInterface/CMakeLists.txt
Normal file
@ -0,0 +1,6 @@
|
||||
set(XNDDSINTERFACE_SOURCES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XNDDSInterface.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XNDDSInterface.cpp
|
||||
)
|
||||
|
||||
set(XNCORE_SOURCES ${XNCORE_SOURCES} ${XNDDSINTERFACE_SOURCES} PARENT_SCOPE)
|
94
XNCore_Win/XNDDSInterface/XNDDSInterface.cpp
Normal file
94
XNCore_Win/XNDDSInterface/XNDDSInterface.cpp
Normal file
@ -0,0 +1,94 @@
|
||||
#include "XNDDSInterface.h"
|
||||
#include "XNDDSManager/XNDDSManager.h"
|
||||
#include "XNFramework/XNFramework.h"
|
||||
|
||||
namespace XNSim {
|
||||
XNByteArray XNDDSInterface::getUDPPackage() {
|
||||
XNByteArray result;
|
||||
|
||||
size_t currentPos = 0;
|
||||
|
||||
// 复制头部
|
||||
result.append(header, headerSize);
|
||||
currentPos = headerSize;
|
||||
|
||||
// 复制数据
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(dataMutex);
|
||||
for (auto func : getByteArrayFunction) {
|
||||
XNByteArray byteArray = func();
|
||||
size_t byteArraySize = byteArray.size();
|
||||
if (currentPos + byteArraySize <= MAX_UDP_PACKET_SIZE) {
|
||||
result.append(byteArray);
|
||||
currentPos += byteArraySize; // 使用实际返回的字节数组大小
|
||||
} else {
|
||||
break; // 超出最大包大小
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 更新包大小
|
||||
if (currentPos >= 8 && currentPos < MAX_UDP_PACKET_SIZE) {
|
||||
result[6] = static_cast<uint8_t>((currentPos >> 8) & 0xFF);
|
||||
result[7] = static_cast<uint8_t>(currentPos & 0xFF);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void XNDDSInterface::setDataByUDPPackage(const XNByteArray &package) {
|
||||
if (package.size() < headerSize) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取包大小
|
||||
uint16_t packageSize = (package[6] << 8) | package[7];
|
||||
if (packageSize > MAX_UDP_PACKET_SIZE) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t currentPos = 8;
|
||||
|
||||
// 设置数据
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(outDataMutex);
|
||||
clearOutData();
|
||||
for (auto &func : setByteArrayFunction) {
|
||||
func(package, currentPos);
|
||||
}
|
||||
}
|
||||
sendOutData();
|
||||
}
|
||||
|
||||
std::unordered_map<std::string, std::string>
|
||||
XNDDSInterface::getStringData(const std::vector<std::string> &varNames) {
|
||||
std::unordered_map<std::string, std::string> result;
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(dataMutex);
|
||||
for (const auto &varName : varNames) {
|
||||
auto it = getDataFunction.find(varName);
|
||||
if (it == getDataFunction.end()) {
|
||||
continue;
|
||||
}
|
||||
result[varName] = it->second();
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void XNDDSInterface::setDataByString(
|
||||
const std::unordered_map<std::string, std::string> &data) {
|
||||
std::lock_guard<std::mutex> lock(outDataMutex);
|
||||
clearOutData();
|
||||
for (const auto &[varName, value] : data) {
|
||||
auto it = setDataFunction.find(varName);
|
||||
if (it == setDataFunction.end()) {
|
||||
continue;
|
||||
}
|
||||
it->second(value);
|
||||
}
|
||||
sendOutData();
|
||||
}
|
||||
} // namespace XNSim
|
422
XNCore_Win/XNDDSInterface/XNDDSInterface.h
Normal file
422
XNCore_Win/XNDDSInterface/XNDDSInterface.h
Normal file
@ -0,0 +1,422 @@
|
||||
#pragma once
|
||||
|
||||
#include "XNGlobalDefine/XNDefine.h"
|
||||
|
||||
namespace XNSim {
|
||||
// 定义UDP包的最大大小
|
||||
constexpr XN_SIZE MAX_UDP_PACKET_SIZE = 40000;
|
||||
|
||||
using XNInterfaceToDataMap = std::unordered_map<XN_STRING, XN_STRING>;
|
||||
using XNInterfaceList = std::vector<XN_STRING>;
|
||||
using XNGetDataFunction = std::function<XN_STRING()>;
|
||||
using XNSetDataFunction = std::function<void(XN_STRING)>;
|
||||
using XNGetByteArrayFunction = std::function<XNByteArray(void)>;
|
||||
using XNSetByteArrayFunction = std::function<void(XNByteArray, XN_UINT32 &)>;
|
||||
using XNGetDataFunctionMap = std::unordered_map<XN_STRING, XNGetDataFunction>;
|
||||
using XNSetDataFunctionMap = std::unordered_map<XN_STRING, XNSetDataFunction>;
|
||||
using XNGetByteArrayFunctionMap = std::vector<XNGetByteArrayFunction>;
|
||||
using XNSetByteArrayFunctionMap = std::vector<XNSetByteArrayFunction>;
|
||||
|
||||
class XNDDSInterface {
|
||||
public:
|
||||
XNDDSInterface() = default;
|
||||
virtual ~XNDDSInterface() = default;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief 初始化
|
||||
* @param framework: 框架
|
||||
*/
|
||||
virtual void Initialize(XNFrameworkPtr framework, XN_UINT32 modelID,
|
||||
XN_UINT32 DDS_type) = 0;
|
||||
|
||||
/**
|
||||
* @brief 获取该接口的UDP包
|
||||
* @return 字节数组
|
||||
*/
|
||||
XNByteArray getUDPPackage();
|
||||
|
||||
/**
|
||||
* @brief 通过UDP包设置数据
|
||||
* @param package: UDP包
|
||||
*/
|
||||
void setDataByUDPPackage(const XNByteArray &package);
|
||||
|
||||
/**
|
||||
* @brief 批量获取指定变量的数据
|
||||
* @param varNames: 变量名列表
|
||||
* @return: 变量名到数据的映射
|
||||
*/
|
||||
XNInterfaceToDataMap getStringData(const XNInterfaceList &varNames);
|
||||
|
||||
/**
|
||||
* @brief 批量设置指定变量的数据
|
||||
* @param data: 变量名到数据的映射
|
||||
*/
|
||||
void setDataByString(const XNInterfaceToDataMap &data);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief 获取指定变量的字节数据,用于网络通信
|
||||
* @param data: 数据
|
||||
* @return 字节数组
|
||||
*/
|
||||
template <typename T> XNByteArray getByteArray(const XNDDSOptional<T> &data) {
|
||||
XNByteArray result(getTypeSize<T>());
|
||||
|
||||
if constexpr (std::is_arithmetic_v<T>) {
|
||||
if (data) {
|
||||
std::memcpy(result.data(), &data.value(), sizeof(T));
|
||||
} else {
|
||||
T zero = 0;
|
||||
std::memcpy(result.data(), &zero, sizeof(T));
|
||||
}
|
||||
} else if constexpr (is_array_v<T>) {
|
||||
if (data) {
|
||||
return getByteArrayFromStdArray(data.value());
|
||||
} else {
|
||||
T zero = {};
|
||||
return getByteArrayFromStdArray(zero);
|
||||
}
|
||||
} else {
|
||||
static_assert(
|
||||
std::is_arithmetic_v<T> || is_array_v<T>,
|
||||
"T 必须是算术类型或std::array类型,详见XNDDSInterface.cpp:line 78");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 设置指定变量的字节数据,用于网络通信
|
||||
* @param data: 数据
|
||||
* @param byteArray: 字节数组
|
||||
*/
|
||||
template <typename T>
|
||||
void setByteArray(XNDDSOptional<T> &data, const XNByteArray &byteArray,
|
||||
XN_UINT32 &pos) {
|
||||
XN_UINT32 thisSize = getTypeSize<T>();
|
||||
XNByteArray thisArray(thisSize);
|
||||
if (pos + thisSize > byteArray.size()) {
|
||||
return;
|
||||
}
|
||||
std::memcpy(thisArray.data(), byteArray.data() + pos, thisSize);
|
||||
pos += thisSize;
|
||||
|
||||
if constexpr (std::is_arithmetic_v<T>) {
|
||||
T temp;
|
||||
std::memcpy(&temp, thisArray.data(), sizeof(T));
|
||||
data = temp;
|
||||
} else if constexpr (is_array_v<T>) {
|
||||
if (!data) {
|
||||
data = T{};
|
||||
}
|
||||
setByteArrayFromStdArray(data.value(), thisArray);
|
||||
} else {
|
||||
static_assert(std::is_arithmetic_v<T> || is_array_v<T>,
|
||||
"T 必须是算术类型或std::array类型,详见" +
|
||||
XN_STRING(__FILE__) + ":" + XN_STRING(__LINE__));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取指定数组变量的字节数据,用于网络通信
|
||||
* @param data: 数据
|
||||
* @return 字节数组
|
||||
*/
|
||||
template <typename T, XN_SIZE N>
|
||||
XNByteArray getByteArrayFromStdArray(const std::array<T, N> &data) {
|
||||
XNByteArray result(getTypeSize<T>() * N);
|
||||
|
||||
for (XN_SIZE i = 0; i < N; ++i) {
|
||||
if constexpr (std::is_arithmetic_v<T>) {
|
||||
std::memcpy(result.data() + i * getTypeSize<T>(), &data[i],
|
||||
getTypeSize<T>());
|
||||
} else if constexpr (is_array_v<T>) {
|
||||
XNByteArray subArray = getByteArrayFromStdArray(data[i]);
|
||||
std::memcpy(result.data() + i * getTypeSize<T>(), subArray.data(),
|
||||
getTypeSize<T>());
|
||||
} else {
|
||||
static_assert(std::is_arithmetic_v<T> || is_array_v<T>,
|
||||
"T 必须是算术类型或std::array类型,详见" +
|
||||
XN_STRING(__FILE__) + ":" + XN_STRING(__LINE__));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 设置指定数组变量的字节数据,用于网络通信
|
||||
* @param data: 数据
|
||||
* @param byteArray: 字节数组
|
||||
*/
|
||||
template <typename T, XN_SIZE N>
|
||||
void setByteArrayFromStdArray(std::array<T, N> &data,
|
||||
const XNByteArray &byteArray) {
|
||||
if (byteArray.size() < getTypeSize<T>() * N)
|
||||
return;
|
||||
|
||||
for (XN_SIZE i = 0; i < N; ++i) {
|
||||
if constexpr (std::is_arithmetic_v<T>) {
|
||||
std::memcpy(&data[i], byteArray.data() + i * getTypeSize<T>(),
|
||||
getTypeSize<T>());
|
||||
} else if constexpr (is_array_v<T>) {
|
||||
XNByteArray subArray(byteArray.data() + i * getTypeSize<T>(),
|
||||
getTypeSize<T>());
|
||||
setByteArrayFromStdArray(data[i], subArray);
|
||||
} else {
|
||||
static_assert(std::is_arithmetic_v<T> || is_array_v<T>,
|
||||
"T 必须是算术类型或std::array类型,详见" +
|
||||
XN_STRING(__FILE__) + ":" + XN_STRING(__LINE__));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取指定变量的字符串数据,用于JSON前端
|
||||
* @param data: 数据
|
||||
* @return: 数据(字符串格式)
|
||||
*/
|
||||
template <typename T> std::string getString(const XNDDSOptional<T> &data) {
|
||||
if constexpr (std::is_arithmetic_v<T>) {
|
||||
if (data) {
|
||||
return std::to_string(data.value());
|
||||
} else {
|
||||
return "Unknown";
|
||||
}
|
||||
} else if constexpr (is_array_v<T>) {
|
||||
if (data) {
|
||||
return getStringFromStdArray(data.value());
|
||||
} else {
|
||||
T zero = {};
|
||||
return getStringFromStdArray(zero);
|
||||
}
|
||||
} else {
|
||||
static_assert(std::is_arithmetic_v<T> || is_array_v<T>,
|
||||
"T 必须是算术类型或std::array类型,详见" +
|
||||
XN_STRING(__FILE__) + ":" + XN_STRING(__LINE__));
|
||||
}
|
||||
return std::string();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 通过字符串数据设置指定变量,用于JSON前端
|
||||
* @param data: 数据
|
||||
* @param value: 字符串数据
|
||||
*/
|
||||
template <typename T>
|
||||
void setDataFromString(XNDDSOptional<T> &data, const std::string &value) {
|
||||
if constexpr (std::is_arithmetic_v<T>) {
|
||||
if constexpr (std::is_same_v<T, float> || std::is_same_v<T, double>) {
|
||||
data = std::stod(value);
|
||||
} else {
|
||||
data = std::stoll(value);
|
||||
}
|
||||
} else if constexpr (is_array_v<T>) {
|
||||
// 解析输入字符串
|
||||
std::stringstream ss(value);
|
||||
std::string item;
|
||||
std::vector<std::string> items;
|
||||
while (std::getline(ss, item, ',')) {
|
||||
items.push_back(item);
|
||||
}
|
||||
T temp;
|
||||
setStdArrayFromString(temp, items, 0);
|
||||
data = temp;
|
||||
} else {
|
||||
static_assert(std::is_arithmetic_v<T> || is_array_v<T>,
|
||||
"T 必须是算术类型或std::array类型,详见" +
|
||||
XN_STRING(__FILE__) + ":" + XN_STRING(__LINE__));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取指定数组变量的字符串数据,用于JSON前端
|
||||
* @param data: 数据
|
||||
* @return: 数据(字符串格式)
|
||||
*/
|
||||
template <typename T, XN_SIZE N>
|
||||
std::string getStringFromStdArray(const std::array<T, N> &data) {
|
||||
std::stringstream ss;
|
||||
for (XN_SIZE i = 0; i < N; ++i) {
|
||||
if (i > 0)
|
||||
ss << ",";
|
||||
if constexpr (std::is_arithmetic_v<T>) {
|
||||
ss << data[i];
|
||||
} else if constexpr (is_array_v<T>) {
|
||||
ss << getStringFromStdArray(data[i]);
|
||||
} else {
|
||||
static_assert(std::is_arithmetic_v<T> || is_array_v<T>,
|
||||
"T 必须是算术类型或std::array类型,详见" +
|
||||
XN_STRING(__FILE__) + ":" + XN_STRING(__LINE__));
|
||||
}
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 通过字符串数据设置指定数组变量,用于JSON前端
|
||||
* @param data: 数据
|
||||
* @param value: 字符串数据,格式为"数字,数字,..."
|
||||
* @param start_pos: 当前数组在输入字符串中的起始位置
|
||||
* @return 处理完当前数组后,下一个数组的起始位置
|
||||
* @throw std::runtime_error: 当输入数据格式不正确时抛出异常
|
||||
*/
|
||||
template <typename T, XN_SIZE N>
|
||||
size_t setStdArrayFromString(std::array<T, N> &data,
|
||||
const std::vector<std::string> &value,
|
||||
size_t start_pos = 0) {
|
||||
// 递归处理每个元素
|
||||
for (XN_SIZE i = 0; i < N; ++i) {
|
||||
try {
|
||||
if constexpr (std::is_arithmetic_v<T>) {
|
||||
// 对于基本类型,直接转换
|
||||
if constexpr (std::is_same_v<T, float> || std::is_same_v<T, double>) {
|
||||
data[i] = static_cast<T>(std::stod(value[start_pos + i]));
|
||||
} else {
|
||||
data[i] = static_cast<T>(std::stoll(value[start_pos + i]));
|
||||
}
|
||||
} else if constexpr (is_array_v<T>) {
|
||||
// 对于嵌套数组,递归处理
|
||||
start_pos = setStdArrayFromString(data[i], value, start_pos);
|
||||
} else {
|
||||
static_assert(
|
||||
std::is_arithmetic_v<T> || is_array_v<T>,
|
||||
"T 必须是算术类型或std::array类型,详见XNDDSInterface.cpp:line "
|
||||
"275");
|
||||
}
|
||||
} catch (const std::exception &e) {
|
||||
throw std::runtime_error("无法解析第 " + std::to_string(i) +
|
||||
" 个元素: " + e.what());
|
||||
}
|
||||
}
|
||||
return start_pos + N;
|
||||
}
|
||||
|
||||
template <typename T1, typename T2>
|
||||
void assign_value_get(const XNDDSOptional<T1> &data, T2 &model_data) {
|
||||
if (data) {
|
||||
auto temp = data.value();
|
||||
if constexpr (std::is_arithmetic_v<T1>) {
|
||||
static_assert(std::is_arithmetic_v<T2>,
|
||||
"模板参数T2必须是算术类型,详见" + XN_STRING(__FILE__) +
|
||||
":" + XN_STRING(__LINE__));
|
||||
static_assert(std::is_convertible_v<T1, T2>,
|
||||
"模板参数T1必须可以转换为T2类型,详见" +
|
||||
XN_STRING(__FILE__) + ":" + XN_STRING(__LINE__));
|
||||
model_data = temp;
|
||||
} else if constexpr (is_array_v<T1>) {
|
||||
XN_SIZE arraySize = array_size_v<T1>;
|
||||
for (XN_SIZE i = 0; i < arraySize; ++i) {
|
||||
auto temp2 = temp[i];
|
||||
using array_type = typename T1::value_type;
|
||||
if constexpr (std::is_arithmetic_v<array_type>) {
|
||||
model_data[i] = temp2;
|
||||
} else if constexpr (is_array_v<array_type>) {
|
||||
XN_SIZE arraySize2 = array_size_v<array_type>;
|
||||
using sub_array_type = typename array_type::value_type;
|
||||
if constexpr (std::is_arithmetic_v<sub_array_type>) {
|
||||
for (XN_SIZE j = 0; j < arraySize2; ++j) {
|
||||
model_data[i][j] = temp2[j];
|
||||
}
|
||||
} else {
|
||||
static_assert(std::is_arithmetic_v<sub_array_type>,
|
||||
"模板参数T1是std::"
|
||||
"array类型时,它的数组嵌套不能超过两层,详见" +
|
||||
XN_STRING(__FILE__) + ":" +
|
||||
XN_STRING(__LINE__));
|
||||
}
|
||||
} else {
|
||||
static_assert(std::is_arithmetic_v<array_type> ||
|
||||
is_array_v<array_type>,
|
||||
"模板参数T1是std::array类型时,它的value_"
|
||||
"type必须是算术类型或std::"
|
||||
"array类型,详见" +
|
||||
XN_STRING(__FILE__) + ":" + XN_STRING(__LINE__));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
static_assert(std::is_arithmetic_v<T1> || is_array_v<T1>,
|
||||
"模板参数T1必须是算术类型或std::"
|
||||
"array类型,详见" +
|
||||
XN_STRING(__FILE__) + ":" + XN_STRING(__LINE__));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T1, typename T2>
|
||||
void assign_value_set(XNDDSOptional<T1> &data, const T2 &model_data) {
|
||||
if constexpr (std::is_arithmetic_v<T1>) {
|
||||
static_assert(std::is_arithmetic_v<T2>, "模板参数T2必须是算术类型,详见" +
|
||||
XN_STRING(__FILE__) + ":" +
|
||||
XN_STRING(__LINE__));
|
||||
static_assert(std::is_convertible_v<T2, T1>,
|
||||
"模板参数T2必须可以转换为T1类型,详见" +
|
||||
XN_STRING(__FILE__) + ":" + XN_STRING(__LINE__));
|
||||
data = model_data;
|
||||
} else if constexpr (is_array_v<T1>) {
|
||||
T1 temp;
|
||||
XN_SIZE arraySize = array_size_v<T1>;
|
||||
using array_type = typename T1::value_type;
|
||||
for (XN_SIZE i = 0; i < arraySize; ++i) {
|
||||
if constexpr (std::is_arithmetic_v<array_type>) {
|
||||
temp[i] = model_data[i];
|
||||
} else if constexpr (is_array_v<array_type>) {
|
||||
XN_SIZE arraySize2 = array_size_v<array_type>;
|
||||
using sub_array_type = typename array_type::value_type;
|
||||
if constexpr (std::is_arithmetic_v<sub_array_type>) {
|
||||
for (XN_SIZE j = 0; j < arraySize2; ++j) {
|
||||
temp[i][j] = model_data[i][j];
|
||||
}
|
||||
} else {
|
||||
static_assert(std::is_arithmetic_v<sub_array_type>,
|
||||
"模板参数T1是std::"
|
||||
"array类型时,它的数组嵌套不能超过两层,详见" +
|
||||
XN_STRING(__FILE__) + ":" + XN_STRING(__LINE__));
|
||||
}
|
||||
} else {
|
||||
static_assert(std::is_arithmetic_v<array_type> ||
|
||||
is_array_v<array_type>,
|
||||
"模板参数T1是std::array类型时,它的value_"
|
||||
"type必须是算术类型或std::"
|
||||
"array类型,详见" +
|
||||
XN_STRING(__FILE__) + ":" + XN_STRING(__LINE__));
|
||||
}
|
||||
}
|
||||
data = temp;
|
||||
} else {
|
||||
static_assert(std::is_arithmetic_v<T1> || is_array_v<T1>,
|
||||
"模板参数T1必须是算术类型或std::"
|
||||
"array类型,详见" +
|
||||
XN_STRING(__FILE__) + ":" + XN_STRING(__LINE__));
|
||||
}
|
||||
}
|
||||
|
||||
virtual void clearOutData() {}
|
||||
virtual void sendOutData() {}
|
||||
|
||||
protected:
|
||||
XNGetDataFunctionMap getDataFunction;
|
||||
XNSetDataFunctionMap setDataFunction;
|
||||
XNGetByteArrayFunctionMap getByteArrayFunction;
|
||||
XNSetByteArrayFunctionMap setByteArrayFunction;
|
||||
XN_MUTEX dataMutex;
|
||||
XN_MUTEX outDataMutex;
|
||||
XN_UINT8 header[8]{0}; // 固定大小的头部
|
||||
XN_SIZE headerSize = 8;
|
||||
XNDDSDataWriterPtr dataWriter;
|
||||
};
|
||||
} // namespace XNSim
|
||||
|
||||
#define MAP_DATA_FUNC(NAME) \
|
||||
getDataFunction[#NAME] = [this]() { return getString(data.NAME()); }; \
|
||||
setDataFunction[#NAME] = [this](const XN_STRING &value) { \
|
||||
setDataFromString(out_data.NAME(), value); \
|
||||
}; \
|
||||
getByteArrayFunction.push_back( \
|
||||
[this]() { return getByteArray(data.NAME()); }); \
|
||||
setByteArrayFunction.push_back( \
|
||||
[this](const XNByteArray &byteArray, XN_UINT32 &pos) { \
|
||||
setByteArray(out_data.NAME(), byteArray, pos); \
|
||||
});
|
6
XNCore_Win/XNDDSManager/CMakeLists.txt
Normal file
6
XNCore_Win/XNDDSManager/CMakeLists.txt
Normal file
@ -0,0 +1,6 @@
|
||||
set(XNDDSMANAGER_SOURCES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XNDDSManager.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XNDDSManager.cpp
|
||||
)
|
||||
|
||||
set(XNCORE_SOURCES ${XNCORE_SOURCES} ${XNDDSMANAGER_SOURCES} PARENT_SCOPE)
|
40
XNCore_Win/XNDDSManager/XNDDSManager.cpp
Normal file
40
XNCore_Win/XNDDSManager/XNDDSManager.cpp
Normal file
@ -0,0 +1,40 @@
|
||||
#include "XNDDSManager.h"
|
||||
|
||||
namespace XNSim {
|
||||
XNDDSManager::XNDDSManager() : XNBaseFrameObject(new XNDDSManagerPrivate()) {
|
||||
SetUniqueId(enumValue(XNCoreObjectID::DDSManager));
|
||||
SetObjectName("XNDDSManager");
|
||||
}
|
||||
|
||||
XNDDSManager::~XNDDSManager() {}
|
||||
|
||||
XNDDSManager::XNDDSManager(PrivateType *p) : XNBaseFrameObject(p) {}
|
||||
|
||||
XN_BOOL XNDDSManager::Initialize() {
|
||||
T_D();
|
||||
d->_status = XNFrameObjectStatus::Initialized;
|
||||
d->participant_ = nullptr;
|
||||
d->topics_.clear();
|
||||
LOG_INFO("DDS管理器初始化成功!");
|
||||
return true;
|
||||
}
|
||||
|
||||
XN_BOOL XNDDSManager::PrepareForExecute() {
|
||||
T_D();
|
||||
d->_status = XNFrameObjectStatus::Ready;
|
||||
LOG_INFO("DDS管理器准备就绪!");
|
||||
return true;
|
||||
}
|
||||
|
||||
void XNDDSManager::SetDomainID(XN_UINT32 domainID) {
|
||||
T_D();
|
||||
XNDDSParticipantQos participantQos;
|
||||
participantQos.name("XNDDSManager");
|
||||
d->participant_ =
|
||||
XN_DDS::DomainParticipantFactory::get_instance()->create_participant(
|
||||
domainID, participantQos);
|
||||
if (d->participant_ == nullptr) {
|
||||
LOG_ERROR("0x2130 DDS管理器创建域参与者失败!");
|
||||
}
|
||||
}
|
||||
} // namespace XNSim
|
126
XNCore_Win/XNDDSManager/XNDDSManager.h
Normal file
126
XNCore_Win/XNDDSManager/XNDDSManager.h
Normal file
@ -0,0 +1,126 @@
|
||||
#pragma once
|
||||
#include "XNBaseFrameObject/XNBaseFrameObject.h"
|
||||
#include "XNBaseFrameObject/XNBaseFrameObject_p.h"
|
||||
|
||||
namespace XNSim {
|
||||
struct XNDDSManagerPrivate : public XNBaseFrameObjectPrivate {
|
||||
XNDDSParticipantPtr participant_;
|
||||
XNDDSTopicMap topics_;
|
||||
std::mutex mutex_;
|
||||
};
|
||||
|
||||
class XNDDSManager : public XNBaseFrameObject {
|
||||
XN_METATYPE(XNDDSManager, XNBaseFrameObject)
|
||||
XN_DECLARE_PRIVATE(XNDDSManager)
|
||||
public:
|
||||
XNDDSManager();
|
||||
~XNDDSManager();
|
||||
|
||||
protected:
|
||||
XNDDSManager(PrivateType *p);
|
||||
|
||||
public:
|
||||
virtual XN_BOOL Initialize() override;
|
||||
|
||||
virtual XN_BOOL PrepareForExecute() override;
|
||||
|
||||
void SetDomainID(XN_UINT32 domainID);
|
||||
|
||||
public:
|
||||
template <typename T>
|
||||
XNDDSDataWriterPtr RegisterPublisher(const XN_STRING &topicName,
|
||||
XN_UINT32 publisherID) {
|
||||
T_D();
|
||||
std::lock_guard<std::mutex> lock(d->mutex_);
|
||||
if (d->topics_.find(topicName) == d->topics_.end()) {
|
||||
d->topics_[topicName] = TopicInfo();
|
||||
TopicInfo &tmp = d->topics_[topicName];
|
||||
XNDDSTypeSupport typeSupport(new T());
|
||||
typeSupport.register_type(d->participant_);
|
||||
tmp.topic = d->participant_->create_topic(
|
||||
topicName, typeSupport.get_type_name(), XN_DDS::TOPIC_QOS_DEFAULT);
|
||||
if (tmp.topic == nullptr) {
|
||||
LOG_ERROR("0x2130 Create Topic %1 Failed!", topicName);
|
||||
d->topics_.erase(topicName);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
TopicInfo &tmp = d->topics_[topicName];
|
||||
tmp.publishers_[publisherID] = PublisherInfo();
|
||||
tmp.publishers_[publisherID].publisher = d->participant_->create_publisher(
|
||||
XN_DDS::PUBLISHER_QOS_DEFAULT, nullptr);
|
||||
if (tmp.publishers_[publisherID].publisher == nullptr) {
|
||||
LOG_ERROR("0x2131 Create Publisher %1 for Topic %2 Failed!", publisherID,
|
||||
topicName);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// 设置数据写入器QoS策略
|
||||
XNDDSDataWriterQos dataWriterQos;
|
||||
// 设置数据写入器的历史记录策略, 只保留最新的一个数据
|
||||
// dataWriterQos.history().kind = FAST_DDS_MACRO::KEEP_LAST_HISTORY_QOS;
|
||||
// dataWriterQos.history().depth = 1;
|
||||
// 设置数据写入器的可靠性策略, 使用最佳努力可靠性
|
||||
// dataWriterQos.reliability().kind =
|
||||
// FAST_DDS_MACRO::BEST_EFFORT_RELIABILITY_QOS; 设置数据写入器的持久性策略,
|
||||
// 使用瞬态本地持久性
|
||||
dataWriterQos.durability().kind = XN_DDS::VOLATILE_DURABILITY_QOS;
|
||||
// 设置数据写入器的生命周期策略, 设置为5秒
|
||||
dataWriterQos.lifespan().duration = XN_DDS::Duration_t(5, 0);
|
||||
|
||||
tmp.publishers_[publisherID].dataWriter =
|
||||
tmp.publishers_[publisherID].publisher->create_datawriter(
|
||||
tmp.topic, dataWriterQos, nullptr);
|
||||
if (tmp.publishers_[publisherID].dataWriter == nullptr) {
|
||||
LOG_ERROR("0x2132 Create DataWriter %1 for Topic %2 Failed!", publisherID,
|
||||
topicName);
|
||||
return nullptr;
|
||||
}
|
||||
LOG_INFO("0x2133 Create Publisher %1 for Topic %2 Success!", publisherID,
|
||||
topicName);
|
||||
return tmp.publishers_[publisherID].dataWriter;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void RegisterSubscriber(const XN_STRING &topicName, XN_UINT32 subscriberID,
|
||||
XNDDSCallBack<typename T::type> fun) {
|
||||
T_D();
|
||||
std::lock_guard<std::mutex> lock(d->mutex_);
|
||||
if (d->topics_.find(topicName) == d->topics_.end()) {
|
||||
d->topics_[topicName] = TopicInfo();
|
||||
TopicInfo &tmp = d->topics_[topicName];
|
||||
XNDDSTypeSupport typeSupport(new T());
|
||||
typeSupport.register_type(d->participant_);
|
||||
tmp.topic = d->participant_->create_topic(
|
||||
topicName, typeSupport.get_type_name(), XN_DDS::TOPIC_QOS_DEFAULT);
|
||||
if (tmp.topic == nullptr) {
|
||||
LOG_ERROR("0x2130 Create Topic %1 Failed!", topicName);
|
||||
d->topics_.erase(topicName);
|
||||
return;
|
||||
}
|
||||
}
|
||||
TopicInfo &tmp = d->topics_[topicName];
|
||||
tmp.subscribers_[subscriberID] = SubscriberInfo();
|
||||
tmp.subscribers_[subscriberID].subscriber =
|
||||
d->participant_->create_subscriber(XN_DDS::SUBSCRIBER_QOS_DEFAULT,
|
||||
nullptr);
|
||||
if (tmp.subscribers_[subscriberID].subscriber == nullptr) {
|
||||
LOG_ERROR("0x2135 Create Subscriber %1 for Topic %2 Failed!",
|
||||
subscriberID, topicName);
|
||||
}
|
||||
XN_DDS::DataReaderQos dataReaderQos;
|
||||
dataReaderQos.durability().kind = XN_DDS::VOLATILE_DURABILITY_QOS;
|
||||
XN_DDS::DataReaderListener *listener =
|
||||
new DataReaderListenerImpl<typename T::type>(fun);
|
||||
tmp.subscribers_[subscriberID].dataReader =
|
||||
tmp.subscribers_[subscriberID].subscriber->create_datareader(
|
||||
tmp.topic, dataReaderQos, listener);
|
||||
if (tmp.subscribers_[subscriberID].dataReader == nullptr) {
|
||||
LOG_ERROR("0x2136 Create DataReader %1 for Topic %2 Failed!",
|
||||
subscriberID, topicName);
|
||||
}
|
||||
LOG_INFO("0x2137 Create Subscriber %1 for Topic %2 Success!", subscriberID,
|
||||
topicName);
|
||||
}
|
||||
};
|
||||
} // namespace XNSim
|
7
XNCore_Win/XNEventManager/CMakeLists.txt
Normal file
7
XNCore_Win/XNEventManager/CMakeLists.txt
Normal file
@ -0,0 +1,7 @@
|
||||
set(XNEVENTMANAGER_SOURCES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XNEventManager.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XNEventManager_p.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XNEventManager.cpp
|
||||
)
|
||||
|
||||
set(XNCORE_SOURCES ${XNCORE_SOURCES} ${XNEVENTMANAGER_SOURCES} PARENT_SCOPE)
|
296
XNCore_Win/XNEventManager/XNEventManager.cpp
Normal file
296
XNCore_Win/XNEventManager/XNEventManager.cpp
Normal file
@ -0,0 +1,296 @@
|
||||
#include "XNEventManager.h"
|
||||
#include "XNEventManager_p.h"
|
||||
#include "XNFramework.h"
|
||||
#include <algorithm>
|
||||
#include <thread>
|
||||
|
||||
|
||||
// 构造函数
|
||||
XNEventManager::XNEventManager()
|
||||
: XNBaseFrameObject(new XNEventManagerPrivate()) {
|
||||
// 设置唯一标识符
|
||||
SetUniqueId(enumValue(XNCoreObjectID::EventManager));
|
||||
// 设置对象名称
|
||||
SetObjectName("XNEventManager");
|
||||
}
|
||||
|
||||
// 析构函数
|
||||
XNEventManager::~XNEventManager() {
|
||||
T_D();
|
||||
d->running = false;
|
||||
d->taskCond.notify_all();
|
||||
for (auto &thread : d->workerThreads) {
|
||||
if (thread.joinable()) {
|
||||
thread.join();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 保护构造函数实现
|
||||
XNEventManager::XNEventManager(PrivateType *p) : XNBaseFrameObject(p) {}
|
||||
|
||||
// 修改注册事件处理器的实现
|
||||
int XNEventManager::RegisterEventHandler(const std::string &eventName,
|
||||
XNEventCallback callback,
|
||||
uint32_t objectId, bool async,
|
||||
XNEvent::Priority priority) {
|
||||
T_D();
|
||||
if (eventName.empty() || !callback) {
|
||||
LOG_WARNING("Invalid event name or callback!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> locker(d->eventMutex);
|
||||
|
||||
// 生成新的本地ID
|
||||
d->localIdCounter = (d->localIdCounter + 1) & 0xFFFF;
|
||||
if (d->localIdCounter == 0)
|
||||
d->localIdCounter = 1; // 避免为0
|
||||
|
||||
// 创建处理器信息
|
||||
EventHandlerInfo handlerInfo;
|
||||
handlerInfo.callback = callback;
|
||||
handlerInfo.objectId = objectId;
|
||||
handlerInfo.localId = d->localIdCounter;
|
||||
handlerInfo.isAsync = async;
|
||||
handlerInfo.priority = priority;
|
||||
// 计算全局处理器ID
|
||||
int handlerId = handlerInfo.GetHandlerId();
|
||||
|
||||
// 添加处理器信息到事件列表
|
||||
d->eventHandlers[eventName].push_back(handlerInfo);
|
||||
// 添加反向映射
|
||||
d->handlerToEvent[handlerId] = eventName;
|
||||
|
||||
LOG_INFO("Registered " + std::string(async ? "async" : "sync") +
|
||||
" event handler for event: " + eventName + ", handler ID: " +
|
||||
std::to_string(handlerId) + " (object: " + std::to_string(objectId) +
|
||||
", local: " + std::to_string(d->localIdCounter) + ")");
|
||||
return handlerId;
|
||||
}
|
||||
|
||||
// 修改移除事件处理器的实现
|
||||
bool XNEventManager::RemoveEventHandler(const std::string &eventName,
|
||||
int handlerId) {
|
||||
T_D();
|
||||
std::lock_guard<std::mutex> locker(d->eventMutex);
|
||||
|
||||
// 如果指定了事件名称,先验证事件是否存在
|
||||
if (!eventName.empty()) {
|
||||
auto it = d->eventHandlers.find(eventName);
|
||||
if (it == d->eventHandlers.end()) {
|
||||
LOG_WARNING("Event " + eventName + " not found!");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 查找并移除指定的处理器
|
||||
auto &handlers = it->second;
|
||||
auto handlerIt = std::find_if(handlers.begin(), handlers.end(),
|
||||
[handlerId](const EventHandlerInfo &info) {
|
||||
return info.GetHandlerId() == handlerId;
|
||||
});
|
||||
|
||||
if (handlerIt != handlers.end()) {
|
||||
handlers.erase(handlerIt);
|
||||
d->handlerToEvent.erase(handlerId);
|
||||
LOG_INFO("Removed handler ID " + std::to_string(handlerId) +
|
||||
" from event: " + eventName);
|
||||
|
||||
// 如果事件没有处理器了,移除整个事件
|
||||
if (handlers.empty()) {
|
||||
d->eventHandlers.erase(it);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
LOG_WARNING("Handler ID " + std::to_string(handlerId) +
|
||||
" not found in event: " + eventName);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 如果没有指定事件名称,使用反向映射查找
|
||||
auto eventIt = d->handlerToEvent.find(handlerId);
|
||||
if (eventIt != d->handlerToEvent.end()) {
|
||||
std::string eventToRemove = eventIt->second;
|
||||
auto &handlers = d->eventHandlers[eventToRemove];
|
||||
|
||||
auto handlerIt = std::find_if(handlers.begin(), handlers.end(),
|
||||
[handlerId](const EventHandlerInfo &info) {
|
||||
return info.GetHandlerId() == handlerId;
|
||||
});
|
||||
|
||||
if (handlerIt != handlers.end()) {
|
||||
handlers.erase(handlerIt);
|
||||
d->handlerToEvent.erase(handlerId);
|
||||
LOG_INFO("Removed handler ID " + std::to_string(handlerId) +
|
||||
" from event: " + eventToRemove);
|
||||
|
||||
// 如果事件没有处理器了,移除整个事件
|
||||
if (handlers.empty()) {
|
||||
d->eventHandlers.erase(eventToRemove);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
LOG_WARNING("Handler ID " + std::to_string(handlerId) + " not found!");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 修改触发事件的实现
|
||||
void XNEventManager::TriggerEvent(const std::string &eventName,
|
||||
const std::any &eventData, bool forceAsync,
|
||||
XNEvent::Priority priority) {
|
||||
T_D();
|
||||
std::list<EventHandlerInfo> handlers;
|
||||
{
|
||||
std::lock_guard<std::mutex> locker(d->eventMutex);
|
||||
auto it = d->eventHandlers.find(eventName);
|
||||
if (it == d->eventHandlers.end()) {
|
||||
return;
|
||||
}
|
||||
handlers = it->second;
|
||||
}
|
||||
|
||||
for (const auto &handler : handlers) {
|
||||
if (forceAsync || handler.isAsync) {
|
||||
if (priority == XNEvent::Priority::RealTime) {
|
||||
// 创建实时任务
|
||||
RTEventTask *task =
|
||||
new RTEventTask(eventName, eventData, handler.callback, this);
|
||||
d->rtManager.addTask(task);
|
||||
} else {
|
||||
// 普通异步任务使用线程池
|
||||
std::lock_guard<std::mutex> lock(d->taskMutex);
|
||||
d->taskQueue.push(
|
||||
new AsyncEventTask(eventName, eventData, handler.callback, this));
|
||||
d->taskCond.notify_one();
|
||||
}
|
||||
} else {
|
||||
// 同步执行
|
||||
try {
|
||||
handler.callback(eventData);
|
||||
EventProcessed(eventName, true);
|
||||
} catch (const std::exception &e) {
|
||||
LOG_ERROR("Exception in handler " +
|
||||
std::to_string(handler.GetHandlerId()) + " for event " +
|
||||
eventName + ": " + e.what());
|
||||
EventProcessed(eventName, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void XNEventManager::SetMaxThreadCount(int count) {
|
||||
T_D();
|
||||
std::lock_guard<std::mutex> lock(d->taskMutex);
|
||||
// 停止现有线程
|
||||
d->running = false;
|
||||
d->taskCond.notify_all();
|
||||
for (auto &thread : d->workerThreads) {
|
||||
if (thread.joinable()) {
|
||||
thread.join();
|
||||
}
|
||||
}
|
||||
d->workerThreads.clear();
|
||||
|
||||
// 创建新线程
|
||||
d->running = true;
|
||||
for (int i = 0; i < count; ++i) {
|
||||
d->workerThreads.emplace_back([this, d]() {
|
||||
while (d->running) {
|
||||
BaseEventTask *task = nullptr;
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(d->taskMutex);
|
||||
d->taskCond.wait(
|
||||
lock, [this, d] { return !d->taskQueue.empty() || !d->running; });
|
||||
if (!d->running) {
|
||||
break;
|
||||
}
|
||||
task = d->taskQueue.front();
|
||||
d->taskQueue.pop();
|
||||
}
|
||||
if (task) {
|
||||
task->execute();
|
||||
delete task;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
LOG_INFO("Set thread pool max thread count to " + std::to_string(count));
|
||||
}
|
||||
|
||||
int XNEventManager::GetMaxThreadCount() const {
|
||||
T_D();
|
||||
std::lock_guard<std::mutex> lock(d->taskMutex);
|
||||
return d->workerThreads.size();
|
||||
}
|
||||
|
||||
void XNEventManager::WaitForAsyncEvents() {
|
||||
T_D();
|
||||
std::unique_lock<std::mutex> lock(d->taskMutex);
|
||||
d->taskCond.wait(lock, [this, d] { return d->taskQueue.empty(); });
|
||||
LOG_INFO("All async events have been processed");
|
||||
}
|
||||
|
||||
// 初始化事件管理器
|
||||
bool XNEventManager::Initialize() {
|
||||
T_D();
|
||||
// 配置普通线程池
|
||||
SetMaxThreadCount(std::thread::hardware_concurrency());
|
||||
|
||||
// 配置实时线程池
|
||||
SetRTThreadPoolConfig(2, // 最大线程数
|
||||
sched_get_priority_min(SCHED_FIFO), // 最小优先级
|
||||
sched_get_priority_max(SCHED_FIFO)); // 最大优先级
|
||||
|
||||
LOG_INFO("XNEventManager Initialize Success!");
|
||||
d->_status = XNFrameObjectStatus::Initialized;
|
||||
return true;
|
||||
}
|
||||
|
||||
// 准备执行
|
||||
bool XNEventManager::PrepareForExecute() {
|
||||
T_D();
|
||||
d->_status = XNFrameObjectStatus::Ready;
|
||||
LOG_INFO("XNEventManager is prepared!");
|
||||
return true;
|
||||
}
|
||||
|
||||
void XNEventManager::SetRTThreadPoolConfig(int maxThreads, int minPriority,
|
||||
int maxPriority) {
|
||||
T_D();
|
||||
d->rtManager.stop();
|
||||
|
||||
XNFrameworkPtr framework = GetFramework();
|
||||
if (!framework) {
|
||||
LOG_WARNING("XNFramework is nullptr!");
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t cpuAffinity = framework->GetCpuAffinity();
|
||||
|
||||
// 找到最后一个可用的CPU
|
||||
int lastCpu = -1;
|
||||
for (int i = 0; i < 32; i++) { // 假设最多32个CPU
|
||||
if (cpuAffinity & (1u << i)) {
|
||||
lastCpu = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (lastCpu < 0) {
|
||||
LOG_WARNING("No available CPU found in affinity mask, using default CPU 1");
|
||||
lastCpu = 1;
|
||||
} else {
|
||||
LOG_INFO("RT thread bound to CPU " + std::to_string(lastCpu));
|
||||
}
|
||||
|
||||
d->rtManager.start(maxThreads, maxPriority, lastCpu);
|
||||
}
|
||||
|
||||
void XNEventManager::EventProcessed(const std::string &eventName,
|
||||
bool success) {
|
||||
T_D();
|
||||
// 这里可以添加事件处理完成的回调逻辑
|
||||
// LOG_INFO("Event " + eventName + " processed " + (success ? "successfully" :
|
||||
// "with error"));
|
||||
}
|
80
XNCore_Win/XNEventManager/XNEventManager.h
Normal file
80
XNCore_Win/XNEventManager/XNEventManager.h
Normal file
@ -0,0 +1,80 @@
|
||||
#pragma once
|
||||
#include <XNBaseFrameObject/XNBaseFrameObject.h>
|
||||
|
||||
namespace XNSim {
|
||||
// 事件优先级定义
|
||||
namespace XNEvent {
|
||||
enum class Priority {
|
||||
RealTime = 0, // 实时优先级
|
||||
High = 1, // 高优先级
|
||||
Normal = 2, // 普通优先级
|
||||
Low = 3 // 低优先级
|
||||
};
|
||||
}
|
||||
|
||||
// 前向声明私有类
|
||||
struct XNEventManagerPrivate;
|
||||
|
||||
// 事件管理器类,继承自XNBaseFrameObject
|
||||
class XNEventManager : public XNBaseFrameObject {
|
||||
XN_METATYPE(XNEventManager, XNBaseFrameObject)
|
||||
XN_DECLARE_PRIVATE(XNEventManager)
|
||||
public:
|
||||
// 构造函数,创建事件管理器实例
|
||||
XNEventManager();
|
||||
// 析构函数
|
||||
~XNEventManager();
|
||||
|
||||
// 注册事件处理器
|
||||
// @param eventName: 事件名称
|
||||
// @param callback: 事件处理回调函数
|
||||
// @param objectId: 对象ID
|
||||
// @param async: 是否异步处理该事件
|
||||
// @param priority: 事件优先级
|
||||
// @return: 返回处理器ID,失败返回-1
|
||||
XN_INT32
|
||||
RegisterEventHandler(const XN_STRING &eventName, XNEventCallback callback,
|
||||
XN_UINT32 objectId, XN_BOOL async = false,
|
||||
XNEvent::Priority priority = XNEvent::Priority::Normal);
|
||||
// 移除事件处理器
|
||||
// @param eventName: 事件名称
|
||||
// @param handlerId: 处理器ID
|
||||
// @return: 移除是否成功
|
||||
XN_BOOL RemoveEventHandler(const XN_STRING &eventName, XN_INT32 handlerId);
|
||||
// 触发指定事件
|
||||
// @param eventName: 要触发的事件名称
|
||||
// @param eventData: 事件携带的数据
|
||||
// @param forceAsync: 强制异步处理
|
||||
// @param priority: 事件优先级
|
||||
void TriggerEvent(const XN_STRING &eventName,
|
||||
const XN_ANY &eventData = XN_ANY(),
|
||||
XN_BOOL forceAsync = false,
|
||||
XNEvent::Priority priority = XNEvent::Priority::Normal);
|
||||
|
||||
// 设置线程池最大线程数
|
||||
void SetMaxThreadCount(XN_UINT32 count);
|
||||
|
||||
// 获取线程池最大线程数
|
||||
XN_UINT32 GetMaxThreadCount() const;
|
||||
|
||||
// 等待所有异步事件处理完成
|
||||
void WaitForAsyncEvents();
|
||||
|
||||
// 设置实时线程池参数
|
||||
void SetRTThreadPoolConfig(XN_UINT32 maxThreads, XN_UINT32 minPriority,
|
||||
XN_UINT32 maxPriority);
|
||||
|
||||
// 事件处理完成回调
|
||||
void EventProcessed(const XN_STRING &eventName, XN_BOOL success);
|
||||
|
||||
protected:
|
||||
// 保护构造函数,用于继承实现
|
||||
XNEventManager(PrivateType *p);
|
||||
|
||||
public:
|
||||
// 初始化事件管理器
|
||||
virtual XN_BOOL Initialize() override;
|
||||
// 准备执行
|
||||
virtual XN_BOOL PrepareForExecute() override;
|
||||
};
|
||||
} // namespace XNSim
|
242
XNCore_Win/XNEventManager/XNEventManager_p.h
Normal file
242
XNCore_Win/XNEventManager/XNEventManager_p.h
Normal file
@ -0,0 +1,242 @@
|
||||
#pragma once
|
||||
#include "XNBaseFrameObject_p.h"
|
||||
#include "XNEventManager.h"
|
||||
#include <functional>
|
||||
#include <sys/types.h>
|
||||
#include <bits/pthreadtypes.h>
|
||||
#include <bits/sched.h>
|
||||
#include <vector>
|
||||
#include <queue>
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
#include <string>
|
||||
#include <any>
|
||||
#include <map>
|
||||
#include <list>
|
||||
|
||||
// 事件处理器信息结构
|
||||
struct EventHandlerInfo {
|
||||
std::function<void(const std::any &)> callback; // 回调函数
|
||||
uint32_t objectId; // 对象ID
|
||||
uint32_t localId; // 本地ID
|
||||
bool isAsync; // 是否异步处理
|
||||
XNEvent::Priority priority; // 事件优先级
|
||||
uint32_t threadPriority; // 线程优先级
|
||||
|
||||
// 获取全局处理器ID
|
||||
uint32_t GetHandlerId() const { return (objectId << 16) | (localId & 0xFFFF); }
|
||||
|
||||
// 从全局处理器ID中提取对象ID
|
||||
static uint32_t GetObjectId(uint32_t handlerId) { return handlerId >> 16; }
|
||||
|
||||
// 从全局处理器ID中提取本地ID
|
||||
static uint32_t GetLocalId(uint32_t handlerId) { return handlerId & 0xFFFF; }
|
||||
};
|
||||
|
||||
// 事件任务基类
|
||||
class BaseEventTask
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief 构造函数
|
||||
* @param name 事件名称
|
||||
* @param data 事件数据
|
||||
* @param callback 回调函数
|
||||
* @param manager 事件管理器指针
|
||||
*/
|
||||
BaseEventTask(const std::string &name, const std::any &data,
|
||||
std::function<void(const std::any &)> callback, XNEventManager *manager)
|
||||
: eventName(name), eventData(data), eventCallback(callback), eventManager(manager)
|
||||
{
|
||||
}
|
||||
virtual ~BaseEventTask() = default;
|
||||
|
||||
/**
|
||||
* @brief 执行任务
|
||||
*/
|
||||
virtual void execute() = 0;
|
||||
|
||||
protected:
|
||||
std::string eventName;
|
||||
std::any eventData;
|
||||
std::function<void(const std::any &)> eventCallback;
|
||||
XNEventManager *eventManager;
|
||||
};
|
||||
|
||||
// 异步事件任务
|
||||
class AsyncEventTask : public BaseEventTask
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief 构造函数
|
||||
* @param name 事件名称
|
||||
* @param data 事件数据
|
||||
* @param callback 回调函数
|
||||
* @param manager 事件管理器指针
|
||||
*/
|
||||
AsyncEventTask(const std::string &name, const std::any &data,
|
||||
std::function<void(const std::any &)> callback, XNEventManager *manager)
|
||||
: BaseEventTask(name, data, callback, manager)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 执行任务
|
||||
*/
|
||||
void execute() override
|
||||
{
|
||||
try {
|
||||
eventCallback(eventData);
|
||||
if (eventManager) {
|
||||
eventManager->EventProcessed(eventName, true);
|
||||
}
|
||||
} catch (const std::exception &e) {
|
||||
LOG_ERROR("Async event handler exception for " + eventName + ": " + e.what());
|
||||
if (eventManager) {
|
||||
eventManager->EventProcessed(eventName, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 实时事件任务
|
||||
class RTEventTask : public BaseEventTask
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief 构造函数
|
||||
* @param name 事件名称
|
||||
* @param data 事件数据
|
||||
* @param callback 回调函数
|
||||
* @param manager 事件管理器指针
|
||||
*/
|
||||
RTEventTask(const std::string &name, const std::any &data,
|
||||
std::function<void(const std::any &)> callback, XNEventManager *manager)
|
||||
: BaseEventTask(name, data, callback, manager)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 执行任务
|
||||
*/
|
||||
void execute() override
|
||||
{
|
||||
try {
|
||||
eventCallback(eventData);
|
||||
if (eventManager) {
|
||||
eventManager->EventProcessed(eventName, true);
|
||||
}
|
||||
} catch (const std::exception &e) {
|
||||
LOG_ERROR("RT event handler exception for " + eventName + ": " + e.what());
|
||||
if (eventManager) {
|
||||
eventManager->EventProcessed(eventName, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 实时线程管理器
|
||||
class RTThreadManager
|
||||
{
|
||||
public:
|
||||
RTThreadManager() : running(false) {}
|
||||
~RTThreadManager() { stop(); }
|
||||
|
||||
void start(int threadCount, int priority, int cpuCore)
|
||||
{
|
||||
running = true;
|
||||
for (int i = 0; i < threadCount; ++i) {
|
||||
pthread_t thread;
|
||||
pthread_create(&thread, nullptr, threadFunction, this);
|
||||
|
||||
// 设置线程优先级
|
||||
struct sched_param param;
|
||||
param.sched_priority = priority;
|
||||
pthread_setschedparam(thread, SCHED_FIFO, ¶m);
|
||||
|
||||
// 设置CPU亲和性
|
||||
cpu_set_t cpuset;
|
||||
CPU_ZERO(&cpuset);
|
||||
CPU_SET(cpuCore, &cpuset);
|
||||
pthread_setaffinity_np(thread, sizeof(cpu_set_t), &cpuset);
|
||||
|
||||
threads.push_back(thread);
|
||||
}
|
||||
}
|
||||
|
||||
void stop()
|
||||
{
|
||||
running = false;
|
||||
taskCond.notify_all();
|
||||
for (auto thread : threads) {
|
||||
pthread_join(thread, nullptr);
|
||||
}
|
||||
threads.clear();
|
||||
}
|
||||
|
||||
void addTask(RTEventTask *task)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(taskMutex);
|
||||
taskQueue.push(task);
|
||||
taskCond.notify_one();
|
||||
}
|
||||
|
||||
private:
|
||||
static void *threadFunction(void *arg)
|
||||
{
|
||||
auto manager = static_cast<RTThreadManager *>(arg);
|
||||
manager->processTask();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void processTask()
|
||||
{
|
||||
while (running) {
|
||||
RTEventTask *task = nullptr;
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(taskMutex);
|
||||
taskCond.wait(lock, [this] { return !taskQueue.empty() || !running; });
|
||||
if (!running)
|
||||
break;
|
||||
task = taskQueue.front();
|
||||
taskQueue.pop();
|
||||
}
|
||||
if (task) {
|
||||
task->execute();
|
||||
delete task;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool running;
|
||||
std::vector<pthread_t> threads;
|
||||
std::queue<RTEventTask *> taskQueue;
|
||||
std::mutex taskMutex;
|
||||
std::condition_variable taskCond;
|
||||
};
|
||||
|
||||
// 事件管理器的私有实现类
|
||||
struct XNEventManagerPrivate : public XNBaseFrameObjectPrivate {
|
||||
// 存储事件及其对应的处理器信息列表
|
||||
// key: 事件名称
|
||||
// value: 该事件对应的所有处理器信息列表
|
||||
std::map<std::string, std::list<EventHandlerInfo>> eventHandlers;
|
||||
|
||||
// 处理器ID到事件名称的反向映射,用于快速查找
|
||||
std::map<int, std::string> handlerToEvent;
|
||||
|
||||
// 本地ID计数器
|
||||
int localIdCounter = 0;
|
||||
|
||||
// 互斥锁,用于保护事件处理器表的线程安全访问
|
||||
std::mutex eventMutex;
|
||||
|
||||
// 线程池相关
|
||||
std::vector<std::thread> workerThreads;
|
||||
std::queue<BaseEventTask *> taskQueue;
|
||||
std::mutex taskMutex;
|
||||
std::condition_variable taskCond;
|
||||
bool running = true;
|
||||
|
||||
RTThreadManager rtManager;
|
||||
};
|
7
XNCore_Win/XNFramework/CMakeLists.txt
Normal file
7
XNCore_Win/XNFramework/CMakeLists.txt
Normal file
@ -0,0 +1,7 @@
|
||||
set(XNFRAMEWORK_SOURCES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XNFramework.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XNFramework_p.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XNFramework.cpp
|
||||
)
|
||||
|
||||
set(XNCORE_SOURCES ${XNCORE_SOURCES} ${XNFRAMEWORK_SOURCES} PARENT_SCOPE)
|
213
XNCore_Win/XNFramework/XNFramework.cpp
Normal file
213
XNCore_Win/XNFramework/XNFramework.cpp
Normal file
@ -0,0 +1,213 @@
|
||||
#include "XNFramework.h"
|
||||
#include "XNFramework_p.h"
|
||||
|
||||
#include "XNConfigManager/XNConfigManager.h"
|
||||
#include "XNDDSManager/XNDDSManager.h"
|
||||
#include "XNEventManager/XNEventManager.h"
|
||||
#include "XNModelManager/XNModelManager.h"
|
||||
#include "XNServiceManager/XNServiceManager.h"
|
||||
#include "XNThreadManager/XNThreadManager.h"
|
||||
#include "XNTimeManager/XNTimeManager.h"
|
||||
|
||||
namespace XNSim {
|
||||
XNFramework::XNFramework() : XNObject(new XNFrameworkPrivate()) {
|
||||
SetObjectName("XNFramework");
|
||||
SetUniqueId(1);
|
||||
T_D();
|
||||
d->timeManager = std::make_shared<XNTimeManager>();
|
||||
d->threadManager = std::make_shared<XNThreadManager>();
|
||||
d->configManager = std::make_shared<XNConfigManager>();
|
||||
d->ddsManager = std::make_shared<XNDDSManager>();
|
||||
d->modelManager = std::make_shared<XNModelManager>();
|
||||
d->serviceManager = std::make_shared<XNServiceManager>();
|
||||
d->eventManager = std::make_shared<XNEventManager>();
|
||||
}
|
||||
|
||||
XNFramework::XNFramework(PrivateType *p) : XNObject(p) {}
|
||||
|
||||
XNFramework::~XNFramework() {}
|
||||
|
||||
XN_STRING XNFramework::GetWorkPath() {
|
||||
T_D();
|
||||
return d->workPath;
|
||||
}
|
||||
|
||||
void XNFramework::SetWorkPath(const XN_STRING &workPath) {
|
||||
T_D();
|
||||
d->workPath = workPath;
|
||||
}
|
||||
|
||||
XN_STRING XNFramework::GetModelPath() {
|
||||
T_D();
|
||||
return d->modelPath;
|
||||
}
|
||||
|
||||
void XNFramework::SetModelPath(const XN_STRING &modelPath) {
|
||||
T_D();
|
||||
d->modelPath = modelPath;
|
||||
}
|
||||
|
||||
XN_STRING XNFramework::GetServicePath() {
|
||||
T_D();
|
||||
return d->servicePath;
|
||||
}
|
||||
|
||||
void XNFramework::SetServicePath(const XN_STRING &servicePath) {
|
||||
T_D();
|
||||
d->servicePath = servicePath;
|
||||
}
|
||||
|
||||
XN_UINT32 XNFramework::GetCpuAffinity() {
|
||||
T_D();
|
||||
return d->uCpuAffinity;
|
||||
}
|
||||
|
||||
void XNFramework::SetCpuAffinity(XN_UINT32 cpuAffinity) {
|
||||
T_D();
|
||||
d->uCpuAffinity = cpuAffinity;
|
||||
}
|
||||
|
||||
XN_BOOL XNFramework::Initialize(XN_UINT32 initialType) {
|
||||
T_D();
|
||||
LOG_INFO("D01054001:主框架正在初始化...");
|
||||
d->ddsManager->SetFramework(XN_THISPTR);
|
||||
d->timeManager->SetFramework(XN_THISPTR);
|
||||
d->threadManager->SetFramework(XN_THISPTR);
|
||||
d->configManager->SetFramework(XN_THISPTR);
|
||||
d->modelManager->SetFramework(XN_THISPTR);
|
||||
d->serviceManager->SetFramework(XN_THISPTR);
|
||||
d->eventManager->SetFramework(XN_THISPTR);
|
||||
XN_BOOL ret = d->eventManager->Initialize();
|
||||
if (!ret) {
|
||||
LOG_ERROR("B01052001:主框架初始化失败!");
|
||||
return false;
|
||||
}
|
||||
ret = d->timeManager->Initialize();
|
||||
if (!ret) {
|
||||
LOG_ERROR("B01052002:主框架初始化失败!");
|
||||
return false;
|
||||
}
|
||||
ret = d->ddsManager->Initialize();
|
||||
if (!ret) {
|
||||
LOG_ERROR("B01052003:主框架初始化失败!");
|
||||
return false;
|
||||
}
|
||||
ret = d->serviceManager->Initialize();
|
||||
if (!ret) {
|
||||
LOG_ERROR("B01052004:主框架初始化失败!");
|
||||
return false;
|
||||
}
|
||||
ret = d->threadManager->Initialize();
|
||||
if (!ret) {
|
||||
LOG_ERROR("B01052005:主框架初始化失败!");
|
||||
return false;
|
||||
}
|
||||
ret = d->modelManager->Initialize();
|
||||
if (!ret) {
|
||||
LOG_ERROR("B01052006:主框架初始化失败!");
|
||||
return false;
|
||||
}
|
||||
ret = d->configManager->Initialize();
|
||||
if (!ret) {
|
||||
LOG_ERROR("B01052007:主框架初始化失败!");
|
||||
return false;
|
||||
}
|
||||
LOG_INFO("D01054002:主框架初始化成功!");
|
||||
LOG_INFO("D01054003:开始解析构型文件 ...");
|
||||
ret = d->configManager->AnalysisScenarioXml(d->scenarioXml, initialType);
|
||||
if (!ret) {
|
||||
LOG_ERROR("B01052008:主框架解析构型文件失败!");
|
||||
return false;
|
||||
}
|
||||
LOG_INFO("D01054004:解析构型文件成功!");
|
||||
return true;
|
||||
}
|
||||
|
||||
XN_BOOL XNFramework::PrepareForExecute() {
|
||||
T_D();
|
||||
|
||||
XN_BOOL ret = d->eventManager->PrepareForExecute();
|
||||
if (!ret) {
|
||||
LOG_ERROR("XNFramework PrepareForExecute Failed!");
|
||||
return false;
|
||||
}
|
||||
ret = d->timeManager->PrepareForExecute();
|
||||
if (!ret) {
|
||||
LOG_ERROR("XNFramework PrepareForExecute Failed!");
|
||||
return false;
|
||||
}
|
||||
ret = d->ddsManager->PrepareForExecute();
|
||||
if (!ret) {
|
||||
LOG_ERROR("XNFramework PrepareForExecute Failed!");
|
||||
return false;
|
||||
}
|
||||
ret = d->serviceManager->PrepareForExecute();
|
||||
if (!ret) {
|
||||
LOG_ERROR("XNFramework PrepareForExecute Failed!");
|
||||
return false;
|
||||
}
|
||||
ret = d->threadManager->PrepareForExecute();
|
||||
if (!ret) {
|
||||
LOG_ERROR("XNFramework PrepareForExecute Failed!");
|
||||
return false;
|
||||
}
|
||||
ret = d->modelManager->PrepareForExecute();
|
||||
if (!ret) {
|
||||
LOG_ERROR("XNFramework PrepareForExecute Failed!");
|
||||
return false;
|
||||
}
|
||||
ret = d->configManager->PrepareForExecute();
|
||||
if (!ret) {
|
||||
LOG_ERROR("XNFramework PrepareForExecute Failed!");
|
||||
return false;
|
||||
}
|
||||
LOG_INFO("XNCore is prepared for execute! Simulation will start soon...");
|
||||
return true;
|
||||
}
|
||||
|
||||
void XNFramework::SetScenarioXml(const XN_STRING &scenarioXml) {
|
||||
T_D();
|
||||
d->scenarioXml = scenarioXml;
|
||||
}
|
||||
|
||||
void XNFramework::SimControl(XN_UINT32 objectId, SimControlCmd cmd) {
|
||||
T_D();
|
||||
d->timeManager->SimControl(objectId, cmd);
|
||||
d->threadManager->SimControl(objectId, cmd);
|
||||
}
|
||||
|
||||
XNTimeManagerPtr XNFramework::GetTimeManager() {
|
||||
T_D();
|
||||
return d->timeManager;
|
||||
}
|
||||
|
||||
XNThreadManagerPtr XNFramework::GetThreadManager() {
|
||||
T_D();
|
||||
return d->threadManager;
|
||||
}
|
||||
|
||||
XNConfigManagerPtr XNFramework::GetConfigManager() {
|
||||
T_D();
|
||||
return d->configManager;
|
||||
}
|
||||
|
||||
XNDDSManagerPtr XNFramework::GetDDSManager() {
|
||||
T_D();
|
||||
return d->ddsManager;
|
||||
}
|
||||
|
||||
XNEventManagerPtr XNFramework::GetEventManager() {
|
||||
T_D();
|
||||
return d->eventManager;
|
||||
}
|
||||
|
||||
XNModelManagerPtr XNFramework::GetModelManager() {
|
||||
T_D();
|
||||
return d->modelManager;
|
||||
}
|
||||
|
||||
XNServiceManagerPtr XNFramework::GetServiceManager() {
|
||||
T_D();
|
||||
return d->serviceManager;
|
||||
}
|
||||
} // namespace XNSim
|
169
XNCore_Win/XNFramework/XNFramework.h
Normal file
169
XNCore_Win/XNFramework/XNFramework.h
Normal file
@ -0,0 +1,169 @@
|
||||
/**
|
||||
* @file XNFramework.h
|
||||
* @author jinchao
|
||||
* @brief 框架类
|
||||
* @version 1.0
|
||||
* @date 2025-01-08
|
||||
*
|
||||
* @copyright Copyright (c) 2025 COMAC
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "XNObject/XNObject.h"
|
||||
|
||||
namespace XNSim {
|
||||
struct XNFrameworkPrivate;
|
||||
|
||||
/**
|
||||
* @brief 框架类
|
||||
*/
|
||||
class XNCORE_EXPORT XNFramework : public XNObject {
|
||||
/**
|
||||
* @brief 宏定义,用于禁用拷贝构造函数
|
||||
*/
|
||||
XN_METATYPE(XNFramework, XNObject)
|
||||
|
||||
/**
|
||||
* @brief 宏定义,用于声明私有数据成员
|
||||
*/
|
||||
XN_DECLARE_PRIVATE(XNFramework)
|
||||
public:
|
||||
/**
|
||||
* @brief 构造函数
|
||||
* @param parent 父对象
|
||||
*/
|
||||
XNFramework();
|
||||
|
||||
/**
|
||||
* @brief 析构函数
|
||||
*/
|
||||
virtual ~XNFramework();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief 构造函数
|
||||
* @param p 私有数据成员
|
||||
*/
|
||||
XNFramework(PrivateType *p);
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief 获取DDS管理器
|
||||
* @return DDS管理器
|
||||
*/
|
||||
XNDDSManagerPtr GetDDSManager();
|
||||
|
||||
/**
|
||||
* @brief 获取事件管理器
|
||||
* @return 事件管理器
|
||||
*/
|
||||
XNEventManagerPtr GetEventManager();
|
||||
|
||||
/**
|
||||
* @brief 获取模型管理器
|
||||
* @return 模型管理器
|
||||
*/
|
||||
XNModelManagerPtr GetModelManager();
|
||||
|
||||
/**
|
||||
* @brief 获取构型管理器
|
||||
* @return 构型管理器
|
||||
*/
|
||||
XNConfigManagerPtr GetConfigManager();
|
||||
|
||||
/**
|
||||
* @brief 获取服务管理器
|
||||
* @return 服务管理器
|
||||
*/
|
||||
XNServiceManagerPtr GetServiceManager();
|
||||
|
||||
/**
|
||||
* @brief 获取线程管理器
|
||||
* @return 线程管理器
|
||||
*/
|
||||
XNThreadManagerPtr GetThreadManager();
|
||||
|
||||
/**
|
||||
* @brief 获取时间管理器
|
||||
* @return 时间管理器
|
||||
*/
|
||||
XNTimeManagerPtr GetTimeManager();
|
||||
|
||||
/**
|
||||
* @brief 获取工作路径
|
||||
* @return 工作路径
|
||||
*/
|
||||
XN_STRING GetWorkPath();
|
||||
|
||||
/**
|
||||
* @brief 设置工作路径
|
||||
* @param workPath 工作路径
|
||||
*/
|
||||
void SetWorkPath(const XN_STRING &workPath);
|
||||
|
||||
/**
|
||||
* @brief 获取模型库路径
|
||||
* @return 模型库路径
|
||||
*/
|
||||
XN_STRING GetModelPath();
|
||||
|
||||
/**
|
||||
* @brief 设置模型库路径
|
||||
* @param modelPath 模型库路径
|
||||
*/
|
||||
void SetModelPath(const XN_STRING &modelPath);
|
||||
|
||||
/**
|
||||
* @brief 获取服务库路径
|
||||
* @return 服务库路径
|
||||
*/
|
||||
XN_STRING GetServicePath();
|
||||
|
||||
/**
|
||||
* @brief 设置服务库路径
|
||||
* @param servicePath 服务库路径
|
||||
*/
|
||||
void SetServicePath(const XN_STRING &servicePath);
|
||||
|
||||
/**
|
||||
* @brief 获取CPU亲和性
|
||||
* @return CPU亲和性
|
||||
*/
|
||||
XN_UINT32 GetCpuAffinity();
|
||||
|
||||
/**
|
||||
* @brief 设置CPU亲和性
|
||||
* @param cpuAffinity CPU亲和性
|
||||
*/
|
||||
void SetCpuAffinity(XN_UINT32 cpuAffinity);
|
||||
|
||||
/**
|
||||
* @brief 设置场景XML
|
||||
* @param scenarioXml 场景XML
|
||||
*/
|
||||
void SetScenarioXml(const XN_STRING &scenarioXml);
|
||||
|
||||
/**
|
||||
* @brief 准备执行
|
||||
* @return true: 准备成功
|
||||
* @return false: 准备失败
|
||||
*/
|
||||
bool PrepareForExecute();
|
||||
|
||||
/**
|
||||
* @brief 仿真控制
|
||||
* @param objectId 对象ID
|
||||
* @param cmd 命令
|
||||
*/
|
||||
void SimControl(XN_UINT32 objectId, SimControlCmd cmd);
|
||||
|
||||
/**
|
||||
* @brief 初始化
|
||||
* @param initialType 初始化类型
|
||||
* @return true: 初始化成功
|
||||
* @return false: 初始化失败
|
||||
*/
|
||||
XN_BOOL Initialize(XN_UINT32 initialType);
|
||||
};
|
||||
} // namespace XNSim
|
87
XNCore_Win/XNFramework/XNFramework_p.h
Normal file
87
XNCore_Win/XNFramework/XNFramework_p.h
Normal file
@ -0,0 +1,87 @@
|
||||
/**
|
||||
* @file XNFramework_p.h
|
||||
* @author jinchao
|
||||
* @brief 框架类的私有数据成员
|
||||
* @version 1.0
|
||||
* @date 2025-01-08
|
||||
*
|
||||
* @copyright Copyright (c) 2025 COMAC
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "XNObject/XNObject_p.h"
|
||||
|
||||
namespace XNSim {
|
||||
/**
|
||||
* @brief 框架类的私有数据成员
|
||||
*/
|
||||
struct XNFrameworkPrivate : public XNObjectPrivate {
|
||||
|
||||
/**
|
||||
* @brief DDS管理器
|
||||
*/
|
||||
XNDDSManagerPtr ddsManager;
|
||||
|
||||
/**
|
||||
* @brief 事件管理器
|
||||
*/
|
||||
XNEventManagerPtr eventManager;
|
||||
|
||||
/**
|
||||
* @brief 模型管理器
|
||||
*/
|
||||
XNModelManagerPtr modelManager;
|
||||
|
||||
/**
|
||||
* @brief 构型管理器
|
||||
*/
|
||||
XNConfigManagerPtr configManager;
|
||||
|
||||
/**
|
||||
* @brief 服务管理器
|
||||
*/
|
||||
XNServiceManagerPtr serviceManager;
|
||||
|
||||
/**
|
||||
* @brief 线程管理器
|
||||
*/
|
||||
XNThreadManagerPtr threadManager;
|
||||
|
||||
/**
|
||||
* @brief 时间管理器
|
||||
*/
|
||||
XNTimeManagerPtr timeManager;
|
||||
|
||||
/**
|
||||
* @brief 工作路径
|
||||
*/
|
||||
XN_STRING workPath;
|
||||
|
||||
/**
|
||||
* @brief 模型路径
|
||||
*/
|
||||
XN_STRING modelPath;
|
||||
|
||||
/**
|
||||
* @brief 服务路径
|
||||
*/
|
||||
XN_STRING servicePath;
|
||||
|
||||
/**
|
||||
* @brief CPU亲和性
|
||||
*/
|
||||
XN_UINT32 uCpuAffinity;
|
||||
|
||||
/**
|
||||
* @brief 场景XML
|
||||
*/
|
||||
XN_STRING scenarioXml;
|
||||
|
||||
/**
|
||||
* @brief 构型ID
|
||||
*/
|
||||
XN_UINT32 configId;
|
||||
};
|
||||
} // namespace XNSim
|
20
XNCore_Win/XNGlobalDefine/CMakeLists.txt
Normal file
20
XNCore_Win/XNGlobalDefine/CMakeLists.txt
Normal file
@ -0,0 +1,20 @@
|
||||
set(XNGLOBALDEFINE_SOURCES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XNByteArray.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XNCore_global.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XNDataBase.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XNDDS.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XNDefine.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XNEnum.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XNFile.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XNJson.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XNMemory.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XNMeta.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XNString.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XNThread.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XNTime.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XNType.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XNTypeTraits.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XNXml.h
|
||||
)
|
||||
|
||||
set(XNCORE_SOURCES ${XNCORE_SOURCES} ${XNGLOBALDEFINE_SOURCES} PARENT_SCOPE)
|
100
XNCore_Win/XNGlobalDefine/XNByteArray.h
Normal file
100
XNCore_Win/XNGlobalDefine/XNByteArray.h
Normal file
@ -0,0 +1,100 @@
|
||||
#pragma once
|
||||
|
||||
#include "XNCore_global.h"
|
||||
#include "XNType.h"
|
||||
#include <vector>
|
||||
|
||||
namespace XNSim {
|
||||
/**
|
||||
* @brief 自定义字节数组容器类
|
||||
* @details 提供类似QByteArray的功能,用于处理二进制数据
|
||||
*/
|
||||
class XNByteArray {
|
||||
public:
|
||||
XNByteArray() = default;
|
||||
explicit XNByteArray(XN_SIZE size) : data_(size) {}
|
||||
|
||||
/**
|
||||
* @brief 从原始数据构造
|
||||
* @param buffer 原始数据缓冲区
|
||||
* @param size 数据大小
|
||||
*/
|
||||
XNByteArray(const XN_UINT8 *buffer, XN_SIZE size)
|
||||
: data_(buffer, buffer + size) {}
|
||||
|
||||
/**
|
||||
* @brief 获取数据指针
|
||||
* @return 数据指针
|
||||
*/
|
||||
XN_UINT8 *data() { return data_.data(); }
|
||||
|
||||
/**
|
||||
* @brief 获取常量数据指针
|
||||
* @return 常量数据指针
|
||||
*/
|
||||
const XN_UINT8 *data() const { return data_.data(); }
|
||||
|
||||
/**
|
||||
* @brief 获取数据大小
|
||||
* @return 数据大小
|
||||
*/
|
||||
XN_SIZE size() const { return data_.size(); }
|
||||
|
||||
/**
|
||||
* @brief 调整大小
|
||||
* @param size 新大小
|
||||
*/
|
||||
void resize(XN_SIZE size) { data_.resize(size); }
|
||||
|
||||
/**
|
||||
* @brief 清空数据
|
||||
*/
|
||||
void clear() { data_.clear(); }
|
||||
|
||||
/**
|
||||
* @brief 追加数据
|
||||
* @param buffer 要追加的数据
|
||||
* @param size 数据大小
|
||||
*/
|
||||
void append(const XN_UINT8 *buffer, XN_SIZE size) {
|
||||
XN_SIZE oldSize = data_.size();
|
||||
data_.resize(oldSize + size);
|
||||
std::memcpy(data_.data() + oldSize, buffer, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 追加另一个XNByteArray
|
||||
* @param other 要追加的XNByteArray
|
||||
*/
|
||||
void append(const XNByteArray &other) { append(other.data(), other.size()); }
|
||||
|
||||
/**
|
||||
* @brief 获取指定位置的字节
|
||||
* @param index 索引
|
||||
* @return 字节值
|
||||
*/
|
||||
XN_UINT8 &operator[](XN_SIZE index) { return data_[index]; }
|
||||
|
||||
/**
|
||||
* @brief 获取指定位置的字节(常量版本)
|
||||
* @param index 索引
|
||||
* @return 字节值
|
||||
*/
|
||||
const XN_UINT8 &operator[](XN_SIZE index) const { return data_[index]; }
|
||||
|
||||
/**
|
||||
* @brief 检查是否为空
|
||||
* @return 是否为空
|
||||
*/
|
||||
XN_BOOL isEmpty() const { return data_.empty(); }
|
||||
|
||||
/**
|
||||
* @brief 预分配空间
|
||||
* @param size 要预分配的大小
|
||||
*/
|
||||
void reserve(XN_SIZE size) { data_.reserve(size); }
|
||||
|
||||
private:
|
||||
std::vector<XN_UINT8> data_;
|
||||
};
|
||||
} // namespace XNSim
|
42
XNCore_Win/XNGlobalDefine/XNCore_global.h
Normal file
42
XNCore_Win/XNGlobalDefine/XNCore_global.h
Normal file
@ -0,0 +1,42 @@
|
||||
#pragma once
|
||||
|
||||
// 导出宏定义
|
||||
#if defined(_WIN32)
|
||||
#if defined(XNCORE_LIBRARY)
|
||||
#define XNCORE_EXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define XNCORE_EXPORT __declspec(dllimport)
|
||||
#endif
|
||||
#elif defined(__linux__)
|
||||
#if defined(XNCORE_LIBRARY)
|
||||
#define XNCORE_EXPORT __attribute__((visibility("default")))
|
||||
#else
|
||||
#define XNCORE_EXPORT __attribute__((visibility("default")))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// 内联宏定义
|
||||
#if defined(_WIN32)
|
||||
#define FORCEINLINE __forceinline
|
||||
#else
|
||||
#define FORCEINLINE __attribute__((always_inline))
|
||||
#endif
|
||||
|
||||
// 平台相关头文件
|
||||
#if defined(_WIN32)
|
||||
#define XN_WINDOWS
|
||||
#include <windows.h>
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#elif defined(__linux__)
|
||||
#define XN_LINUX
|
||||
#include <dlfcn.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <pthread.h>
|
||||
#include <sched.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/timeb.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
76
XNCore_Win/XNGlobalDefine/XNDDS.h
Normal file
76
XNCore_Win/XNGlobalDefine/XNDDS.h
Normal file
@ -0,0 +1,76 @@
|
||||
#pragma once
|
||||
|
||||
// FastDDS头文件
|
||||
#include <fastcdr/xcdr/optional.hpp>
|
||||
#include <fastdds/dds/domain/DomainParticipant.hpp>
|
||||
#include <fastdds/dds/domain/DomainParticipantFactory.hpp>
|
||||
#include <fastdds/dds/publisher/DataWriter.hpp>
|
||||
#include <fastdds/dds/publisher/Publisher.hpp>
|
||||
#include <fastdds/dds/subscriber/DataReader.hpp>
|
||||
#include <fastdds/dds/subscriber/DataReaderListener.hpp>
|
||||
#include <fastdds/dds/subscriber/Subscriber.hpp>
|
||||
#include <fastdds/dds/topic/TypeSupport.hpp>
|
||||
#include <functional>
|
||||
|
||||
// FastDDS宏定义
|
||||
#define XN_DDS eprosima::fastdds::dds
|
||||
namespace XNSim {
|
||||
template <typename T> using XNDDSOptional = eprosima::fastcdr::optional<T>;
|
||||
|
||||
using XNDDSParticipantPtr = XN_DDS::DomainParticipant *;
|
||||
using XNDDSPublisherPtr = XN_DDS::Publisher *;
|
||||
using XNDDSSubscriberPtr = XN_DDS::Subscriber *;
|
||||
using XNDDSTopicPtr = XN_DDS::Topic *;
|
||||
using XNDDSDataWriterPtr = XN_DDS::DataWriter *;
|
||||
using XNDDSDataReaderPtr = XN_DDS::DataReader *;
|
||||
using XNDDSTypeSupport = XN_DDS::TypeSupport;
|
||||
using XNDDSDataWriterQos = XN_DDS::DataWriterQos;
|
||||
using XNDDSDataReaderQos = XN_DDS::DataReaderQos;
|
||||
using XNDDSParticipantQos = XN_DDS::DomainParticipantQos;
|
||||
using XNDDSTopicQos = XN_DDS::TopicQos;
|
||||
using XNDDSPublisherQos = XN_DDS::PublisherQos;
|
||||
using XNDDSSubscriberQos = XN_DDS::SubscriberQos;
|
||||
|
||||
using XNDDSPublisherMap = std::unordered_map<XN_STRING, XNDDSPublisherPtr>;
|
||||
using XNDDSSubscriberMap = std::unordered_map<XN_STRING, XNDDSSubscriberPtr>;
|
||||
using XNDDSDataWriterMap = std::unordered_map<XN_STRING, XNDDSDataWriterPtr>;
|
||||
|
||||
struct PublisherInfo {
|
||||
XNDDSPublisherPtr publisher;
|
||||
XNDDSDataWriterPtr dataWriter;
|
||||
};
|
||||
|
||||
struct SubscriberInfo {
|
||||
XNDDSSubscriberPtr subscriber;
|
||||
XNDDSDataReaderPtr dataReader;
|
||||
};
|
||||
|
||||
struct TopicInfo {
|
||||
XNDDSTopicPtr topic;
|
||||
XNDDSPublisherMap publishers_;
|
||||
XNDDSSubscriberMap subscribers_;
|
||||
};
|
||||
|
||||
using XNDDSTopicMap = std::unordered_map<XN_STRING, TopicInfo>;
|
||||
|
||||
template <typename T> using XNDDSCallBack = std::function<void(const T &)>;
|
||||
|
||||
template <typename T>
|
||||
class DataReaderListenerImpl : public XN_DDS::DataReaderListener {
|
||||
public:
|
||||
DataReaderListenerImpl(XNDDSCallBack<T> callback) : callback_(callback) {}
|
||||
|
||||
void on_data_available(XNDDSDataReaderPtr reader) override {
|
||||
XN_DDS::SampleInfo info;
|
||||
if (reader->take_next_sample(&data_, &info) == XN_DDS::RETCODE_OK &&
|
||||
info.valid_data) {
|
||||
callback_(data_);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
T data_;
|
||||
XNDDSCallBack<T> callback_;
|
||||
};
|
||||
|
||||
} // namespace XNSim
|
60
XNCore_Win/XNGlobalDefine/XNDataBase.h
Normal file
60
XNCore_Win/XNGlobalDefine/XNDataBase.h
Normal file
@ -0,0 +1,60 @@
|
||||
#pragma once
|
||||
|
||||
// sqlite3头文件
|
||||
#include "XNCore_global.h"
|
||||
#include "XNString.h"
|
||||
#include "XNType.h"
|
||||
#include <sqlite3.h>
|
||||
|
||||
namespace XNSim {
|
||||
using XN_DB = sqlite3;
|
||||
using XN_DB_PTR = XN_DB *;
|
||||
using XN_DB_STMT = sqlite3_stmt;
|
||||
using XN_DB_STMT_PTR = XN_DB_STMT *;
|
||||
|
||||
FORCEINLINE XN_DB_PTR openDatabase(const XN_STRING &dbPath) {
|
||||
sqlite3 *db;
|
||||
if (sqlite3_open(dbPath.c_str(), &db) != SQLITE_OK) {
|
||||
return nullptr;
|
||||
}
|
||||
return db;
|
||||
}
|
||||
|
||||
FORCEINLINE XN_INT32 closeDatabase(XN_DB_PTR db) { return sqlite3_close(db); }
|
||||
|
||||
FORCEINLINE XN_DB_STMT_PTR prepareSql(XN_DB_PTR db, const XN_STRING &sql) {
|
||||
sqlite3_stmt *stmt;
|
||||
if (sqlite3_prepare_v2(db, sql.c_str(), -1, &stmt, nullptr) != SQLITE_OK) {
|
||||
return nullptr;
|
||||
}
|
||||
return stmt;
|
||||
}
|
||||
|
||||
FORCEINLINE void finalizeSql(XN_DB_STMT_PTR stmt) { sqlite3_finalize(stmt); }
|
||||
|
||||
FORCEINLINE XN_BOOL bindText(XN_DB_STMT_PTR stmt, XN_INT32 index,
|
||||
const XN_STRING &text) {
|
||||
if (sqlite3_bind_text(stmt, index, text.c_str(), text.length(), nullptr) !=
|
||||
SQLITE_OK) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
FORCEINLINE XN_BOOL stepSql(XN_DB_STMT_PTR stmt) {
|
||||
if (sqlite3_step(stmt) != SQLITE_ROW) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
FORCEINLINE XN_STRING getStringFromSqlite3(XN_DB_STMT_PTR stmt,
|
||||
XN_INT32 column) {
|
||||
const char *text =
|
||||
reinterpret_cast<const char *>(sqlite3_column_text(stmt, column));
|
||||
if (text == nullptr) {
|
||||
return "";
|
||||
}
|
||||
return XN_STRING(text);
|
||||
}
|
||||
} // namespace XNSim
|
46
XNCore_Win/XNGlobalDefine/XNDefine.h
Normal file
46
XNCore_Win/XNGlobalDefine/XNDefine.h
Normal file
@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
|
||||
#include "XNByteArray.h"
|
||||
#include "XNCore_global.h"
|
||||
#include "XNDDS.h"
|
||||
#include "XNDataBase.h"
|
||||
#include "XNDynamicLoad.h"
|
||||
#include "XNEnum.h"
|
||||
#include "XNFile.h"
|
||||
#include "XNJson.h"
|
||||
#include "XNMemory.h"
|
||||
#include "XNMeta.h"
|
||||
#include "XNString.h"
|
||||
#include "XNThread.h"
|
||||
#include "XNTime.h"
|
||||
#include "XNType.h"
|
||||
#include "XNTypeTraits.h"
|
||||
#include "XNXml.h"
|
||||
|
||||
|
||||
// 标准库头文件
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
#include <initializer_list>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <queue>
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
|
||||
/**
|
||||
* @brief 默认基频定义,单位 Hz
|
||||
*/
|
||||
#define BASE_RUN_FREQ 100.0
|
||||
|
||||
/**
|
||||
* @brief 默认基础运行间隔定义 单位纳秒
|
||||
*/
|
||||
#define BASE_RUN_INTER (1.0E9 / BASE_RUN_FREQ)
|
||||
|
||||
#define XN_MODEL_ID_SIZE 10000
|
||||
#define XN_MODEL_ID_START 10000
|
||||
#define XN_MODEL_ID_END 19999
|
||||
#define XN_SERVICE_ID_SIZE 10000
|
||||
#define XN_SERVICE_ID_START 20000
|
||||
#define XN_SERVICE_ID_END 29999
|
49
XNCore_Win/XNGlobalDefine/XNDynamicLoad.h
Normal file
49
XNCore_Win/XNGlobalDefine/XNDynamicLoad.h
Normal file
@ -0,0 +1,49 @@
|
||||
#pragma once
|
||||
|
||||
#include "XNCore_global.h"
|
||||
#include "XNString.h"
|
||||
|
||||
namespace XNSim {
|
||||
#ifdef XN_WINDOWS
|
||||
using XN_HANDLE = HMODULE;
|
||||
using XN_FARPROC = FARPROC;
|
||||
#else
|
||||
using XN_HANDLE = void *;
|
||||
using XN_FARPROC = void *;
|
||||
#endif
|
||||
|
||||
FORCEINLINE XN_HANDLE loadLibrary(const XN_STRING &libPath) {
|
||||
#ifdef XN_WINDOWS
|
||||
return LoadLibrary(libPath.c_str());
|
||||
#else
|
||||
return dlopen(libPath.c_str(), RTLD_LAZY);
|
||||
#endif
|
||||
}
|
||||
|
||||
FORCEINLINE XN_FARPROC getSymbol(XN_HANDLE handle, const XN_STRING &symbol) {
|
||||
#ifdef XN_WINDOWS
|
||||
return GetProcAddress(handle, symbol.c_str());
|
||||
#else
|
||||
return dlsym(handle, symbol.c_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
FORCEINLINE XN_STRING LoadError() {
|
||||
#ifdef XN_WINDOWS
|
||||
return To_XNString(GetLastError());
|
||||
#else
|
||||
return To_XNString(dlerror());
|
||||
#endif
|
||||
}
|
||||
|
||||
FORCEINLINE void closeLibrary(XN_HANDLE handle) {
|
||||
#ifdef XN_WINDOWS
|
||||
FreeLibrary(handle);
|
||||
#else
|
||||
dlclose(handle);
|
||||
#endif
|
||||
|
||||
LoadError();
|
||||
}
|
||||
|
||||
} // namespace XNSim
|
142
XNCore_Win/XNGlobalDefine/XNEnum.h
Normal file
142
XNCore_Win/XNGlobalDefine/XNEnum.h
Normal file
@ -0,0 +1,142 @@
|
||||
#pragma once
|
||||
|
||||
namespace XNSim {
|
||||
/**
|
||||
* @brief 系统运行状态枚举类
|
||||
*/
|
||||
enum class RunStatus {
|
||||
/**
|
||||
* @brief 未开始
|
||||
*/
|
||||
NotStart = 0,
|
||||
/**
|
||||
* @brief 运行中
|
||||
*/
|
||||
Runing,
|
||||
/**
|
||||
* @brief 暂停
|
||||
*/
|
||||
Suspend,
|
||||
/**
|
||||
* @brief 中止
|
||||
*/
|
||||
Aborted,
|
||||
/**
|
||||
* @brief 结束
|
||||
*/
|
||||
Finished
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 仿真控制命令枚举类
|
||||
*/
|
||||
enum class SimControlCmd {
|
||||
/**
|
||||
* @brief 开始
|
||||
*/
|
||||
Start = 0,
|
||||
/**
|
||||
* @brief 继续
|
||||
*/
|
||||
Continue,
|
||||
/**
|
||||
* @brief 暂停
|
||||
*/
|
||||
Suspend,
|
||||
/**
|
||||
* @brief 中止
|
||||
*/
|
||||
Abort
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 运行频率族枚举类
|
||||
*/
|
||||
enum class FreqLevel {
|
||||
/**
|
||||
* @brief 基础频率
|
||||
*/
|
||||
BaseFreq = 0, // 120/100/60 Hz
|
||||
/**
|
||||
* @brief 半频
|
||||
*/
|
||||
HalfFreq, // 60/50/30 Hz
|
||||
/**
|
||||
* @brief 四分之一频
|
||||
*/
|
||||
QuarterFreq, // 30/25/15 Hz
|
||||
/**
|
||||
* @brief 八分之一频
|
||||
*/
|
||||
EighthFreq, // 15/12.5/7.5 Hz
|
||||
/**
|
||||
* @brief 十六分之一频
|
||||
*/
|
||||
SixteenthFreq, // 7.5/6.25/3.75 Hz
|
||||
/**
|
||||
* @brief 三十二分之一频
|
||||
*/
|
||||
ThirtyTwothFreq, // 3.75/3.125/1.875 Hz
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 框架对象状态枚举
|
||||
*/
|
||||
enum class XNFrameObjectStatus {
|
||||
/**
|
||||
* @brief 未初始化
|
||||
*/
|
||||
NotReady = 0,
|
||||
/**
|
||||
* @brief 已初始化
|
||||
*/
|
||||
Initialized,
|
||||
/**
|
||||
* @brief 已准备好
|
||||
*/
|
||||
Ready,
|
||||
/**
|
||||
* @brief 未知
|
||||
*/
|
||||
Unknown
|
||||
};
|
||||
|
||||
enum class XNCoreObjectID {
|
||||
/**
|
||||
* @brief 框架对象
|
||||
*/
|
||||
Framework = 0,
|
||||
/**
|
||||
* @brief 模型管理器
|
||||
*/
|
||||
ModelManager,
|
||||
/**
|
||||
* @brief 时间管理器
|
||||
*/
|
||||
TimeManager = 2,
|
||||
/**
|
||||
* @brief 线程管理器
|
||||
*/
|
||||
ThreadManager = 3,
|
||||
/**
|
||||
* @brief 服务管理器
|
||||
*/
|
||||
ServiceManager = 4,
|
||||
/**
|
||||
* @brief 构型管理器
|
||||
*/
|
||||
ConfigManager = 5,
|
||||
/**
|
||||
* @brief 模型管理器
|
||||
*/
|
||||
ModelManager = 6,
|
||||
/**
|
||||
* @brief 事件管理器
|
||||
*/
|
||||
EventManager = 7,
|
||||
/**
|
||||
* @brief DDS管理器
|
||||
*/
|
||||
DDSManager = 8
|
||||
};
|
||||
} // namespace XNSim
|
41
XNCore_Win/XNGlobalDefine/XNFile.h
Normal file
41
XNCore_Win/XNGlobalDefine/XNFile.h
Normal file
@ -0,0 +1,41 @@
|
||||
#pragma once
|
||||
|
||||
#include "XNCore_global.h"
|
||||
#include "XNString.h"
|
||||
#include "XNType.h"
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
|
||||
namespace XNSim {
|
||||
using XN_PATH = std::filesystem::path;
|
||||
// 流相关类型别名
|
||||
using XN_OFSTREAM = std::ofstream;
|
||||
using XN_IFSTREAM = std::ifstream;
|
||||
using XN_FSTREAM = std::fstream;
|
||||
|
||||
FORCEINLINE XN_PATH getCurrentPath() { return std::filesystem::current_path(); }
|
||||
|
||||
FORCEINLINE bool isExist(const XN_PATH &path) {
|
||||
return std::filesystem::exists(path);
|
||||
}
|
||||
|
||||
FORCEINLINE bool isDirectory(const XN_PATH &path) {
|
||||
return std::filesystem::is_directory(path);
|
||||
}
|
||||
|
||||
FORCEINLINE void createDirectory(const XN_PATH &path) {
|
||||
std::filesystem::create_directories(path);
|
||||
}
|
||||
|
||||
FORCEINLINE XN_STRING getFileNameWithoutExt(const XN_STRING &path) {
|
||||
XN_SIZE lastDot = path.find_last_of('.');
|
||||
if (lastDot != XN_STRING::npos) {
|
||||
return path.substr(0, lastDot);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
FORCEINLINE XN_STRING getEnv(const XN_STRING &name) {
|
||||
return std::getenv(name.c_str());
|
||||
}
|
||||
} // namespace XNSim
|
17
XNCore_Win/XNGlobalDefine/XNJson.h
Normal file
17
XNCore_Win/XNGlobalDefine/XNJson.h
Normal file
@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
// json头文件
|
||||
#include "XNCore_global.h"
|
||||
#include "XNString.h"
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
namespace XNSim {
|
||||
// json类型别名
|
||||
using XN_JSON = nlohmann::json;
|
||||
|
||||
FORCEINLINE XN_JSON parseJson(const XN_STRING &jsonStr) {
|
||||
return XN_JSON::parse(jsonStr);
|
||||
}
|
||||
|
||||
FORCEINLINE XN_STRING toJson(const XN_JSON &json) { return json.dump(); }
|
||||
} // namespace XNSim
|
42
XNCore_Win/XNGlobalDefine/XNMemory.h
Normal file
42
XNCore_Win/XNGlobalDefine/XNMemory.h
Normal file
@ -0,0 +1,42 @@
|
||||
#pragma once
|
||||
|
||||
#include "XNCore_global.h"
|
||||
#include <memory>
|
||||
|
||||
namespace XNSim {
|
||||
template <typename T>
|
||||
using XN_ENABLE_SHARED_FROM_THIS = std::enable_shared_from_this<T>;
|
||||
|
||||
// 静态指针类型转换辅助函数
|
||||
template <class ToType, class FromType>
|
||||
FORCEINLINE ToType XNStaticCastHelper(const FromType &from) {
|
||||
return std::static_pointer_cast<typename ToType::element_type>(from);
|
||||
}
|
||||
|
||||
// 动态指针类型转换辅助函数
|
||||
template <class ToType, class FromType>
|
||||
FORCEINLINE ToType XNCastHelper(const FromType &from) {
|
||||
return std::dynamic_pointer_cast<typename ToType::element_type>(from);
|
||||
}
|
||||
|
||||
} // namespace XNSim
|
||||
|
||||
// 静态类型转换宏
|
||||
#define XN_CAST(from, to) XNStaticCastHelper<to>(from)
|
||||
|
||||
// 获取当前对象的智能指针
|
||||
#define XN_THISPTR std::static_pointer_cast<ThisType>(shared_from_this())
|
||||
|
||||
// 类智能指针声明宏
|
||||
#define XNCLASS_PTR_DECLARE(a) \
|
||||
using a##Ptr = std::shared_ptr<class a>; \
|
||||
using a##WPtr = std::weak_ptr<class a>; \
|
||||
using a##UPtr = std::unique_ptr<class a>; \
|
||||
using a##ConsPtr = std::shared_ptr<const class a>;
|
||||
|
||||
// 结构体智能指针声明宏
|
||||
#define XNSTRUCT_PTR_DECLARE(a) \
|
||||
using a##Ptr = std::shared_ptr<struct a>; \
|
||||
using a##WPtr = std::weak_ptr<struct a>; \
|
||||
using a##UPtr = std::unique_ptr<struct a>; \
|
||||
using a##ConsPtr = std::shared_ptr<const struct a>;
|
45
XNCore_Win/XNGlobalDefine/XNMeta.h
Normal file
45
XNCore_Win/XNGlobalDefine/XNMeta.h
Normal file
@ -0,0 +1,45 @@
|
||||
#pragma once
|
||||
|
||||
#include "XNCore_global.h"
|
||||
|
||||
namespace XNSim {
|
||||
// 空类宏
|
||||
struct XNNullClass {};
|
||||
} // namespace XNSim
|
||||
|
||||
// 禁止拷贝构造和赋值宏
|
||||
#define XN_NOCOPYABLE(Class) \
|
||||
public: \
|
||||
using NoCopyable = Class; \
|
||||
\
|
||||
private: \
|
||||
Class(const Class &) = delete; \
|
||||
Class &operator=(const Class &) = delete;
|
||||
|
||||
// 声明私有类宏
|
||||
#define XN_DECLARE_PRIVATE(Class) \
|
||||
XN_NOCOPYABLE(Class) \
|
||||
protected: \
|
||||
friend class Class##Private; \
|
||||
inline Class##Private *GetPP() const { \
|
||||
return reinterpret_cast<Class##Private *>(_Private_Ptr); \
|
||||
} \
|
||||
using PrivateType = Class##Private;
|
||||
|
||||
// 获取私有类指针宏
|
||||
#define T_D() PrivateType *const d = GetPP()
|
||||
|
||||
// 元类型声明宏
|
||||
#define XN_METATYPE_P(cls) \
|
||||
public: \
|
||||
using ThisType = cls; \
|
||||
using SuperType = XNSim::XNNullClass;
|
||||
|
||||
// 元类型声明宏
|
||||
#define XN_METATYPE(cls, sup) \
|
||||
public: \
|
||||
using ThisType = cls; \
|
||||
using SuperType = sup;
|
||||
|
||||
// 忽略参数宏
|
||||
#define XN_UNUSED(x) (void)x
|
73
XNCore_Win/XNGlobalDefine/XNString.h
Normal file
73
XNCore_Win/XNGlobalDefine/XNString.h
Normal file
@ -0,0 +1,73 @@
|
||||
#pragma once
|
||||
#include "XNCore_global.h"
|
||||
#include "XNType.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace XNSim {
|
||||
// 字符串类型抽象
|
||||
using XN_STRING = std::string;
|
||||
using XN_WSTRING = std::wstring;
|
||||
using XN_STRINGLIST = std::vector<XN_STRING>;
|
||||
using XN_WSTRINGLIST = std::vector<XN_WSTRING>;
|
||||
// 字符串转换辅助函数
|
||||
template <typename T> FORCEINLINE XN_STRING To_XNString(const T &value) {
|
||||
return std::to_string(value);
|
||||
}
|
||||
|
||||
template <typename T> FORCEINLINE XN_WSTRING To_XNWString(const T &value) {
|
||||
return std::to_wstring(value);
|
||||
}
|
||||
|
||||
FORCEINLINE XN_STRINGLIST XNSplit(const XN_STRING &str,
|
||||
const XN_STRING &delim) {
|
||||
XN_STRINGLIST tokens;
|
||||
XN_SIZE prev = 0, pos = 0;
|
||||
do {
|
||||
pos = str.find(delim, prev);
|
||||
if (pos == XN_STRING::npos)
|
||||
pos = str.length();
|
||||
XN_STRING token = str.substr(prev, pos - prev);
|
||||
if (!token.empty())
|
||||
tokens.push_back(token);
|
||||
prev = pos + delim.length();
|
||||
} while (pos < str.length() && prev < str.length());
|
||||
return tokens;
|
||||
}
|
||||
|
||||
FORCEINLINE XN_INT32 XNSafe_stoi(const XN_STRING &str,
|
||||
XN_INT32 defaultValue = 0) {
|
||||
if (str.empty()) {
|
||||
return defaultValue;
|
||||
}
|
||||
try {
|
||||
return std::stoi(str);
|
||||
} catch (const std::exception &) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
FORCEINLINE XN_DOUBLE XNSafe_stod(const XN_STRING &str,
|
||||
XN_DOUBLE defaultValue = 0) {
|
||||
if (str.empty()) {
|
||||
return defaultValue;
|
||||
}
|
||||
try {
|
||||
return std::stod(str);
|
||||
} catch (const std::exception &) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
FORCEINLINE XN_INT64 XNSafe_stoll(const XN_STRING &str,
|
||||
XN_INT64 defaultValue = 0) {
|
||||
if (str.empty()) {
|
||||
return defaultValue;
|
||||
}
|
||||
try {
|
||||
return std::stoll(str);
|
||||
} catch (const std::exception &) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
} // namespace XNSim
|
108
XNCore_Win/XNGlobalDefine/XNThread.h
Normal file
108
XNCore_Win/XNGlobalDefine/XNThread.h
Normal file
@ -0,0 +1,108 @@
|
||||
#pragma once
|
||||
|
||||
#include <XNGlobalDefine/XNCore_global.h>
|
||||
#include <any>
|
||||
#include <condition_variable>
|
||||
#include <functional>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
#ifdef XN_LINUX
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
namespace XNSim {
|
||||
// 线程相关抽象
|
||||
using XN_MUTEX = std::mutex;
|
||||
|
||||
#ifdef XN_WINDOWS
|
||||
using XN_THREAD = std::thread;
|
||||
using XN_THREAD_MUTEX = std::unique_lock<std::mutex>;
|
||||
using XN_THREAD_CV = std::condition_variable;
|
||||
#endif
|
||||
|
||||
#ifdef XN_LINUX
|
||||
using XN_THREAD = pthread_t;
|
||||
using XN_THREAD_MUTEX = pthread_mutex_t;
|
||||
using XN_THREAD_CV = pthread_cond_t;
|
||||
using XN_THREAD_ATTR = pthread_attr_t;
|
||||
using XN_THREAD_SCHED_PARAM = sched_param;
|
||||
#endif
|
||||
|
||||
FORCEINLINE void XNThreadMutexLock(XN_THREAD_MUTEX *mutex) {
|
||||
#ifdef XN_WINDOWS
|
||||
mutex->lock();
|
||||
#endif
|
||||
#ifdef XN_LINUX
|
||||
pthread_mutex_lock(mutex);
|
||||
#endif
|
||||
}
|
||||
|
||||
FORCEINLINE void XNThreadMutexUnlock(XN_THREAD_MUTEX *mutex) {
|
||||
#ifdef XN_WINDOWS
|
||||
mutex->unlock();
|
||||
#endif
|
||||
#ifdef XN_LINUX
|
||||
pthread_mutex_unlock(mutex);
|
||||
#endif
|
||||
}
|
||||
|
||||
FORCEINLINE void XNThreadCVWait(XN_THREAD_CV *cv, XN_THREAD_MUTEX *mutex) {
|
||||
#ifdef XN_WINDOWS
|
||||
cv->wait(*mutex);
|
||||
#endif
|
||||
#ifdef XN_LINUX
|
||||
pthread_cond_wait(cv, mutex);
|
||||
#endif
|
||||
}
|
||||
|
||||
FORCEINLINE void XNThreadCVNotifyOne(XN_THREAD_CV *cv) {
|
||||
#ifdef XN_WINDOWS
|
||||
cv->notify_one();
|
||||
#endif
|
||||
#ifdef XN_LINUX
|
||||
pthread_cond_signal(cv);
|
||||
#endif
|
||||
}
|
||||
|
||||
FORCEINLINE void XNThreadCVNotifyAll(XN_THREAD_CV *cv) {
|
||||
#ifdef XN_WINDOWS
|
||||
cv->notify_all();
|
||||
#endif
|
||||
#ifdef XN_LINUX
|
||||
pthread_cond_broadcast(cv);
|
||||
#endif
|
||||
}
|
||||
|
||||
FORCEINLINE void XNThreadJoin(XN_THREAD &thread) {
|
||||
#ifdef XN_WINDOWS
|
||||
thread.join();
|
||||
#endif
|
||||
#ifdef XN_LINUX
|
||||
pthread_join(thread, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
FORCEINLINE void XNThreadDetach(XN_THREAD &thread) {
|
||||
#ifdef XN_WINDOWS
|
||||
thread.detach();
|
||||
#endif
|
||||
#ifdef XN_LINUX
|
||||
pthread_detach(thread);
|
||||
#endif
|
||||
}
|
||||
|
||||
FORCEINLINE XN_UINT32 XNThreadGetID() {
|
||||
#ifdef XN_WINDOWS
|
||||
return GetCurrentThreadId();
|
||||
#endif
|
||||
#ifdef XN_LINUX
|
||||
return pthread_self();
|
||||
#endif
|
||||
}
|
||||
|
||||
// 模型周期性回调函数类型别名
|
||||
using XNCallBack = std::function<void()>;
|
||||
|
||||
// 事件回调函数类型别名
|
||||
using XNEventCallback = std::function<void(const std::any &)>;
|
||||
} // namespace XNSim
|
99
XNCore_Win/XNGlobalDefine/XNTime.h
Normal file
99
XNCore_Win/XNGlobalDefine/XNTime.h
Normal file
@ -0,0 +1,99 @@
|
||||
#pragma once
|
||||
|
||||
#include "XNCore_global.h"
|
||||
#include "XNString.h"
|
||||
#include "XNType.h"
|
||||
#include <chrono>
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
#include <time.h>
|
||||
|
||||
namespace XNSim {
|
||||
|
||||
// 系统时间点类型别名
|
||||
using XNTimePoint = std::chrono::system_clock::time_point;
|
||||
|
||||
/**
|
||||
* @brief 将ISO格式的时间字符串转换为系统时间点
|
||||
* @param timeStr ISO格式的时间字符串 (YYYY-MM-DDTHH:mm:ss)
|
||||
* @return 系统时间点
|
||||
*/
|
||||
FORCEINLINE XNTimePoint parseISOTime(const XN_STRING &timeStr) {
|
||||
std::tm tm = {};
|
||||
std::istringstream ss(timeStr);
|
||||
ss >> std::get_time(&tm, "%Y-%m-%dT%H:%M:%S");
|
||||
auto tp = std::chrono::system_clock::from_time_t(std::mktime(&tm));
|
||||
return tp;
|
||||
}
|
||||
|
||||
struct PERIOD_INFO;
|
||||
|
||||
#ifdef XN_WINDOWS
|
||||
using XN_TIMESPEC = LARGE_INTEGER;
|
||||
|
||||
FORCEINLINE void getCurrentRTTime(XN_TIMESPEC *time) {
|
||||
QueryPerformanceCounter(time);
|
||||
}
|
||||
|
||||
FORCEINLINE double calculateRTTime(XN_TIMESPEC *now, XN_TIMESPEC *last) {
|
||||
XN_TIMESPEC freq;
|
||||
QueryPerformanceFrequency(&freq);
|
||||
XN_INT64 ns = (now->QuadPart - last->QuadPart) * 1000000LL / freq.QuadPart;
|
||||
return (double)ns / 1.0E9;
|
||||
}
|
||||
|
||||
FORCEINLINE void sleepToNextRTTime(PERIOD_INFO *pinfo) {
|
||||
XN_TIMESPEC freq;
|
||||
QueryPerformanceFrequency(&freq);
|
||||
auto now = pinfo->next_period;
|
||||
pinfo->next_period.QuadPart += (pinfo->period_ns * freq.QuadPart) / 1000000LL;
|
||||
XN_INT64 ns =
|
||||
(pinfo->next_period.QuadPart - now.QuadPart) * 1000000LL / freq.QuadPart;
|
||||
Sleep(ns / 1000);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef XN_LINUX
|
||||
using XN_TIMESPEC = timespec;
|
||||
|
||||
FORCEINLINE void getCurrentRTTime(XN_TIMESPEC *time) {
|
||||
clock_gettime(CLOCK_MONOTONIC, time);
|
||||
}
|
||||
|
||||
FORCEINLINE double calculateRTTime(XN_TIMESPEC *now, XN_TIMESPEC *last) {
|
||||
double seconds = (double)(now->tv_sec - last->tv_sec) +
|
||||
(double)(now->tv_nsec - last->tv_nsec) / 1.0E9;
|
||||
return seconds;
|
||||
}
|
||||
|
||||
FORCEINLINE void sleepToNextRTTime(PERIOD_INFO *pinfo) {
|
||||
// 睡眠时间步进
|
||||
pinfo->next_period.tv_nsec += pinfo->period_ns;
|
||||
|
||||
// 睡眠时间整理
|
||||
while (pinfo->next_period.tv_nsec >= 1000000000) {
|
||||
pinfo->next_period.tv_sec++;
|
||||
pinfo->next_period.tv_nsec -= 1000000000;
|
||||
}
|
||||
|
||||
// 执行纳秒睡眠
|
||||
clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &pinfo->next_period, NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief 纳秒睡眠相关时间结构体
|
||||
* @details 用于线程睡眠时间控制
|
||||
*/
|
||||
struct PERIOD_INFO {
|
||||
/**
|
||||
* @brief 系统提供的时间记录结构体,精确到纳秒
|
||||
*/
|
||||
XN_TIMESPEC next_period;
|
||||
/**
|
||||
* @brief 睡眠时长,单位纳秒
|
||||
*/
|
||||
XN_INT64 period_ns;
|
||||
};
|
||||
|
||||
} // namespace XNSim
|
23
XNCore_Win/XNGlobalDefine/XNType.h
Normal file
23
XNCore_Win/XNGlobalDefine/XNType.h
Normal file
@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace XNSim {
|
||||
// 基础类型抽象
|
||||
using XN_INT8 = int8_t;
|
||||
using XN_UINT8 = uint8_t;
|
||||
using XN_INT16 = int16_t;
|
||||
using XN_UINT16 = uint16_t;
|
||||
using XN_INT32 = int32_t;
|
||||
using XN_UINT32 = uint32_t;
|
||||
using XN_INT64 = int64_t;
|
||||
using XN_UINT64 = uint64_t;
|
||||
using XN_FLOAT = float;
|
||||
using XN_DOUBLE = double;
|
||||
using XN_BOOL = bool;
|
||||
using XN_SIZE = size_t;
|
||||
|
||||
using XNAsignedIDFlag = std::vector<bool>;
|
||||
|
||||
using XN_ANY = std::any;
|
||||
} // namespace XNSim
|
71
XNCore_Win/XNGlobalDefine/XNTypeTraits.h
Normal file
71
XNCore_Win/XNGlobalDefine/XNTypeTraits.h
Normal file
@ -0,0 +1,71 @@
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <stdexcept>
|
||||
#include <type_traits>
|
||||
|
||||
namespace XNSim {
|
||||
|
||||
// 类型检查
|
||||
template <typename T, typename U>
|
||||
inline constexpr bool is_same_v = std::is_same_v<T, U>;
|
||||
|
||||
// 算术类型检查
|
||||
template <typename T>
|
||||
inline constexpr bool is_arithmetic_v = std::is_arithmetic_v<T>;
|
||||
|
||||
// 可转换类型检查
|
||||
template <typename T, typename U>
|
||||
inline constexpr bool is_convertible_v = std::is_convertible_v<T, U>;
|
||||
|
||||
// 数组类型检查
|
||||
namespace TypeTraits {
|
||||
template <typename T> struct is_std_array : std::false_type {};
|
||||
|
||||
template <typename T, std::size_t N>
|
||||
struct is_std_array<std::array<T, N>> : std::true_type {};
|
||||
} // namespace TypeTraits
|
||||
|
||||
// 数组类型检查简化使用
|
||||
template <typename T>
|
||||
inline constexpr bool is_array_v = TypeTraits::is_std_array<T>::value;
|
||||
|
||||
// 获取数组大小
|
||||
namespace TypeTraits {
|
||||
template <typename T>
|
||||
struct array_size : std::integral_constant<std::size_t, 1> {};
|
||||
|
||||
template <typename T, std::size_t N>
|
||||
struct array_size<std::array<T, N>> : std::integral_constant<std::size_t, N> {};
|
||||
} // namespace TypeTraits
|
||||
|
||||
// 获取数组大小简化使用
|
||||
template <typename T>
|
||||
inline constexpr std::size_t array_size_v = TypeTraits::array_size<T>::value;
|
||||
|
||||
// 获取类型大小
|
||||
template <typename T> constexpr size_t getTypeSize() {
|
||||
if constexpr (is_array_v<T>) {
|
||||
// 对于std::array,计算所有元素的总大小
|
||||
return getTypeSize<typename T::value_type>() * array_size_v<T>;
|
||||
} else {
|
||||
return sizeof(T);
|
||||
}
|
||||
}
|
||||
|
||||
// 获取数组总大小
|
||||
template <typename T> constexpr std::size_t arrayTotalSize(const T &arr) {
|
||||
if constexpr (is_array_v<T>) {
|
||||
// 对于std::array,计算所有元素的总大小
|
||||
return getTypeSize<typename T::value_type>() * array_size_v<T>;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// 枚举值获取函数
|
||||
template <typename T>
|
||||
constexpr typename std::underlying_type<T>::type enumValue(T e) {
|
||||
return static_cast<typename std::underlying_type<T>::type>(e);
|
||||
}
|
||||
} // namespace XNSim
|
43
XNCore_Win/XNGlobalDefine/XNXml.h
Normal file
43
XNCore_Win/XNGlobalDefine/XNXml.h
Normal file
@ -0,0 +1,43 @@
|
||||
#pragma once
|
||||
|
||||
// tinyxml2头文件
|
||||
#include "XNCore_global.h"
|
||||
#include "XNString.h"
|
||||
#include <tinyxml2.h>
|
||||
|
||||
namespace XNSim {
|
||||
using XN_XMLDocument = tinyxml2::XMLDocument;
|
||||
using XN_XMLElement = tinyxml2::XMLElement;
|
||||
|
||||
FORCEINLINE XN_INT32 LoadXmlFile(const XN_STRING &filePath,
|
||||
XN_XMLDocument &doc) {
|
||||
if (doc.LoadFile(filePath.c_str()) != tinyxml2::XML_SUCCESS) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
FORCEINLINE XN_XMLElement *GetRootElement(XN_XMLDocument &doc) {
|
||||
return doc.RootElement();
|
||||
}
|
||||
|
||||
FORCEINLINE XN_XMLElement *GetFirstChildElement(XN_XMLElement *element,
|
||||
const XN_STRING &name) {
|
||||
return element->FirstChildElement(name.c_str());
|
||||
}
|
||||
|
||||
FORCEINLINE XN_STRING GetFirstChildElementText(XN_XMLElement *element,
|
||||
const XN_STRING &name) {
|
||||
return XN_STRING(GetFirstChildElement(element, name)->GetText());
|
||||
}
|
||||
|
||||
FORCEINLINE XN_XMLElement *GetNextSiblingElement(XN_XMLElement *element,
|
||||
const XN_STRING &name) {
|
||||
return element->NextSiblingElement(name.c_str());
|
||||
}
|
||||
|
||||
FORCEINLINE XN_STRING GetAttribute(XN_XMLElement *element,
|
||||
const XN_STRING &name) {
|
||||
return XN_STRING(element->Attribute(name.c_str()));
|
||||
}
|
||||
} // namespace XNSim
|
11
XNCore_Win/XNIDL/CMakeLists.txt
Normal file
11
XNCore_Win/XNIDL/CMakeLists.txt
Normal file
@ -0,0 +1,11 @@
|
||||
set(XNIDL_SOURCES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XNSimStatus.hpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XNSimStatusCdrAux.hpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XNSimStatusCdrAux.ipp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XNSimStatusPubSubTypes.cxx
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XNSimStatusPubSubTypes.hpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XNSimStatusTypeObjectSupport.cxx
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XNSimStatusTypeObjectSupport.hpp
|
||||
)
|
||||
|
||||
set(XNCORE_SOURCES ${XNCORE_SOURCES} ${XNIDL_SOURCES} PARENT_SCOPE)
|
1760
XNCore_Win/XNIDL/XNSimStatus.hpp
Normal file
1760
XNCore_Win/XNIDL/XNSimStatus.hpp
Normal file
File diff suppressed because it is too large
Load Diff
67
XNCore_Win/XNIDL/XNSimStatus.idl
Normal file
67
XNCore_Win/XNIDL/XNSimStatus.idl
Normal file
@ -0,0 +1,67 @@
|
||||
module XNSim
|
||||
{
|
||||
module XNSimStatus
|
||||
{
|
||||
//内核加载状态,内置类型,不能用作主题
|
||||
@nested
|
||||
struct XNCoreStatus
|
||||
{
|
||||
long XNFWStatus; //主框架加载状态 0-未加载 1-初始化完成 2-正常 其它-异常
|
||||
long XNTMStatus; //时间管理器加载状态 0-未加载 1-初始化完成 2-正常 其它-异常
|
||||
long XNEMStatus; //事件管理器加载状态 0-未加载 1-初始化完成 2-正常 其它-异常
|
||||
long XNSDStatus; //场景管理器加载状态 0-未加载 1-初始化完成 2-正常 其它-异常
|
||||
long XNThMStatus; //线程管理器加载状态 0-未加载 1-初始化完成 2-正常 其它-异常
|
||||
long XNMMStatus; //模型管理器加载状态 0-未加载 1-初始化完成 2-正常 其它-异常
|
||||
long XNSMStatus; //服务管理器加载状态 0-未加载 1-初始化完成 2-正常 其它-异常
|
||||
long XNDMStatus; //DDS管理器加载状态 0-未加载 1-初始化完成 2-正常 其它-异常
|
||||
};
|
||||
|
||||
//引擎状态主题
|
||||
struct XNEngineStatus
|
||||
{
|
||||
string XNEngineName; //引擎名称
|
||||
long XNEngineID; //引擎ID
|
||||
long XNEngineSt; //引擎状态 0-未开始 1-运行中 2-暂停 3-终止 其它-未知状态
|
||||
long XNEngineAff; //引擎CPU亲和性
|
||||
long XNThCnt; //线程数量
|
||||
XNCoreStatus XNCoreSt; //内核状态
|
||||
};
|
||||
|
||||
//线程状态主题
|
||||
struct XNThreadStatus
|
||||
{
|
||||
string XNThreadName; //线程名称
|
||||
long XNThreadID; //线程ID
|
||||
long XNThreadSt; //线程状态 0-未开始 1-运行中 2-暂停 3-终止 其它-未知状态
|
||||
long XNThreadAff; //线程CPU亲和性
|
||||
long XNThreadPro; //线程优先级
|
||||
unsigned long long XNThRunCnt; //线程运行周期数
|
||||
double XNThCurFreq; //线程实时频率,单位Hz
|
||||
double XNThSetFreq; //线程设置频率,单位Hz
|
||||
};
|
||||
|
||||
//模型状态主题
|
||||
struct XNModelStatus
|
||||
{
|
||||
string XNModelName; //模型名称
|
||||
long XNModelID; //模型ID
|
||||
long XNModelSt; //模型状态主题
|
||||
long XNModelThID; //模型所属线程ID
|
||||
long XNModelNode; //模型运行节点
|
||||
long XNModelPro; //模型运行优先级
|
||||
unsigned long long XNModelRunCnt; //模型运行周期数
|
||||
double XNMdlCurFreq; //模型实时频率,单位Hz
|
||||
double XNMdlSetFreq; //模型设置频率,单位Hz
|
||||
};
|
||||
};
|
||||
|
||||
module XNSimControl
|
||||
{
|
||||
//仿真运行控制主题
|
||||
struct XNRuntimeControl
|
||||
{
|
||||
long XNSimCmd; //仿真控制指令 0-无指令 1-暂停 2-继续 3-终止
|
||||
long XNThrCmd; //线程控制指令 从低位到高位,每两个二进制位控制一个线程的运行:00-无指令,01- 暂停,10-继续,11-结束
|
||||
};
|
||||
};
|
||||
};
|
74
XNCore_Win/XNIDL/XNSimStatusCdrAux.hpp
Normal file
74
XNCore_Win/XNIDL/XNSimStatusCdrAux.hpp
Normal file
@ -0,0 +1,74 @@
|
||||
// Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima).
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/*!
|
||||
* @file XNSimStatusCdrAux.hpp
|
||||
* This source file contains some definitions of CDR related functions.
|
||||
*
|
||||
* This file was generated by the tool fastddsgen.
|
||||
*/
|
||||
|
||||
#ifndef FAST_DDS_GENERATED__XNSIM_XNSIMCONTROL_XNSIMSTATUSCDRAUX_HPP
|
||||
#define FAST_DDS_GENERATED__XNSIM_XNSIMCONTROL_XNSIMSTATUSCDRAUX_HPP
|
||||
|
||||
#include "XNSimStatus.hpp"
|
||||
|
||||
constexpr uint32_t XNSim_XNSimStatus_XNCoreStatus_max_cdr_typesize {36UL};
|
||||
constexpr uint32_t XNSim_XNSimStatus_XNCoreStatus_max_key_cdr_typesize {0UL};
|
||||
|
||||
constexpr uint32_t XNSim_XNSimStatus_XNModelStatus_max_cdr_typesize {312UL};
|
||||
constexpr uint32_t XNSim_XNSimStatus_XNModelStatus_max_key_cdr_typesize {0UL};
|
||||
|
||||
constexpr uint32_t XNSim_XNSimStatus_XNThreadStatus_max_cdr_typesize {304UL};
|
||||
constexpr uint32_t XNSim_XNSimStatus_XNThreadStatus_max_key_cdr_typesize {0UL};
|
||||
|
||||
constexpr uint32_t XNSim_XNSimControl_XNRuntimeControl_max_cdr_typesize {12UL};
|
||||
constexpr uint32_t XNSim_XNSimControl_XNRuntimeControl_max_key_cdr_typesize {0UL};
|
||||
|
||||
constexpr uint32_t XNSim_XNSimStatus_XNEngineStatus_max_cdr_typesize {316UL};
|
||||
constexpr uint32_t XNSim_XNSimStatus_XNEngineStatus_max_key_cdr_typesize {0UL};
|
||||
|
||||
|
||||
namespace eprosima {
|
||||
namespace fastcdr {
|
||||
|
||||
class Cdr;
|
||||
class CdrSizeCalculator;
|
||||
|
||||
eProsima_user_DllExport void serialize_key(
|
||||
eprosima::fastcdr::Cdr& scdr,
|
||||
const XNSim::XNSimStatus::XNCoreStatus& data);
|
||||
|
||||
eProsima_user_DllExport void serialize_key(
|
||||
eprosima::fastcdr::Cdr& scdr,
|
||||
const XNSim::XNSimStatus::XNEngineStatus& data);
|
||||
|
||||
eProsima_user_DllExport void serialize_key(
|
||||
eprosima::fastcdr::Cdr& scdr,
|
||||
const XNSim::XNSimStatus::XNThreadStatus& data);
|
||||
|
||||
eProsima_user_DllExport void serialize_key(
|
||||
eprosima::fastcdr::Cdr& scdr,
|
||||
const XNSim::XNSimStatus::XNModelStatus& data);
|
||||
|
||||
eProsima_user_DllExport void serialize_key(
|
||||
eprosima::fastcdr::Cdr& scdr,
|
||||
const XNSim::XNSimControl::XNRuntimeControl& data);
|
||||
|
||||
|
||||
} // namespace fastcdr
|
||||
} // namespace eprosima
|
||||
|
||||
#endif // FAST_DDS_GENERATED__XNSIM_XNSIMCONTROL_XNSIMSTATUSCDRAUX_HPP
|
||||
|
756
XNCore_Win/XNIDL/XNSimStatusCdrAux.ipp
Normal file
756
XNCore_Win/XNIDL/XNSimStatusCdrAux.ipp
Normal file
@ -0,0 +1,756 @@
|
||||
// Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima).
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/*!
|
||||
* @file XNSimStatusCdrAux.ipp
|
||||
* This source file contains some declarations of CDR related functions.
|
||||
*
|
||||
* This file was generated by the tool fastddsgen.
|
||||
*/
|
||||
|
||||
#ifndef FAST_DDS_GENERATED__XNSIM_XNSIMCONTROL_XNSIMSTATUSCDRAUX_IPP
|
||||
#define FAST_DDS_GENERATED__XNSIM_XNSIMCONTROL_XNSIMSTATUSCDRAUX_IPP
|
||||
|
||||
#include "XNSimStatusCdrAux.hpp"
|
||||
|
||||
#include <fastcdr/Cdr.h>
|
||||
#include <fastcdr/CdrSizeCalculator.hpp>
|
||||
|
||||
|
||||
#include <fastcdr/exceptions/BadParamException.h>
|
||||
using namespace eprosima::fastcdr::exception;
|
||||
|
||||
namespace eprosima {
|
||||
namespace fastcdr {
|
||||
|
||||
template<>
|
||||
eProsima_user_DllExport size_t calculate_serialized_size(
|
||||
eprosima::fastcdr::CdrSizeCalculator& calculator,
|
||||
const XNSim::XNSimStatus::XNCoreStatus& data,
|
||||
size_t& current_alignment)
|
||||
{
|
||||
using namespace XNSim::XNSimStatus;
|
||||
|
||||
static_cast<void>(data);
|
||||
|
||||
eprosima::fastcdr::EncodingAlgorithmFlag previous_encoding = calculator.get_encoding();
|
||||
size_t calculated_size {calculator.begin_calculate_type_serialized_size(
|
||||
eprosima::fastcdr::CdrVersion::XCDRv2 == calculator.get_cdr_version() ?
|
||||
eprosima::fastcdr::EncodingAlgorithmFlag::DELIMIT_CDR2 :
|
||||
eprosima::fastcdr::EncodingAlgorithmFlag::PLAIN_CDR,
|
||||
current_alignment)};
|
||||
|
||||
|
||||
calculated_size += calculator.calculate_member_serialized_size(eprosima::fastcdr::MemberId(0),
|
||||
data.XNFWStatus(), current_alignment);
|
||||
|
||||
calculated_size += calculator.calculate_member_serialized_size(eprosima::fastcdr::MemberId(1),
|
||||
data.XNTMStatus(), current_alignment);
|
||||
|
||||
calculated_size += calculator.calculate_member_serialized_size(eprosima::fastcdr::MemberId(2),
|
||||
data.XNEMStatus(), current_alignment);
|
||||
|
||||
calculated_size += calculator.calculate_member_serialized_size(eprosima::fastcdr::MemberId(3),
|
||||
data.XNSDStatus(), current_alignment);
|
||||
|
||||
calculated_size += calculator.calculate_member_serialized_size(eprosima::fastcdr::MemberId(4),
|
||||
data.XNThMStatus(), current_alignment);
|
||||
|
||||
calculated_size += calculator.calculate_member_serialized_size(eprosima::fastcdr::MemberId(5),
|
||||
data.XNMMStatus(), current_alignment);
|
||||
|
||||
calculated_size += calculator.calculate_member_serialized_size(eprosima::fastcdr::MemberId(6),
|
||||
data.XNSMStatus(), current_alignment);
|
||||
|
||||
calculated_size += calculator.calculate_member_serialized_size(eprosima::fastcdr::MemberId(7),
|
||||
data.XNDMStatus(), current_alignment);
|
||||
|
||||
|
||||
calculated_size += calculator.end_calculate_type_serialized_size(previous_encoding, current_alignment);
|
||||
|
||||
return calculated_size;
|
||||
}
|
||||
|
||||
template<>
|
||||
eProsima_user_DllExport void serialize(
|
||||
eprosima::fastcdr::Cdr& scdr,
|
||||
const XNSim::XNSimStatus::XNCoreStatus& data)
|
||||
{
|
||||
using namespace XNSim::XNSimStatus;
|
||||
|
||||
eprosima::fastcdr::Cdr::state current_state(scdr);
|
||||
scdr.begin_serialize_type(current_state,
|
||||
eprosima::fastcdr::CdrVersion::XCDRv2 == scdr.get_cdr_version() ?
|
||||
eprosima::fastcdr::EncodingAlgorithmFlag::DELIMIT_CDR2 :
|
||||
eprosima::fastcdr::EncodingAlgorithmFlag::PLAIN_CDR);
|
||||
|
||||
scdr
|
||||
<< eprosima::fastcdr::MemberId(0) << data.XNFWStatus()
|
||||
<< eprosima::fastcdr::MemberId(1) << data.XNTMStatus()
|
||||
<< eprosima::fastcdr::MemberId(2) << data.XNEMStatus()
|
||||
<< eprosima::fastcdr::MemberId(3) << data.XNSDStatus()
|
||||
<< eprosima::fastcdr::MemberId(4) << data.XNThMStatus()
|
||||
<< eprosima::fastcdr::MemberId(5) << data.XNMMStatus()
|
||||
<< eprosima::fastcdr::MemberId(6) << data.XNSMStatus()
|
||||
<< eprosima::fastcdr::MemberId(7) << data.XNDMStatus()
|
||||
;
|
||||
scdr.end_serialize_type(current_state);
|
||||
}
|
||||
|
||||
template<>
|
||||
eProsima_user_DllExport void deserialize(
|
||||
eprosima::fastcdr::Cdr& cdr,
|
||||
XNSim::XNSimStatus::XNCoreStatus& data)
|
||||
{
|
||||
using namespace XNSim::XNSimStatus;
|
||||
|
||||
cdr.deserialize_type(eprosima::fastcdr::CdrVersion::XCDRv2 == cdr.get_cdr_version() ?
|
||||
eprosima::fastcdr::EncodingAlgorithmFlag::DELIMIT_CDR2 :
|
||||
eprosima::fastcdr::EncodingAlgorithmFlag::PLAIN_CDR,
|
||||
[&data](eprosima::fastcdr::Cdr& dcdr, const eprosima::fastcdr::MemberId& mid) -> bool
|
||||
{
|
||||
bool ret_value = true;
|
||||
switch (mid.id)
|
||||
{
|
||||
case 0:
|
||||
dcdr >> data.XNFWStatus();
|
||||
break;
|
||||
|
||||
case 1:
|
||||
dcdr >> data.XNTMStatus();
|
||||
break;
|
||||
|
||||
case 2:
|
||||
dcdr >> data.XNEMStatus();
|
||||
break;
|
||||
|
||||
case 3:
|
||||
dcdr >> data.XNSDStatus();
|
||||
break;
|
||||
|
||||
case 4:
|
||||
dcdr >> data.XNThMStatus();
|
||||
break;
|
||||
|
||||
case 5:
|
||||
dcdr >> data.XNMMStatus();
|
||||
break;
|
||||
|
||||
case 6:
|
||||
dcdr >> data.XNSMStatus();
|
||||
break;
|
||||
|
||||
case 7:
|
||||
dcdr >> data.XNDMStatus();
|
||||
break;
|
||||
|
||||
default:
|
||||
ret_value = false;
|
||||
break;
|
||||
}
|
||||
return ret_value;
|
||||
});
|
||||
}
|
||||
|
||||
void serialize_key(
|
||||
eprosima::fastcdr::Cdr& scdr,
|
||||
const XNSim::XNSimStatus::XNCoreStatus& data)
|
||||
{
|
||||
using namespace XNSim::XNSimStatus;
|
||||
|
||||
static_cast<void>(scdr);
|
||||
static_cast<void>(data);
|
||||
scdr << data.XNFWStatus();
|
||||
|
||||
scdr << data.XNTMStatus();
|
||||
|
||||
scdr << data.XNEMStatus();
|
||||
|
||||
scdr << data.XNSDStatus();
|
||||
|
||||
scdr << data.XNThMStatus();
|
||||
|
||||
scdr << data.XNMMStatus();
|
||||
|
||||
scdr << data.XNSMStatus();
|
||||
|
||||
scdr << data.XNDMStatus();
|
||||
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
eProsima_user_DllExport size_t calculate_serialized_size(
|
||||
eprosima::fastcdr::CdrSizeCalculator& calculator,
|
||||
const XNSim::XNSimStatus::XNEngineStatus& data,
|
||||
size_t& current_alignment)
|
||||
{
|
||||
using namespace XNSim::XNSimStatus;
|
||||
|
||||
static_cast<void>(data);
|
||||
|
||||
eprosima::fastcdr::EncodingAlgorithmFlag previous_encoding = calculator.get_encoding();
|
||||
size_t calculated_size {calculator.begin_calculate_type_serialized_size(
|
||||
eprosima::fastcdr::CdrVersion::XCDRv2 == calculator.get_cdr_version() ?
|
||||
eprosima::fastcdr::EncodingAlgorithmFlag::DELIMIT_CDR2 :
|
||||
eprosima::fastcdr::EncodingAlgorithmFlag::PLAIN_CDR,
|
||||
current_alignment)};
|
||||
|
||||
|
||||
calculated_size += calculator.calculate_member_serialized_size(eprosima::fastcdr::MemberId(0),
|
||||
data.XNEngineName(), current_alignment);
|
||||
|
||||
calculated_size += calculator.calculate_member_serialized_size(eprosima::fastcdr::MemberId(1),
|
||||
data.XNEngineID(), current_alignment);
|
||||
|
||||
calculated_size += calculator.calculate_member_serialized_size(eprosima::fastcdr::MemberId(2),
|
||||
data.XNEngineSt(), current_alignment);
|
||||
|
||||
calculated_size += calculator.calculate_member_serialized_size(eprosima::fastcdr::MemberId(3),
|
||||
data.XNEngineAff(), current_alignment);
|
||||
|
||||
calculated_size += calculator.calculate_member_serialized_size(eprosima::fastcdr::MemberId(4),
|
||||
data.XNThCnt(), current_alignment);
|
||||
|
||||
calculated_size += calculator.calculate_member_serialized_size(eprosima::fastcdr::MemberId(5),
|
||||
data.XNCoreSt(), current_alignment);
|
||||
|
||||
|
||||
calculated_size += calculator.end_calculate_type_serialized_size(previous_encoding, current_alignment);
|
||||
|
||||
return calculated_size;
|
||||
}
|
||||
|
||||
template<>
|
||||
eProsima_user_DllExport void serialize(
|
||||
eprosima::fastcdr::Cdr& scdr,
|
||||
const XNSim::XNSimStatus::XNEngineStatus& data)
|
||||
{
|
||||
using namespace XNSim::XNSimStatus;
|
||||
|
||||
eprosima::fastcdr::Cdr::state current_state(scdr);
|
||||
scdr.begin_serialize_type(current_state,
|
||||
eprosima::fastcdr::CdrVersion::XCDRv2 == scdr.get_cdr_version() ?
|
||||
eprosima::fastcdr::EncodingAlgorithmFlag::DELIMIT_CDR2 :
|
||||
eprosima::fastcdr::EncodingAlgorithmFlag::PLAIN_CDR);
|
||||
|
||||
scdr
|
||||
<< eprosima::fastcdr::MemberId(0) << data.XNEngineName()
|
||||
<< eprosima::fastcdr::MemberId(1) << data.XNEngineID()
|
||||
<< eprosima::fastcdr::MemberId(2) << data.XNEngineSt()
|
||||
<< eprosima::fastcdr::MemberId(3) << data.XNEngineAff()
|
||||
<< eprosima::fastcdr::MemberId(4) << data.XNThCnt()
|
||||
<< eprosima::fastcdr::MemberId(5) << data.XNCoreSt()
|
||||
;
|
||||
scdr.end_serialize_type(current_state);
|
||||
}
|
||||
|
||||
template<>
|
||||
eProsima_user_DllExport void deserialize(
|
||||
eprosima::fastcdr::Cdr& cdr,
|
||||
XNSim::XNSimStatus::XNEngineStatus& data)
|
||||
{
|
||||
using namespace XNSim::XNSimStatus;
|
||||
|
||||
cdr.deserialize_type(eprosima::fastcdr::CdrVersion::XCDRv2 == cdr.get_cdr_version() ?
|
||||
eprosima::fastcdr::EncodingAlgorithmFlag::DELIMIT_CDR2 :
|
||||
eprosima::fastcdr::EncodingAlgorithmFlag::PLAIN_CDR,
|
||||
[&data](eprosima::fastcdr::Cdr& dcdr, const eprosima::fastcdr::MemberId& mid) -> bool
|
||||
{
|
||||
bool ret_value = true;
|
||||
switch (mid.id)
|
||||
{
|
||||
case 0:
|
||||
dcdr >> data.XNEngineName();
|
||||
break;
|
||||
|
||||
case 1:
|
||||
dcdr >> data.XNEngineID();
|
||||
break;
|
||||
|
||||
case 2:
|
||||
dcdr >> data.XNEngineSt();
|
||||
break;
|
||||
|
||||
case 3:
|
||||
dcdr >> data.XNEngineAff();
|
||||
break;
|
||||
|
||||
case 4:
|
||||
dcdr >> data.XNThCnt();
|
||||
break;
|
||||
|
||||
case 5:
|
||||
dcdr >> data.XNCoreSt();
|
||||
break;
|
||||
|
||||
default:
|
||||
ret_value = false;
|
||||
break;
|
||||
}
|
||||
return ret_value;
|
||||
});
|
||||
}
|
||||
|
||||
void serialize_key(
|
||||
eprosima::fastcdr::Cdr& scdr,
|
||||
const XNSim::XNSimStatus::XNEngineStatus& data)
|
||||
{
|
||||
using namespace XNSim::XNSimStatus;
|
||||
extern void serialize_key(
|
||||
Cdr& scdr,
|
||||
const XNSim::XNSimStatus::XNCoreStatus& data);
|
||||
|
||||
|
||||
static_cast<void>(scdr);
|
||||
static_cast<void>(data);
|
||||
scdr << data.XNEngineName();
|
||||
|
||||
scdr << data.XNEngineID();
|
||||
|
||||
scdr << data.XNEngineSt();
|
||||
|
||||
scdr << data.XNEngineAff();
|
||||
|
||||
scdr << data.XNThCnt();
|
||||
|
||||
serialize_key(scdr, data.XNCoreSt());
|
||||
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
eProsima_user_DllExport size_t calculate_serialized_size(
|
||||
eprosima::fastcdr::CdrSizeCalculator& calculator,
|
||||
const XNSim::XNSimStatus::XNThreadStatus& data,
|
||||
size_t& current_alignment)
|
||||
{
|
||||
using namespace XNSim::XNSimStatus;
|
||||
|
||||
static_cast<void>(data);
|
||||
|
||||
eprosima::fastcdr::EncodingAlgorithmFlag previous_encoding = calculator.get_encoding();
|
||||
size_t calculated_size {calculator.begin_calculate_type_serialized_size(
|
||||
eprosima::fastcdr::CdrVersion::XCDRv2 == calculator.get_cdr_version() ?
|
||||
eprosima::fastcdr::EncodingAlgorithmFlag::DELIMIT_CDR2 :
|
||||
eprosima::fastcdr::EncodingAlgorithmFlag::PLAIN_CDR,
|
||||
current_alignment)};
|
||||
|
||||
|
||||
calculated_size += calculator.calculate_member_serialized_size(eprosima::fastcdr::MemberId(0),
|
||||
data.XNThreadName(), current_alignment);
|
||||
|
||||
calculated_size += calculator.calculate_member_serialized_size(eprosima::fastcdr::MemberId(1),
|
||||
data.XNThreadID(), current_alignment);
|
||||
|
||||
calculated_size += calculator.calculate_member_serialized_size(eprosima::fastcdr::MemberId(2),
|
||||
data.XNThreadSt(), current_alignment);
|
||||
|
||||
calculated_size += calculator.calculate_member_serialized_size(eprosima::fastcdr::MemberId(3),
|
||||
data.XNThreadAff(), current_alignment);
|
||||
|
||||
calculated_size += calculator.calculate_member_serialized_size(eprosima::fastcdr::MemberId(4),
|
||||
data.XNThreadPro(), current_alignment);
|
||||
|
||||
calculated_size += calculator.calculate_member_serialized_size(eprosima::fastcdr::MemberId(5),
|
||||
data.XNThRunCnt(), current_alignment);
|
||||
|
||||
calculated_size += calculator.calculate_member_serialized_size(eprosima::fastcdr::MemberId(6),
|
||||
data.XNThCurFreq(), current_alignment);
|
||||
|
||||
calculated_size += calculator.calculate_member_serialized_size(eprosima::fastcdr::MemberId(7),
|
||||
data.XNThSetFreq(), current_alignment);
|
||||
|
||||
|
||||
calculated_size += calculator.end_calculate_type_serialized_size(previous_encoding, current_alignment);
|
||||
|
||||
return calculated_size;
|
||||
}
|
||||
|
||||
template<>
|
||||
eProsima_user_DllExport void serialize(
|
||||
eprosima::fastcdr::Cdr& scdr,
|
||||
const XNSim::XNSimStatus::XNThreadStatus& data)
|
||||
{
|
||||
using namespace XNSim::XNSimStatus;
|
||||
|
||||
eprosima::fastcdr::Cdr::state current_state(scdr);
|
||||
scdr.begin_serialize_type(current_state,
|
||||
eprosima::fastcdr::CdrVersion::XCDRv2 == scdr.get_cdr_version() ?
|
||||
eprosima::fastcdr::EncodingAlgorithmFlag::DELIMIT_CDR2 :
|
||||
eprosima::fastcdr::EncodingAlgorithmFlag::PLAIN_CDR);
|
||||
|
||||
scdr
|
||||
<< eprosima::fastcdr::MemberId(0) << data.XNThreadName()
|
||||
<< eprosima::fastcdr::MemberId(1) << data.XNThreadID()
|
||||
<< eprosima::fastcdr::MemberId(2) << data.XNThreadSt()
|
||||
<< eprosima::fastcdr::MemberId(3) << data.XNThreadAff()
|
||||
<< eprosima::fastcdr::MemberId(4) << data.XNThreadPro()
|
||||
<< eprosima::fastcdr::MemberId(5) << data.XNThRunCnt()
|
||||
<< eprosima::fastcdr::MemberId(6) << data.XNThCurFreq()
|
||||
<< eprosima::fastcdr::MemberId(7) << data.XNThSetFreq()
|
||||
;
|
||||
scdr.end_serialize_type(current_state);
|
||||
}
|
||||
|
||||
template<>
|
||||
eProsima_user_DllExport void deserialize(
|
||||
eprosima::fastcdr::Cdr& cdr,
|
||||
XNSim::XNSimStatus::XNThreadStatus& data)
|
||||
{
|
||||
using namespace XNSim::XNSimStatus;
|
||||
|
||||
cdr.deserialize_type(eprosima::fastcdr::CdrVersion::XCDRv2 == cdr.get_cdr_version() ?
|
||||
eprosima::fastcdr::EncodingAlgorithmFlag::DELIMIT_CDR2 :
|
||||
eprosima::fastcdr::EncodingAlgorithmFlag::PLAIN_CDR,
|
||||
[&data](eprosima::fastcdr::Cdr& dcdr, const eprosima::fastcdr::MemberId& mid) -> bool
|
||||
{
|
||||
bool ret_value = true;
|
||||
switch (mid.id)
|
||||
{
|
||||
case 0:
|
||||
dcdr >> data.XNThreadName();
|
||||
break;
|
||||
|
||||
case 1:
|
||||
dcdr >> data.XNThreadID();
|
||||
break;
|
||||
|
||||
case 2:
|
||||
dcdr >> data.XNThreadSt();
|
||||
break;
|
||||
|
||||
case 3:
|
||||
dcdr >> data.XNThreadAff();
|
||||
break;
|
||||
|
||||
case 4:
|
||||
dcdr >> data.XNThreadPro();
|
||||
break;
|
||||
|
||||
case 5:
|
||||
dcdr >> data.XNThRunCnt();
|
||||
break;
|
||||
|
||||
case 6:
|
||||
dcdr >> data.XNThCurFreq();
|
||||
break;
|
||||
|
||||
case 7:
|
||||
dcdr >> data.XNThSetFreq();
|
||||
break;
|
||||
|
||||
default:
|
||||
ret_value = false;
|
||||
break;
|
||||
}
|
||||
return ret_value;
|
||||
});
|
||||
}
|
||||
|
||||
void serialize_key(
|
||||
eprosima::fastcdr::Cdr& scdr,
|
||||
const XNSim::XNSimStatus::XNThreadStatus& data)
|
||||
{
|
||||
using namespace XNSim::XNSimStatus;
|
||||
|
||||
static_cast<void>(scdr);
|
||||
static_cast<void>(data);
|
||||
scdr << data.XNThreadName();
|
||||
|
||||
scdr << data.XNThreadID();
|
||||
|
||||
scdr << data.XNThreadSt();
|
||||
|
||||
scdr << data.XNThreadAff();
|
||||
|
||||
scdr << data.XNThreadPro();
|
||||
|
||||
scdr << data.XNThRunCnt();
|
||||
|
||||
scdr << data.XNThCurFreq();
|
||||
|
||||
scdr << data.XNThSetFreq();
|
||||
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
eProsima_user_DllExport size_t calculate_serialized_size(
|
||||
eprosima::fastcdr::CdrSizeCalculator& calculator,
|
||||
const XNSim::XNSimStatus::XNModelStatus& data,
|
||||
size_t& current_alignment)
|
||||
{
|
||||
using namespace XNSim::XNSimStatus;
|
||||
|
||||
static_cast<void>(data);
|
||||
|
||||
eprosima::fastcdr::EncodingAlgorithmFlag previous_encoding = calculator.get_encoding();
|
||||
size_t calculated_size {calculator.begin_calculate_type_serialized_size(
|
||||
eprosima::fastcdr::CdrVersion::XCDRv2 == calculator.get_cdr_version() ?
|
||||
eprosima::fastcdr::EncodingAlgorithmFlag::DELIMIT_CDR2 :
|
||||
eprosima::fastcdr::EncodingAlgorithmFlag::PLAIN_CDR,
|
||||
current_alignment)};
|
||||
|
||||
|
||||
calculated_size += calculator.calculate_member_serialized_size(eprosima::fastcdr::MemberId(0),
|
||||
data.XNModelName(), current_alignment);
|
||||
|
||||
calculated_size += calculator.calculate_member_serialized_size(eprosima::fastcdr::MemberId(1),
|
||||
data.XNModelID(), current_alignment);
|
||||
|
||||
calculated_size += calculator.calculate_member_serialized_size(eprosima::fastcdr::MemberId(2),
|
||||
data.XNModelSt(), current_alignment);
|
||||
|
||||
calculated_size += calculator.calculate_member_serialized_size(eprosima::fastcdr::MemberId(3),
|
||||
data.XNModelThID(), current_alignment);
|
||||
|
||||
calculated_size += calculator.calculate_member_serialized_size(eprosima::fastcdr::MemberId(4),
|
||||
data.XNModelNode(), current_alignment);
|
||||
|
||||
calculated_size += calculator.calculate_member_serialized_size(eprosima::fastcdr::MemberId(5),
|
||||
data.XNModelPro(), current_alignment);
|
||||
|
||||
calculated_size += calculator.calculate_member_serialized_size(eprosima::fastcdr::MemberId(6),
|
||||
data.XNModelRunCnt(), current_alignment);
|
||||
|
||||
calculated_size += calculator.calculate_member_serialized_size(eprosima::fastcdr::MemberId(7),
|
||||
data.XNMdlCurFreq(), current_alignment);
|
||||
|
||||
calculated_size += calculator.calculate_member_serialized_size(eprosima::fastcdr::MemberId(8),
|
||||
data.XNMdlSetFreq(), current_alignment);
|
||||
|
||||
|
||||
calculated_size += calculator.end_calculate_type_serialized_size(previous_encoding, current_alignment);
|
||||
|
||||
return calculated_size;
|
||||
}
|
||||
|
||||
template<>
|
||||
eProsima_user_DllExport void serialize(
|
||||
eprosima::fastcdr::Cdr& scdr,
|
||||
const XNSim::XNSimStatus::XNModelStatus& data)
|
||||
{
|
||||
using namespace XNSim::XNSimStatus;
|
||||
|
||||
eprosima::fastcdr::Cdr::state current_state(scdr);
|
||||
scdr.begin_serialize_type(current_state,
|
||||
eprosima::fastcdr::CdrVersion::XCDRv2 == scdr.get_cdr_version() ?
|
||||
eprosima::fastcdr::EncodingAlgorithmFlag::DELIMIT_CDR2 :
|
||||
eprosima::fastcdr::EncodingAlgorithmFlag::PLAIN_CDR);
|
||||
|
||||
scdr
|
||||
<< eprosima::fastcdr::MemberId(0) << data.XNModelName()
|
||||
<< eprosima::fastcdr::MemberId(1) << data.XNModelID()
|
||||
<< eprosima::fastcdr::MemberId(2) << data.XNModelSt()
|
||||
<< eprosima::fastcdr::MemberId(3) << data.XNModelThID()
|
||||
<< eprosima::fastcdr::MemberId(4) << data.XNModelNode()
|
||||
<< eprosima::fastcdr::MemberId(5) << data.XNModelPro()
|
||||
<< eprosima::fastcdr::MemberId(6) << data.XNModelRunCnt()
|
||||
<< eprosima::fastcdr::MemberId(7) << data.XNMdlCurFreq()
|
||||
<< eprosima::fastcdr::MemberId(8) << data.XNMdlSetFreq()
|
||||
;
|
||||
scdr.end_serialize_type(current_state);
|
||||
}
|
||||
|
||||
template<>
|
||||
eProsima_user_DllExport void deserialize(
|
||||
eprosima::fastcdr::Cdr& cdr,
|
||||
XNSim::XNSimStatus::XNModelStatus& data)
|
||||
{
|
||||
using namespace XNSim::XNSimStatus;
|
||||
|
||||
cdr.deserialize_type(eprosima::fastcdr::CdrVersion::XCDRv2 == cdr.get_cdr_version() ?
|
||||
eprosima::fastcdr::EncodingAlgorithmFlag::DELIMIT_CDR2 :
|
||||
eprosima::fastcdr::EncodingAlgorithmFlag::PLAIN_CDR,
|
||||
[&data](eprosima::fastcdr::Cdr& dcdr, const eprosima::fastcdr::MemberId& mid) -> bool
|
||||
{
|
||||
bool ret_value = true;
|
||||
switch (mid.id)
|
||||
{
|
||||
case 0:
|
||||
dcdr >> data.XNModelName();
|
||||
break;
|
||||
|
||||
case 1:
|
||||
dcdr >> data.XNModelID();
|
||||
break;
|
||||
|
||||
case 2:
|
||||
dcdr >> data.XNModelSt();
|
||||
break;
|
||||
|
||||
case 3:
|
||||
dcdr >> data.XNModelThID();
|
||||
break;
|
||||
|
||||
case 4:
|
||||
dcdr >> data.XNModelNode();
|
||||
break;
|
||||
|
||||
case 5:
|
||||
dcdr >> data.XNModelPro();
|
||||
break;
|
||||
|
||||
case 6:
|
||||
dcdr >> data.XNModelRunCnt();
|
||||
break;
|
||||
|
||||
case 7:
|
||||
dcdr >> data.XNMdlCurFreq();
|
||||
break;
|
||||
|
||||
case 8:
|
||||
dcdr >> data.XNMdlSetFreq();
|
||||
break;
|
||||
|
||||
default:
|
||||
ret_value = false;
|
||||
break;
|
||||
}
|
||||
return ret_value;
|
||||
});
|
||||
}
|
||||
|
||||
void serialize_key(
|
||||
eprosima::fastcdr::Cdr& scdr,
|
||||
const XNSim::XNSimStatus::XNModelStatus& data)
|
||||
{
|
||||
using namespace XNSim::XNSimStatus;
|
||||
|
||||
static_cast<void>(scdr);
|
||||
static_cast<void>(data);
|
||||
scdr << data.XNModelName();
|
||||
|
||||
scdr << data.XNModelID();
|
||||
|
||||
scdr << data.XNModelSt();
|
||||
|
||||
scdr << data.XNModelThID();
|
||||
|
||||
scdr << data.XNModelNode();
|
||||
|
||||
scdr << data.XNModelPro();
|
||||
|
||||
scdr << data.XNModelRunCnt();
|
||||
|
||||
scdr << data.XNMdlCurFreq();
|
||||
|
||||
scdr << data.XNMdlSetFreq();
|
||||
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
eProsima_user_DllExport size_t calculate_serialized_size(
|
||||
eprosima::fastcdr::CdrSizeCalculator& calculator,
|
||||
const XNSim::XNSimControl::XNRuntimeControl& data,
|
||||
size_t& current_alignment)
|
||||
{
|
||||
using namespace XNSim::XNSimControl;
|
||||
|
||||
static_cast<void>(data);
|
||||
|
||||
eprosima::fastcdr::EncodingAlgorithmFlag previous_encoding = calculator.get_encoding();
|
||||
size_t calculated_size {calculator.begin_calculate_type_serialized_size(
|
||||
eprosima::fastcdr::CdrVersion::XCDRv2 == calculator.get_cdr_version() ?
|
||||
eprosima::fastcdr::EncodingAlgorithmFlag::DELIMIT_CDR2 :
|
||||
eprosima::fastcdr::EncodingAlgorithmFlag::PLAIN_CDR,
|
||||
current_alignment)};
|
||||
|
||||
|
||||
calculated_size += calculator.calculate_member_serialized_size(eprosima::fastcdr::MemberId(0),
|
||||
data.XNSimCmd(), current_alignment);
|
||||
|
||||
calculated_size += calculator.calculate_member_serialized_size(eprosima::fastcdr::MemberId(1),
|
||||
data.XNThrCmd(), current_alignment);
|
||||
|
||||
|
||||
calculated_size += calculator.end_calculate_type_serialized_size(previous_encoding, current_alignment);
|
||||
|
||||
return calculated_size;
|
||||
}
|
||||
|
||||
template<>
|
||||
eProsima_user_DllExport void serialize(
|
||||
eprosima::fastcdr::Cdr& scdr,
|
||||
const XNSim::XNSimControl::XNRuntimeControl& data)
|
||||
{
|
||||
using namespace XNSim::XNSimControl;
|
||||
|
||||
eprosima::fastcdr::Cdr::state current_state(scdr);
|
||||
scdr.begin_serialize_type(current_state,
|
||||
eprosima::fastcdr::CdrVersion::XCDRv2 == scdr.get_cdr_version() ?
|
||||
eprosima::fastcdr::EncodingAlgorithmFlag::DELIMIT_CDR2 :
|
||||
eprosima::fastcdr::EncodingAlgorithmFlag::PLAIN_CDR);
|
||||
|
||||
scdr
|
||||
<< eprosima::fastcdr::MemberId(0) << data.XNSimCmd()
|
||||
<< eprosima::fastcdr::MemberId(1) << data.XNThrCmd()
|
||||
;
|
||||
scdr.end_serialize_type(current_state);
|
||||
}
|
||||
|
||||
template<>
|
||||
eProsima_user_DllExport void deserialize(
|
||||
eprosima::fastcdr::Cdr& cdr,
|
||||
XNSim::XNSimControl::XNRuntimeControl& data)
|
||||
{
|
||||
using namespace XNSim::XNSimControl;
|
||||
|
||||
cdr.deserialize_type(eprosima::fastcdr::CdrVersion::XCDRv2 == cdr.get_cdr_version() ?
|
||||
eprosima::fastcdr::EncodingAlgorithmFlag::DELIMIT_CDR2 :
|
||||
eprosima::fastcdr::EncodingAlgorithmFlag::PLAIN_CDR,
|
||||
[&data](eprosima::fastcdr::Cdr& dcdr, const eprosima::fastcdr::MemberId& mid) -> bool
|
||||
{
|
||||
bool ret_value = true;
|
||||
switch (mid.id)
|
||||
{
|
||||
case 0:
|
||||
dcdr >> data.XNSimCmd();
|
||||
break;
|
||||
|
||||
case 1:
|
||||
dcdr >> data.XNThrCmd();
|
||||
break;
|
||||
|
||||
default:
|
||||
ret_value = false;
|
||||
break;
|
||||
}
|
||||
return ret_value;
|
||||
});
|
||||
}
|
||||
|
||||
void serialize_key(
|
||||
eprosima::fastcdr::Cdr& scdr,
|
||||
const XNSim::XNSimControl::XNRuntimeControl& data)
|
||||
{
|
||||
using namespace XNSim::XNSimControl;
|
||||
|
||||
static_cast<void>(scdr);
|
||||
static_cast<void>(data);
|
||||
scdr << data.XNSimCmd();
|
||||
|
||||
scdr << data.XNThrCmd();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace fastcdr
|
||||
} // namespace eprosima
|
||||
|
||||
#endif // FAST_DDS_GENERATED__XNSIM_XNSIMCONTROL_XNSIMSTATUSCDRAUX_IPP
|
||||
|
955
XNCore_Win/XNIDL/XNSimStatusPubSubTypes.cxx
Normal file
955
XNCore_Win/XNIDL/XNSimStatusPubSubTypes.cxx
Normal file
@ -0,0 +1,955 @@
|
||||
// Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima).
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/*!
|
||||
* @file XNSimStatusPubSubTypes.cpp
|
||||
* This header file contains the implementation of the serialization functions.
|
||||
*
|
||||
* This file was generated by the tool fastddsgen.
|
||||
*/
|
||||
|
||||
#include "XNSimStatusPubSubTypes.hpp"
|
||||
|
||||
#include <fastdds/dds/log/Log.hpp>
|
||||
#include <fastdds/rtps/common/CdrSerialization.hpp>
|
||||
|
||||
#include "XNSimStatusCdrAux.hpp"
|
||||
#include "XNSimStatusTypeObjectSupport.hpp"
|
||||
|
||||
using SerializedPayload_t = eprosima::fastdds::rtps::SerializedPayload_t;
|
||||
using InstanceHandle_t = eprosima::fastdds::rtps::InstanceHandle_t;
|
||||
using DataRepresentationId_t = eprosima::fastdds::dds::DataRepresentationId_t;
|
||||
|
||||
namespace XNSim {
|
||||
namespace XNSimStatus {
|
||||
XNCoreStatusPubSubType::XNCoreStatusPubSubType()
|
||||
{
|
||||
set_name("XNSim::XNSimStatus::XNCoreStatus");
|
||||
uint32_t type_size = XNSim_XNSimStatus_XNCoreStatus_max_cdr_typesize;
|
||||
type_size += static_cast<uint32_t>(eprosima::fastcdr::Cdr::alignment(type_size, 4)); /* possible submessage alignment */
|
||||
max_serialized_type_size = type_size + 4; /*encapsulation*/
|
||||
is_compute_key_provided = false;
|
||||
uint32_t key_length = XNSim_XNSimStatus_XNCoreStatus_max_key_cdr_typesize > 16 ? XNSim_XNSimStatus_XNCoreStatus_max_key_cdr_typesize : 16;
|
||||
key_buffer_ = reinterpret_cast<unsigned char*>(malloc(key_length));
|
||||
memset(key_buffer_, 0, key_length);
|
||||
}
|
||||
|
||||
XNCoreStatusPubSubType::~XNCoreStatusPubSubType()
|
||||
{
|
||||
if (key_buffer_ != nullptr)
|
||||
{
|
||||
free(key_buffer_);
|
||||
}
|
||||
}
|
||||
|
||||
bool XNCoreStatusPubSubType::serialize(
|
||||
const void* const data,
|
||||
SerializedPayload_t& payload,
|
||||
DataRepresentationId_t data_representation)
|
||||
{
|
||||
const XNCoreStatus* p_type = static_cast<const XNCoreStatus*>(data);
|
||||
|
||||
// Object that manages the raw buffer.
|
||||
eprosima::fastcdr::FastBuffer fastbuffer(reinterpret_cast<char*>(payload.data), payload.max_size);
|
||||
// Object that serializes the data.
|
||||
eprosima::fastcdr::Cdr ser(fastbuffer, eprosima::fastcdr::Cdr::DEFAULT_ENDIAN,
|
||||
data_representation == DataRepresentationId_t::XCDR_DATA_REPRESENTATION ?
|
||||
eprosima::fastcdr::CdrVersion::XCDRv1 : eprosima::fastcdr::CdrVersion::XCDRv2);
|
||||
payload.encapsulation = ser.endianness() == eprosima::fastcdr::Cdr::BIG_ENDIANNESS ? CDR_BE : CDR_LE;
|
||||
ser.set_encoding_flag(
|
||||
data_representation == DataRepresentationId_t::XCDR_DATA_REPRESENTATION ?
|
||||
eprosima::fastcdr::EncodingAlgorithmFlag::PLAIN_CDR :
|
||||
eprosima::fastcdr::EncodingAlgorithmFlag::DELIMIT_CDR2);
|
||||
|
||||
try
|
||||
{
|
||||
// Serialize encapsulation
|
||||
ser.serialize_encapsulation();
|
||||
// Serialize the object.
|
||||
ser << *p_type;
|
||||
ser.set_dds_cdr_options({0,0});
|
||||
}
|
||||
catch (eprosima::fastcdr::exception::Exception& /*exception*/)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the serialized length
|
||||
payload.length = static_cast<uint32_t>(ser.get_serialized_data_length());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool XNCoreStatusPubSubType::deserialize(
|
||||
SerializedPayload_t& payload,
|
||||
void* data)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Convert DATA to pointer of your type
|
||||
XNCoreStatus* p_type = static_cast<XNCoreStatus*>(data);
|
||||
|
||||
// Object that manages the raw buffer.
|
||||
eprosima::fastcdr::FastBuffer fastbuffer(reinterpret_cast<char*>(payload.data), payload.length);
|
||||
|
||||
// Object that deserializes the data.
|
||||
eprosima::fastcdr::Cdr deser(fastbuffer, eprosima::fastcdr::Cdr::DEFAULT_ENDIAN);
|
||||
|
||||
// Deserialize encapsulation.
|
||||
deser.read_encapsulation();
|
||||
payload.encapsulation = deser.endianness() == eprosima::fastcdr::Cdr::BIG_ENDIANNESS ? CDR_BE : CDR_LE;
|
||||
|
||||
// Deserialize the object.
|
||||
deser >> *p_type;
|
||||
}
|
||||
catch (eprosima::fastcdr::exception::Exception& /*exception*/)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t XNCoreStatusPubSubType::calculate_serialized_size(
|
||||
const void* const data,
|
||||
DataRepresentationId_t data_representation)
|
||||
{
|
||||
try
|
||||
{
|
||||
eprosima::fastcdr::CdrSizeCalculator calculator(
|
||||
data_representation == DataRepresentationId_t::XCDR_DATA_REPRESENTATION ?
|
||||
eprosima::fastcdr::CdrVersion::XCDRv1 :eprosima::fastcdr::CdrVersion::XCDRv2);
|
||||
size_t current_alignment {0};
|
||||
return static_cast<uint32_t>(calculator.calculate_serialized_size(
|
||||
*static_cast<const XNCoreStatus*>(data), current_alignment)) +
|
||||
4u /*encapsulation*/;
|
||||
}
|
||||
catch (eprosima::fastcdr::exception::Exception& /*exception*/)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void* XNCoreStatusPubSubType::create_data()
|
||||
{
|
||||
return reinterpret_cast<void*>(new XNCoreStatus());
|
||||
}
|
||||
|
||||
void XNCoreStatusPubSubType::delete_data(
|
||||
void* data)
|
||||
{
|
||||
delete(reinterpret_cast<XNCoreStatus*>(data));
|
||||
}
|
||||
|
||||
bool XNCoreStatusPubSubType::compute_key(
|
||||
SerializedPayload_t& payload,
|
||||
InstanceHandle_t& handle,
|
||||
bool force_md5)
|
||||
{
|
||||
if (!is_compute_key_provided)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
XNCoreStatus data;
|
||||
if (deserialize(payload, static_cast<void*>(&data)))
|
||||
{
|
||||
return compute_key(static_cast<void*>(&data), handle, force_md5);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool XNCoreStatusPubSubType::compute_key(
|
||||
const void* const data,
|
||||
InstanceHandle_t& handle,
|
||||
bool force_md5)
|
||||
{
|
||||
if (!is_compute_key_provided)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const XNCoreStatus* p_type = static_cast<const XNCoreStatus*>(data);
|
||||
|
||||
// Object that manages the raw buffer.
|
||||
eprosima::fastcdr::FastBuffer fastbuffer(reinterpret_cast<char*>(key_buffer_),
|
||||
XNSim_XNSimStatus_XNCoreStatus_max_key_cdr_typesize);
|
||||
|
||||
// Object that serializes the data.
|
||||
eprosima::fastcdr::Cdr ser(fastbuffer, eprosima::fastcdr::Cdr::BIG_ENDIANNESS, eprosima::fastcdr::CdrVersion::XCDRv2);
|
||||
ser.set_encoding_flag(eprosima::fastcdr::EncodingAlgorithmFlag::PLAIN_CDR2);
|
||||
eprosima::fastcdr::serialize_key(ser, *p_type);
|
||||
if (force_md5 || XNSim_XNSimStatus_XNCoreStatus_max_key_cdr_typesize > 16)
|
||||
{
|
||||
md5_.init();
|
||||
md5_.update(key_buffer_, static_cast<unsigned int>(ser.get_serialized_data_length()));
|
||||
md5_.finalize();
|
||||
for (uint8_t i = 0; i < 16; ++i)
|
||||
{
|
||||
handle.value[i] = md5_.digest[i];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (uint8_t i = 0; i < 16; ++i)
|
||||
{
|
||||
handle.value[i] = key_buffer_[i];
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void XNCoreStatusPubSubType::register_type_object_representation()
|
||||
{
|
||||
register_XNCoreStatus_type_identifier(type_identifiers_);
|
||||
}
|
||||
|
||||
XNEngineStatusPubSubType::XNEngineStatusPubSubType()
|
||||
{
|
||||
set_name("XNSim::XNSimStatus::XNEngineStatus");
|
||||
uint32_t type_size = XNSim_XNSimStatus_XNEngineStatus_max_cdr_typesize;
|
||||
type_size += static_cast<uint32_t>(eprosima::fastcdr::Cdr::alignment(type_size, 4)); /* possible submessage alignment */
|
||||
max_serialized_type_size = type_size + 4; /*encapsulation*/
|
||||
is_compute_key_provided = false;
|
||||
uint32_t key_length = XNSim_XNSimStatus_XNEngineStatus_max_key_cdr_typesize > 16 ? XNSim_XNSimStatus_XNEngineStatus_max_key_cdr_typesize : 16;
|
||||
key_buffer_ = reinterpret_cast<unsigned char*>(malloc(key_length));
|
||||
memset(key_buffer_, 0, key_length);
|
||||
}
|
||||
|
||||
XNEngineStatusPubSubType::~XNEngineStatusPubSubType()
|
||||
{
|
||||
if (key_buffer_ != nullptr)
|
||||
{
|
||||
free(key_buffer_);
|
||||
}
|
||||
}
|
||||
|
||||
bool XNEngineStatusPubSubType::serialize(
|
||||
const void* const data,
|
||||
SerializedPayload_t& payload,
|
||||
DataRepresentationId_t data_representation)
|
||||
{
|
||||
const XNEngineStatus* p_type = static_cast<const XNEngineStatus*>(data);
|
||||
|
||||
// Object that manages the raw buffer.
|
||||
eprosima::fastcdr::FastBuffer fastbuffer(reinterpret_cast<char*>(payload.data), payload.max_size);
|
||||
// Object that serializes the data.
|
||||
eprosima::fastcdr::Cdr ser(fastbuffer, eprosima::fastcdr::Cdr::DEFAULT_ENDIAN,
|
||||
data_representation == DataRepresentationId_t::XCDR_DATA_REPRESENTATION ?
|
||||
eprosima::fastcdr::CdrVersion::XCDRv1 : eprosima::fastcdr::CdrVersion::XCDRv2);
|
||||
payload.encapsulation = ser.endianness() == eprosima::fastcdr::Cdr::BIG_ENDIANNESS ? CDR_BE : CDR_LE;
|
||||
ser.set_encoding_flag(
|
||||
data_representation == DataRepresentationId_t::XCDR_DATA_REPRESENTATION ?
|
||||
eprosima::fastcdr::EncodingAlgorithmFlag::PLAIN_CDR :
|
||||
eprosima::fastcdr::EncodingAlgorithmFlag::DELIMIT_CDR2);
|
||||
|
||||
try
|
||||
{
|
||||
// Serialize encapsulation
|
||||
ser.serialize_encapsulation();
|
||||
// Serialize the object.
|
||||
ser << *p_type;
|
||||
ser.set_dds_cdr_options({0,0});
|
||||
}
|
||||
catch (eprosima::fastcdr::exception::Exception& /*exception*/)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the serialized length
|
||||
payload.length = static_cast<uint32_t>(ser.get_serialized_data_length());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool XNEngineStatusPubSubType::deserialize(
|
||||
SerializedPayload_t& payload,
|
||||
void* data)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Convert DATA to pointer of your type
|
||||
XNEngineStatus* p_type = static_cast<XNEngineStatus*>(data);
|
||||
|
||||
// Object that manages the raw buffer.
|
||||
eprosima::fastcdr::FastBuffer fastbuffer(reinterpret_cast<char*>(payload.data), payload.length);
|
||||
|
||||
// Object that deserializes the data.
|
||||
eprosima::fastcdr::Cdr deser(fastbuffer, eprosima::fastcdr::Cdr::DEFAULT_ENDIAN);
|
||||
|
||||
// Deserialize encapsulation.
|
||||
deser.read_encapsulation();
|
||||
payload.encapsulation = deser.endianness() == eprosima::fastcdr::Cdr::BIG_ENDIANNESS ? CDR_BE : CDR_LE;
|
||||
|
||||
// Deserialize the object.
|
||||
deser >> *p_type;
|
||||
}
|
||||
catch (eprosima::fastcdr::exception::Exception& /*exception*/)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t XNEngineStatusPubSubType::calculate_serialized_size(
|
||||
const void* const data,
|
||||
DataRepresentationId_t data_representation)
|
||||
{
|
||||
try
|
||||
{
|
||||
eprosima::fastcdr::CdrSizeCalculator calculator(
|
||||
data_representation == DataRepresentationId_t::XCDR_DATA_REPRESENTATION ?
|
||||
eprosima::fastcdr::CdrVersion::XCDRv1 :eprosima::fastcdr::CdrVersion::XCDRv2);
|
||||
size_t current_alignment {0};
|
||||
return static_cast<uint32_t>(calculator.calculate_serialized_size(
|
||||
*static_cast<const XNEngineStatus*>(data), current_alignment)) +
|
||||
4u /*encapsulation*/;
|
||||
}
|
||||
catch (eprosima::fastcdr::exception::Exception& /*exception*/)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void* XNEngineStatusPubSubType::create_data()
|
||||
{
|
||||
return reinterpret_cast<void*>(new XNEngineStatus());
|
||||
}
|
||||
|
||||
void XNEngineStatusPubSubType::delete_data(
|
||||
void* data)
|
||||
{
|
||||
delete(reinterpret_cast<XNEngineStatus*>(data));
|
||||
}
|
||||
|
||||
bool XNEngineStatusPubSubType::compute_key(
|
||||
SerializedPayload_t& payload,
|
||||
InstanceHandle_t& handle,
|
||||
bool force_md5)
|
||||
{
|
||||
if (!is_compute_key_provided)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
XNEngineStatus data;
|
||||
if (deserialize(payload, static_cast<void*>(&data)))
|
||||
{
|
||||
return compute_key(static_cast<void*>(&data), handle, force_md5);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool XNEngineStatusPubSubType::compute_key(
|
||||
const void* const data,
|
||||
InstanceHandle_t& handle,
|
||||
bool force_md5)
|
||||
{
|
||||
if (!is_compute_key_provided)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const XNEngineStatus* p_type = static_cast<const XNEngineStatus*>(data);
|
||||
|
||||
// Object that manages the raw buffer.
|
||||
eprosima::fastcdr::FastBuffer fastbuffer(reinterpret_cast<char*>(key_buffer_),
|
||||
XNSim_XNSimStatus_XNEngineStatus_max_key_cdr_typesize);
|
||||
|
||||
// Object that serializes the data.
|
||||
eprosima::fastcdr::Cdr ser(fastbuffer, eprosima::fastcdr::Cdr::BIG_ENDIANNESS, eprosima::fastcdr::CdrVersion::XCDRv2);
|
||||
ser.set_encoding_flag(eprosima::fastcdr::EncodingAlgorithmFlag::PLAIN_CDR2);
|
||||
eprosima::fastcdr::serialize_key(ser, *p_type);
|
||||
if (force_md5 || XNSim_XNSimStatus_XNEngineStatus_max_key_cdr_typesize > 16)
|
||||
{
|
||||
md5_.init();
|
||||
md5_.update(key_buffer_, static_cast<unsigned int>(ser.get_serialized_data_length()));
|
||||
md5_.finalize();
|
||||
for (uint8_t i = 0; i < 16; ++i)
|
||||
{
|
||||
handle.value[i] = md5_.digest[i];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (uint8_t i = 0; i < 16; ++i)
|
||||
{
|
||||
handle.value[i] = key_buffer_[i];
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void XNEngineStatusPubSubType::register_type_object_representation()
|
||||
{
|
||||
register_XNEngineStatus_type_identifier(type_identifiers_);
|
||||
}
|
||||
|
||||
XNThreadStatusPubSubType::XNThreadStatusPubSubType()
|
||||
{
|
||||
set_name("XNSim::XNSimStatus::XNThreadStatus");
|
||||
uint32_t type_size = XNSim_XNSimStatus_XNThreadStatus_max_cdr_typesize;
|
||||
type_size += static_cast<uint32_t>(eprosima::fastcdr::Cdr::alignment(type_size, 4)); /* possible submessage alignment */
|
||||
max_serialized_type_size = type_size + 4; /*encapsulation*/
|
||||
is_compute_key_provided = false;
|
||||
uint32_t key_length = XNSim_XNSimStatus_XNThreadStatus_max_key_cdr_typesize > 16 ? XNSim_XNSimStatus_XNThreadStatus_max_key_cdr_typesize : 16;
|
||||
key_buffer_ = reinterpret_cast<unsigned char*>(malloc(key_length));
|
||||
memset(key_buffer_, 0, key_length);
|
||||
}
|
||||
|
||||
XNThreadStatusPubSubType::~XNThreadStatusPubSubType()
|
||||
{
|
||||
if (key_buffer_ != nullptr)
|
||||
{
|
||||
free(key_buffer_);
|
||||
}
|
||||
}
|
||||
|
||||
bool XNThreadStatusPubSubType::serialize(
|
||||
const void* const data,
|
||||
SerializedPayload_t& payload,
|
||||
DataRepresentationId_t data_representation)
|
||||
{
|
||||
const XNThreadStatus* p_type = static_cast<const XNThreadStatus*>(data);
|
||||
|
||||
// Object that manages the raw buffer.
|
||||
eprosima::fastcdr::FastBuffer fastbuffer(reinterpret_cast<char*>(payload.data), payload.max_size);
|
||||
// Object that serializes the data.
|
||||
eprosima::fastcdr::Cdr ser(fastbuffer, eprosima::fastcdr::Cdr::DEFAULT_ENDIAN,
|
||||
data_representation == DataRepresentationId_t::XCDR_DATA_REPRESENTATION ?
|
||||
eprosima::fastcdr::CdrVersion::XCDRv1 : eprosima::fastcdr::CdrVersion::XCDRv2);
|
||||
payload.encapsulation = ser.endianness() == eprosima::fastcdr::Cdr::BIG_ENDIANNESS ? CDR_BE : CDR_LE;
|
||||
ser.set_encoding_flag(
|
||||
data_representation == DataRepresentationId_t::XCDR_DATA_REPRESENTATION ?
|
||||
eprosima::fastcdr::EncodingAlgorithmFlag::PLAIN_CDR :
|
||||
eprosima::fastcdr::EncodingAlgorithmFlag::DELIMIT_CDR2);
|
||||
|
||||
try
|
||||
{
|
||||
// Serialize encapsulation
|
||||
ser.serialize_encapsulation();
|
||||
// Serialize the object.
|
||||
ser << *p_type;
|
||||
ser.set_dds_cdr_options({0,0});
|
||||
}
|
||||
catch (eprosima::fastcdr::exception::Exception& /*exception*/)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the serialized length
|
||||
payload.length = static_cast<uint32_t>(ser.get_serialized_data_length());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool XNThreadStatusPubSubType::deserialize(
|
||||
SerializedPayload_t& payload,
|
||||
void* data)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Convert DATA to pointer of your type
|
||||
XNThreadStatus* p_type = static_cast<XNThreadStatus*>(data);
|
||||
|
||||
// Object that manages the raw buffer.
|
||||
eprosima::fastcdr::FastBuffer fastbuffer(reinterpret_cast<char*>(payload.data), payload.length);
|
||||
|
||||
// Object that deserializes the data.
|
||||
eprosima::fastcdr::Cdr deser(fastbuffer, eprosima::fastcdr::Cdr::DEFAULT_ENDIAN);
|
||||
|
||||
// Deserialize encapsulation.
|
||||
deser.read_encapsulation();
|
||||
payload.encapsulation = deser.endianness() == eprosima::fastcdr::Cdr::BIG_ENDIANNESS ? CDR_BE : CDR_LE;
|
||||
|
||||
// Deserialize the object.
|
||||
deser >> *p_type;
|
||||
}
|
||||
catch (eprosima::fastcdr::exception::Exception& /*exception*/)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t XNThreadStatusPubSubType::calculate_serialized_size(
|
||||
const void* const data,
|
||||
DataRepresentationId_t data_representation)
|
||||
{
|
||||
try
|
||||
{
|
||||
eprosima::fastcdr::CdrSizeCalculator calculator(
|
||||
data_representation == DataRepresentationId_t::XCDR_DATA_REPRESENTATION ?
|
||||
eprosima::fastcdr::CdrVersion::XCDRv1 :eprosima::fastcdr::CdrVersion::XCDRv2);
|
||||
size_t current_alignment {0};
|
||||
return static_cast<uint32_t>(calculator.calculate_serialized_size(
|
||||
*static_cast<const XNThreadStatus*>(data), current_alignment)) +
|
||||
4u /*encapsulation*/;
|
||||
}
|
||||
catch (eprosima::fastcdr::exception::Exception& /*exception*/)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void* XNThreadStatusPubSubType::create_data()
|
||||
{
|
||||
return reinterpret_cast<void*>(new XNThreadStatus());
|
||||
}
|
||||
|
||||
void XNThreadStatusPubSubType::delete_data(
|
||||
void* data)
|
||||
{
|
||||
delete(reinterpret_cast<XNThreadStatus*>(data));
|
||||
}
|
||||
|
||||
bool XNThreadStatusPubSubType::compute_key(
|
||||
SerializedPayload_t& payload,
|
||||
InstanceHandle_t& handle,
|
||||
bool force_md5)
|
||||
{
|
||||
if (!is_compute_key_provided)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
XNThreadStatus data;
|
||||
if (deserialize(payload, static_cast<void*>(&data)))
|
||||
{
|
||||
return compute_key(static_cast<void*>(&data), handle, force_md5);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool XNThreadStatusPubSubType::compute_key(
|
||||
const void* const data,
|
||||
InstanceHandle_t& handle,
|
||||
bool force_md5)
|
||||
{
|
||||
if (!is_compute_key_provided)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const XNThreadStatus* p_type = static_cast<const XNThreadStatus*>(data);
|
||||
|
||||
// Object that manages the raw buffer.
|
||||
eprosima::fastcdr::FastBuffer fastbuffer(reinterpret_cast<char*>(key_buffer_),
|
||||
XNSim_XNSimStatus_XNThreadStatus_max_key_cdr_typesize);
|
||||
|
||||
// Object that serializes the data.
|
||||
eprosima::fastcdr::Cdr ser(fastbuffer, eprosima::fastcdr::Cdr::BIG_ENDIANNESS, eprosima::fastcdr::CdrVersion::XCDRv2);
|
||||
ser.set_encoding_flag(eprosima::fastcdr::EncodingAlgorithmFlag::PLAIN_CDR2);
|
||||
eprosima::fastcdr::serialize_key(ser, *p_type);
|
||||
if (force_md5 || XNSim_XNSimStatus_XNThreadStatus_max_key_cdr_typesize > 16)
|
||||
{
|
||||
md5_.init();
|
||||
md5_.update(key_buffer_, static_cast<unsigned int>(ser.get_serialized_data_length()));
|
||||
md5_.finalize();
|
||||
for (uint8_t i = 0; i < 16; ++i)
|
||||
{
|
||||
handle.value[i] = md5_.digest[i];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (uint8_t i = 0; i < 16; ++i)
|
||||
{
|
||||
handle.value[i] = key_buffer_[i];
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void XNThreadStatusPubSubType::register_type_object_representation()
|
||||
{
|
||||
register_XNThreadStatus_type_identifier(type_identifiers_);
|
||||
}
|
||||
|
||||
XNModelStatusPubSubType::XNModelStatusPubSubType()
|
||||
{
|
||||
set_name("XNSim::XNSimStatus::XNModelStatus");
|
||||
uint32_t type_size = XNSim_XNSimStatus_XNModelStatus_max_cdr_typesize;
|
||||
type_size += static_cast<uint32_t>(eprosima::fastcdr::Cdr::alignment(type_size, 4)); /* possible submessage alignment */
|
||||
max_serialized_type_size = type_size + 4; /*encapsulation*/
|
||||
is_compute_key_provided = false;
|
||||
uint32_t key_length = XNSim_XNSimStatus_XNModelStatus_max_key_cdr_typesize > 16 ? XNSim_XNSimStatus_XNModelStatus_max_key_cdr_typesize : 16;
|
||||
key_buffer_ = reinterpret_cast<unsigned char*>(malloc(key_length));
|
||||
memset(key_buffer_, 0, key_length);
|
||||
}
|
||||
|
||||
XNModelStatusPubSubType::~XNModelStatusPubSubType()
|
||||
{
|
||||
if (key_buffer_ != nullptr)
|
||||
{
|
||||
free(key_buffer_);
|
||||
}
|
||||
}
|
||||
|
||||
bool XNModelStatusPubSubType::serialize(
|
||||
const void* const data,
|
||||
SerializedPayload_t& payload,
|
||||
DataRepresentationId_t data_representation)
|
||||
{
|
||||
const XNModelStatus* p_type = static_cast<const XNModelStatus*>(data);
|
||||
|
||||
// Object that manages the raw buffer.
|
||||
eprosima::fastcdr::FastBuffer fastbuffer(reinterpret_cast<char*>(payload.data), payload.max_size);
|
||||
// Object that serializes the data.
|
||||
eprosima::fastcdr::Cdr ser(fastbuffer, eprosima::fastcdr::Cdr::DEFAULT_ENDIAN,
|
||||
data_representation == DataRepresentationId_t::XCDR_DATA_REPRESENTATION ?
|
||||
eprosima::fastcdr::CdrVersion::XCDRv1 : eprosima::fastcdr::CdrVersion::XCDRv2);
|
||||
payload.encapsulation = ser.endianness() == eprosima::fastcdr::Cdr::BIG_ENDIANNESS ? CDR_BE : CDR_LE;
|
||||
ser.set_encoding_flag(
|
||||
data_representation == DataRepresentationId_t::XCDR_DATA_REPRESENTATION ?
|
||||
eprosima::fastcdr::EncodingAlgorithmFlag::PLAIN_CDR :
|
||||
eprosima::fastcdr::EncodingAlgorithmFlag::DELIMIT_CDR2);
|
||||
|
||||
try
|
||||
{
|
||||
// Serialize encapsulation
|
||||
ser.serialize_encapsulation();
|
||||
// Serialize the object.
|
||||
ser << *p_type;
|
||||
ser.set_dds_cdr_options({0,0});
|
||||
}
|
||||
catch (eprosima::fastcdr::exception::Exception& /*exception*/)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the serialized length
|
||||
payload.length = static_cast<uint32_t>(ser.get_serialized_data_length());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool XNModelStatusPubSubType::deserialize(
|
||||
SerializedPayload_t& payload,
|
||||
void* data)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Convert DATA to pointer of your type
|
||||
XNModelStatus* p_type = static_cast<XNModelStatus*>(data);
|
||||
|
||||
// Object that manages the raw buffer.
|
||||
eprosima::fastcdr::FastBuffer fastbuffer(reinterpret_cast<char*>(payload.data), payload.length);
|
||||
|
||||
// Object that deserializes the data.
|
||||
eprosima::fastcdr::Cdr deser(fastbuffer, eprosima::fastcdr::Cdr::DEFAULT_ENDIAN);
|
||||
|
||||
// Deserialize encapsulation.
|
||||
deser.read_encapsulation();
|
||||
payload.encapsulation = deser.endianness() == eprosima::fastcdr::Cdr::BIG_ENDIANNESS ? CDR_BE : CDR_LE;
|
||||
|
||||
// Deserialize the object.
|
||||
deser >> *p_type;
|
||||
}
|
||||
catch (eprosima::fastcdr::exception::Exception& /*exception*/)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t XNModelStatusPubSubType::calculate_serialized_size(
|
||||
const void* const data,
|
||||
DataRepresentationId_t data_representation)
|
||||
{
|
||||
try
|
||||
{
|
||||
eprosima::fastcdr::CdrSizeCalculator calculator(
|
||||
data_representation == DataRepresentationId_t::XCDR_DATA_REPRESENTATION ?
|
||||
eprosima::fastcdr::CdrVersion::XCDRv1 :eprosima::fastcdr::CdrVersion::XCDRv2);
|
||||
size_t current_alignment {0};
|
||||
return static_cast<uint32_t>(calculator.calculate_serialized_size(
|
||||
*static_cast<const XNModelStatus*>(data), current_alignment)) +
|
||||
4u /*encapsulation*/;
|
||||
}
|
||||
catch (eprosima::fastcdr::exception::Exception& /*exception*/)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void* XNModelStatusPubSubType::create_data()
|
||||
{
|
||||
return reinterpret_cast<void*>(new XNModelStatus());
|
||||
}
|
||||
|
||||
void XNModelStatusPubSubType::delete_data(
|
||||
void* data)
|
||||
{
|
||||
delete(reinterpret_cast<XNModelStatus*>(data));
|
||||
}
|
||||
|
||||
bool XNModelStatusPubSubType::compute_key(
|
||||
SerializedPayload_t& payload,
|
||||
InstanceHandle_t& handle,
|
||||
bool force_md5)
|
||||
{
|
||||
if (!is_compute_key_provided)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
XNModelStatus data;
|
||||
if (deserialize(payload, static_cast<void*>(&data)))
|
||||
{
|
||||
return compute_key(static_cast<void*>(&data), handle, force_md5);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool XNModelStatusPubSubType::compute_key(
|
||||
const void* const data,
|
||||
InstanceHandle_t& handle,
|
||||
bool force_md5)
|
||||
{
|
||||
if (!is_compute_key_provided)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const XNModelStatus* p_type = static_cast<const XNModelStatus*>(data);
|
||||
|
||||
// Object that manages the raw buffer.
|
||||
eprosima::fastcdr::FastBuffer fastbuffer(reinterpret_cast<char*>(key_buffer_),
|
||||
XNSim_XNSimStatus_XNModelStatus_max_key_cdr_typesize);
|
||||
|
||||
// Object that serializes the data.
|
||||
eprosima::fastcdr::Cdr ser(fastbuffer, eprosima::fastcdr::Cdr::BIG_ENDIANNESS, eprosima::fastcdr::CdrVersion::XCDRv2);
|
||||
ser.set_encoding_flag(eprosima::fastcdr::EncodingAlgorithmFlag::PLAIN_CDR2);
|
||||
eprosima::fastcdr::serialize_key(ser, *p_type);
|
||||
if (force_md5 || XNSim_XNSimStatus_XNModelStatus_max_key_cdr_typesize > 16)
|
||||
{
|
||||
md5_.init();
|
||||
md5_.update(key_buffer_, static_cast<unsigned int>(ser.get_serialized_data_length()));
|
||||
md5_.finalize();
|
||||
for (uint8_t i = 0; i < 16; ++i)
|
||||
{
|
||||
handle.value[i] = md5_.digest[i];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (uint8_t i = 0; i < 16; ++i)
|
||||
{
|
||||
handle.value[i] = key_buffer_[i];
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void XNModelStatusPubSubType::register_type_object_representation()
|
||||
{
|
||||
register_XNModelStatus_type_identifier(type_identifiers_);
|
||||
}
|
||||
|
||||
} // namespace XNSimStatus
|
||||
|
||||
namespace XNSimControl {
|
||||
XNRuntimeControlPubSubType::XNRuntimeControlPubSubType()
|
||||
{
|
||||
set_name("XNSim::XNSimControl::XNRuntimeControl");
|
||||
uint32_t type_size = XNSim_XNSimControl_XNRuntimeControl_max_cdr_typesize;
|
||||
type_size += static_cast<uint32_t>(eprosima::fastcdr::Cdr::alignment(type_size, 4)); /* possible submessage alignment */
|
||||
max_serialized_type_size = type_size + 4; /*encapsulation*/
|
||||
is_compute_key_provided = false;
|
||||
uint32_t key_length = XNSim_XNSimControl_XNRuntimeControl_max_key_cdr_typesize > 16 ? XNSim_XNSimControl_XNRuntimeControl_max_key_cdr_typesize : 16;
|
||||
key_buffer_ = reinterpret_cast<unsigned char*>(malloc(key_length));
|
||||
memset(key_buffer_, 0, key_length);
|
||||
}
|
||||
|
||||
XNRuntimeControlPubSubType::~XNRuntimeControlPubSubType()
|
||||
{
|
||||
if (key_buffer_ != nullptr)
|
||||
{
|
||||
free(key_buffer_);
|
||||
}
|
||||
}
|
||||
|
||||
bool XNRuntimeControlPubSubType::serialize(
|
||||
const void* const data,
|
||||
SerializedPayload_t& payload,
|
||||
DataRepresentationId_t data_representation)
|
||||
{
|
||||
const XNRuntimeControl* p_type = static_cast<const XNRuntimeControl*>(data);
|
||||
|
||||
// Object that manages the raw buffer.
|
||||
eprosima::fastcdr::FastBuffer fastbuffer(reinterpret_cast<char*>(payload.data), payload.max_size);
|
||||
// Object that serializes the data.
|
||||
eprosima::fastcdr::Cdr ser(fastbuffer, eprosima::fastcdr::Cdr::DEFAULT_ENDIAN,
|
||||
data_representation == DataRepresentationId_t::XCDR_DATA_REPRESENTATION ?
|
||||
eprosima::fastcdr::CdrVersion::XCDRv1 : eprosima::fastcdr::CdrVersion::XCDRv2);
|
||||
payload.encapsulation = ser.endianness() == eprosima::fastcdr::Cdr::BIG_ENDIANNESS ? CDR_BE : CDR_LE;
|
||||
ser.set_encoding_flag(
|
||||
data_representation == DataRepresentationId_t::XCDR_DATA_REPRESENTATION ?
|
||||
eprosima::fastcdr::EncodingAlgorithmFlag::PLAIN_CDR :
|
||||
eprosima::fastcdr::EncodingAlgorithmFlag::DELIMIT_CDR2);
|
||||
|
||||
try
|
||||
{
|
||||
// Serialize encapsulation
|
||||
ser.serialize_encapsulation();
|
||||
// Serialize the object.
|
||||
ser << *p_type;
|
||||
ser.set_dds_cdr_options({0,0});
|
||||
}
|
||||
catch (eprosima::fastcdr::exception::Exception& /*exception*/)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the serialized length
|
||||
payload.length = static_cast<uint32_t>(ser.get_serialized_data_length());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool XNRuntimeControlPubSubType::deserialize(
|
||||
SerializedPayload_t& payload,
|
||||
void* data)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Convert DATA to pointer of your type
|
||||
XNRuntimeControl* p_type = static_cast<XNRuntimeControl*>(data);
|
||||
|
||||
// Object that manages the raw buffer.
|
||||
eprosima::fastcdr::FastBuffer fastbuffer(reinterpret_cast<char*>(payload.data), payload.length);
|
||||
|
||||
// Object that deserializes the data.
|
||||
eprosima::fastcdr::Cdr deser(fastbuffer, eprosima::fastcdr::Cdr::DEFAULT_ENDIAN);
|
||||
|
||||
// Deserialize encapsulation.
|
||||
deser.read_encapsulation();
|
||||
payload.encapsulation = deser.endianness() == eprosima::fastcdr::Cdr::BIG_ENDIANNESS ? CDR_BE : CDR_LE;
|
||||
|
||||
// Deserialize the object.
|
||||
deser >> *p_type;
|
||||
}
|
||||
catch (eprosima::fastcdr::exception::Exception& /*exception*/)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t XNRuntimeControlPubSubType::calculate_serialized_size(
|
||||
const void* const data,
|
||||
DataRepresentationId_t data_representation)
|
||||
{
|
||||
try
|
||||
{
|
||||
eprosima::fastcdr::CdrSizeCalculator calculator(
|
||||
data_representation == DataRepresentationId_t::XCDR_DATA_REPRESENTATION ?
|
||||
eprosima::fastcdr::CdrVersion::XCDRv1 :eprosima::fastcdr::CdrVersion::XCDRv2);
|
||||
size_t current_alignment {0};
|
||||
return static_cast<uint32_t>(calculator.calculate_serialized_size(
|
||||
*static_cast<const XNRuntimeControl*>(data), current_alignment)) +
|
||||
4u /*encapsulation*/;
|
||||
}
|
||||
catch (eprosima::fastcdr::exception::Exception& /*exception*/)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void* XNRuntimeControlPubSubType::create_data()
|
||||
{
|
||||
return reinterpret_cast<void*>(new XNRuntimeControl());
|
||||
}
|
||||
|
||||
void XNRuntimeControlPubSubType::delete_data(
|
||||
void* data)
|
||||
{
|
||||
delete(reinterpret_cast<XNRuntimeControl*>(data));
|
||||
}
|
||||
|
||||
bool XNRuntimeControlPubSubType::compute_key(
|
||||
SerializedPayload_t& payload,
|
||||
InstanceHandle_t& handle,
|
||||
bool force_md5)
|
||||
{
|
||||
if (!is_compute_key_provided)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
XNRuntimeControl data;
|
||||
if (deserialize(payload, static_cast<void*>(&data)))
|
||||
{
|
||||
return compute_key(static_cast<void*>(&data), handle, force_md5);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool XNRuntimeControlPubSubType::compute_key(
|
||||
const void* const data,
|
||||
InstanceHandle_t& handle,
|
||||
bool force_md5)
|
||||
{
|
||||
if (!is_compute_key_provided)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const XNRuntimeControl* p_type = static_cast<const XNRuntimeControl*>(data);
|
||||
|
||||
// Object that manages the raw buffer.
|
||||
eprosima::fastcdr::FastBuffer fastbuffer(reinterpret_cast<char*>(key_buffer_),
|
||||
XNSim_XNSimControl_XNRuntimeControl_max_key_cdr_typesize);
|
||||
|
||||
// Object that serializes the data.
|
||||
eprosima::fastcdr::Cdr ser(fastbuffer, eprosima::fastcdr::Cdr::BIG_ENDIANNESS, eprosima::fastcdr::CdrVersion::XCDRv2);
|
||||
ser.set_encoding_flag(eprosima::fastcdr::EncodingAlgorithmFlag::PLAIN_CDR2);
|
||||
eprosima::fastcdr::serialize_key(ser, *p_type);
|
||||
if (force_md5 || XNSim_XNSimControl_XNRuntimeControl_max_key_cdr_typesize > 16)
|
||||
{
|
||||
md5_.init();
|
||||
md5_.update(key_buffer_, static_cast<unsigned int>(ser.get_serialized_data_length()));
|
||||
md5_.finalize();
|
||||
for (uint8_t i = 0; i < 16; ++i)
|
||||
{
|
||||
handle.value[i] = md5_.digest[i];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (uint8_t i = 0; i < 16; ++i)
|
||||
{
|
||||
handle.value[i] = key_buffer_[i];
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void XNRuntimeControlPubSubType::register_type_object_representation()
|
||||
{
|
||||
register_XNRuntimeControl_type_identifier(type_identifiers_);
|
||||
}
|
||||
|
||||
} // namespace XNSimControl
|
||||
|
||||
} // namespace XNSim
|
||||
|
||||
|
||||
// Include auxiliary functions like for serializing/deserializing.
|
||||
#include "XNSimStatusCdrAux.ipp"
|
456
XNCore_Win/XNIDL/XNSimStatusPubSubTypes.hpp
Normal file
456
XNCore_Win/XNIDL/XNSimStatusPubSubTypes.hpp
Normal file
@ -0,0 +1,456 @@
|
||||
// Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima).
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/*!
|
||||
* @file XNSimStatusPubSubTypes.hpp
|
||||
* This header file contains the declaration of the serialization functions.
|
||||
*
|
||||
* This file was generated by the tool fastddsgen.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef FAST_DDS_GENERATED__XNSIM_XNSIMCONTROL_XNSIMSTATUS_PUBSUBTYPES_HPP
|
||||
#define FAST_DDS_GENERATED__XNSIM_XNSIMCONTROL_XNSIMSTATUS_PUBSUBTYPES_HPP
|
||||
|
||||
#include <fastdds/dds/core/policy/QosPolicies.hpp>
|
||||
#include <fastdds/dds/topic/TopicDataType.hpp>
|
||||
#include <fastdds/rtps/common/InstanceHandle.hpp>
|
||||
#include <fastdds/rtps/common/SerializedPayload.hpp>
|
||||
#include <fastdds/utils/md5.hpp>
|
||||
|
||||
#include "XNSimStatus.hpp"
|
||||
|
||||
|
||||
#if !defined(FASTDDS_GEN_API_VER) || (FASTDDS_GEN_API_VER != 3)
|
||||
#error \
|
||||
Generated XNSimStatus is not compatible with current installed Fast DDS. Please, regenerate it with fastddsgen.
|
||||
#endif // FASTDDS_GEN_API_VER
|
||||
|
||||
namespace XNSim
|
||||
{
|
||||
namespace XNSimStatus
|
||||
{
|
||||
|
||||
/*!
|
||||
* @brief This class represents the TopicDataType of the type XNCoreStatus defined by the user in the IDL file.
|
||||
* @ingroup XNSimStatus
|
||||
*/
|
||||
class XNCoreStatusPubSubType : public eprosima::fastdds::dds::TopicDataType
|
||||
{
|
||||
public:
|
||||
|
||||
typedef XNCoreStatus type;
|
||||
|
||||
eProsima_user_DllExport XNCoreStatusPubSubType();
|
||||
|
||||
eProsima_user_DllExport ~XNCoreStatusPubSubType() override;
|
||||
|
||||
eProsima_user_DllExport bool serialize(
|
||||
const void* const data,
|
||||
eprosima::fastdds::rtps::SerializedPayload_t& payload,
|
||||
eprosima::fastdds::dds::DataRepresentationId_t data_representation) override;
|
||||
|
||||
eProsima_user_DllExport bool deserialize(
|
||||
eprosima::fastdds::rtps::SerializedPayload_t& payload,
|
||||
void* data) override;
|
||||
|
||||
eProsima_user_DllExport uint32_t calculate_serialized_size(
|
||||
const void* const data,
|
||||
eprosima::fastdds::dds::DataRepresentationId_t data_representation) override;
|
||||
|
||||
eProsima_user_DllExport bool compute_key(
|
||||
eprosima::fastdds::rtps::SerializedPayload_t& payload,
|
||||
eprosima::fastdds::rtps::InstanceHandle_t& ihandle,
|
||||
bool force_md5 = false) override;
|
||||
|
||||
eProsima_user_DllExport bool compute_key(
|
||||
const void* const data,
|
||||
eprosima::fastdds::rtps::InstanceHandle_t& ihandle,
|
||||
bool force_md5 = false) override;
|
||||
|
||||
eProsima_user_DllExport void* create_data() override;
|
||||
|
||||
eProsima_user_DllExport void delete_data(
|
||||
void* data) override;
|
||||
|
||||
//Register TypeObject representation in Fast DDS TypeObjectRegistry
|
||||
eProsima_user_DllExport void register_type_object_representation() override;
|
||||
|
||||
#ifdef TOPIC_DATA_TYPE_API_HAS_IS_BOUNDED
|
||||
eProsima_user_DllExport inline bool is_bounded() const override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif // TOPIC_DATA_TYPE_API_HAS_IS_BOUNDED
|
||||
|
||||
#ifdef TOPIC_DATA_TYPE_API_HAS_IS_PLAIN
|
||||
|
||||
eProsima_user_DllExport inline bool is_plain(
|
||||
eprosima::fastdds::dds::DataRepresentationId_t data_representation) const override
|
||||
{
|
||||
static_cast<void>(data_representation);
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif // TOPIC_DATA_TYPE_API_HAS_IS_PLAIN
|
||||
|
||||
#ifdef TOPIC_DATA_TYPE_API_HAS_CONSTRUCT_SAMPLE
|
||||
eProsima_user_DllExport inline bool construct_sample(
|
||||
void* memory) const override
|
||||
{
|
||||
static_cast<void>(memory);
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif // TOPIC_DATA_TYPE_API_HAS_CONSTRUCT_SAMPLE
|
||||
|
||||
private:
|
||||
|
||||
eprosima::fastdds::MD5 md5_;
|
||||
unsigned char* key_buffer_;
|
||||
|
||||
};
|
||||
|
||||
/*!
|
||||
* @brief This class represents the TopicDataType of the type XNEngineStatus defined by the user in the IDL file.
|
||||
* @ingroup XNSimStatus
|
||||
*/
|
||||
class XNEngineStatusPubSubType : public eprosima::fastdds::dds::TopicDataType
|
||||
{
|
||||
public:
|
||||
|
||||
typedef XNEngineStatus type;
|
||||
|
||||
eProsima_user_DllExport XNEngineStatusPubSubType();
|
||||
|
||||
eProsima_user_DllExport ~XNEngineStatusPubSubType() override;
|
||||
|
||||
eProsima_user_DllExport bool serialize(
|
||||
const void* const data,
|
||||
eprosima::fastdds::rtps::SerializedPayload_t& payload,
|
||||
eprosima::fastdds::dds::DataRepresentationId_t data_representation) override;
|
||||
|
||||
eProsima_user_DllExport bool deserialize(
|
||||
eprosima::fastdds::rtps::SerializedPayload_t& payload,
|
||||
void* data) override;
|
||||
|
||||
eProsima_user_DllExport uint32_t calculate_serialized_size(
|
||||
const void* const data,
|
||||
eprosima::fastdds::dds::DataRepresentationId_t data_representation) override;
|
||||
|
||||
eProsima_user_DllExport bool compute_key(
|
||||
eprosima::fastdds::rtps::SerializedPayload_t& payload,
|
||||
eprosima::fastdds::rtps::InstanceHandle_t& ihandle,
|
||||
bool force_md5 = false) override;
|
||||
|
||||
eProsima_user_DllExport bool compute_key(
|
||||
const void* const data,
|
||||
eprosima::fastdds::rtps::InstanceHandle_t& ihandle,
|
||||
bool force_md5 = false) override;
|
||||
|
||||
eProsima_user_DllExport void* create_data() override;
|
||||
|
||||
eProsima_user_DllExport void delete_data(
|
||||
void* data) override;
|
||||
|
||||
//Register TypeObject representation in Fast DDS TypeObjectRegistry
|
||||
eProsima_user_DllExport void register_type_object_representation() override;
|
||||
|
||||
#ifdef TOPIC_DATA_TYPE_API_HAS_IS_BOUNDED
|
||||
eProsima_user_DllExport inline bool is_bounded() const override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif // TOPIC_DATA_TYPE_API_HAS_IS_BOUNDED
|
||||
|
||||
#ifdef TOPIC_DATA_TYPE_API_HAS_IS_PLAIN
|
||||
|
||||
eProsima_user_DllExport inline bool is_plain(
|
||||
eprosima::fastdds::dds::DataRepresentationId_t data_representation) const override
|
||||
{
|
||||
static_cast<void>(data_representation);
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif // TOPIC_DATA_TYPE_API_HAS_IS_PLAIN
|
||||
|
||||
#ifdef TOPIC_DATA_TYPE_API_HAS_CONSTRUCT_SAMPLE
|
||||
eProsima_user_DllExport inline bool construct_sample(
|
||||
void* memory) const override
|
||||
{
|
||||
static_cast<void>(memory);
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif // TOPIC_DATA_TYPE_API_HAS_CONSTRUCT_SAMPLE
|
||||
|
||||
private:
|
||||
|
||||
eprosima::fastdds::MD5 md5_;
|
||||
unsigned char* key_buffer_;
|
||||
|
||||
};
|
||||
|
||||
/*!
|
||||
* @brief This class represents the TopicDataType of the type XNThreadStatus defined by the user in the IDL file.
|
||||
* @ingroup XNSimStatus
|
||||
*/
|
||||
class XNThreadStatusPubSubType : public eprosima::fastdds::dds::TopicDataType
|
||||
{
|
||||
public:
|
||||
|
||||
typedef XNThreadStatus type;
|
||||
|
||||
eProsima_user_DllExport XNThreadStatusPubSubType();
|
||||
|
||||
eProsima_user_DllExport ~XNThreadStatusPubSubType() override;
|
||||
|
||||
eProsima_user_DllExport bool serialize(
|
||||
const void* const data,
|
||||
eprosima::fastdds::rtps::SerializedPayload_t& payload,
|
||||
eprosima::fastdds::dds::DataRepresentationId_t data_representation) override;
|
||||
|
||||
eProsima_user_DllExport bool deserialize(
|
||||
eprosima::fastdds::rtps::SerializedPayload_t& payload,
|
||||
void* data) override;
|
||||
|
||||
eProsima_user_DllExport uint32_t calculate_serialized_size(
|
||||
const void* const data,
|
||||
eprosima::fastdds::dds::DataRepresentationId_t data_representation) override;
|
||||
|
||||
eProsima_user_DllExport bool compute_key(
|
||||
eprosima::fastdds::rtps::SerializedPayload_t& payload,
|
||||
eprosima::fastdds::rtps::InstanceHandle_t& ihandle,
|
||||
bool force_md5 = false) override;
|
||||
|
||||
eProsima_user_DllExport bool compute_key(
|
||||
const void* const data,
|
||||
eprosima::fastdds::rtps::InstanceHandle_t& ihandle,
|
||||
bool force_md5 = false) override;
|
||||
|
||||
eProsima_user_DllExport void* create_data() override;
|
||||
|
||||
eProsima_user_DllExport void delete_data(
|
||||
void* data) override;
|
||||
|
||||
//Register TypeObject representation in Fast DDS TypeObjectRegistry
|
||||
eProsima_user_DllExport void register_type_object_representation() override;
|
||||
|
||||
#ifdef TOPIC_DATA_TYPE_API_HAS_IS_BOUNDED
|
||||
eProsima_user_DllExport inline bool is_bounded() const override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif // TOPIC_DATA_TYPE_API_HAS_IS_BOUNDED
|
||||
|
||||
#ifdef TOPIC_DATA_TYPE_API_HAS_IS_PLAIN
|
||||
|
||||
eProsima_user_DllExport inline bool is_plain(
|
||||
eprosima::fastdds::dds::DataRepresentationId_t data_representation) const override
|
||||
{
|
||||
static_cast<void>(data_representation);
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif // TOPIC_DATA_TYPE_API_HAS_IS_PLAIN
|
||||
|
||||
#ifdef TOPIC_DATA_TYPE_API_HAS_CONSTRUCT_SAMPLE
|
||||
eProsima_user_DllExport inline bool construct_sample(
|
||||
void* memory) const override
|
||||
{
|
||||
static_cast<void>(memory);
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif // TOPIC_DATA_TYPE_API_HAS_CONSTRUCT_SAMPLE
|
||||
|
||||
private:
|
||||
|
||||
eprosima::fastdds::MD5 md5_;
|
||||
unsigned char* key_buffer_;
|
||||
|
||||
};
|
||||
|
||||
/*!
|
||||
* @brief This class represents the TopicDataType of the type XNModelStatus defined by the user in the IDL file.
|
||||
* @ingroup XNSimStatus
|
||||
*/
|
||||
class XNModelStatusPubSubType : public eprosima::fastdds::dds::TopicDataType
|
||||
{
|
||||
public:
|
||||
|
||||
typedef XNModelStatus type;
|
||||
|
||||
eProsima_user_DllExport XNModelStatusPubSubType();
|
||||
|
||||
eProsima_user_DllExport ~XNModelStatusPubSubType() override;
|
||||
|
||||
eProsima_user_DllExport bool serialize(
|
||||
const void* const data,
|
||||
eprosima::fastdds::rtps::SerializedPayload_t& payload,
|
||||
eprosima::fastdds::dds::DataRepresentationId_t data_representation) override;
|
||||
|
||||
eProsima_user_DllExport bool deserialize(
|
||||
eprosima::fastdds::rtps::SerializedPayload_t& payload,
|
||||
void* data) override;
|
||||
|
||||
eProsima_user_DllExport uint32_t calculate_serialized_size(
|
||||
const void* const data,
|
||||
eprosima::fastdds::dds::DataRepresentationId_t data_representation) override;
|
||||
|
||||
eProsima_user_DllExport bool compute_key(
|
||||
eprosima::fastdds::rtps::SerializedPayload_t& payload,
|
||||
eprosima::fastdds::rtps::InstanceHandle_t& ihandle,
|
||||
bool force_md5 = false) override;
|
||||
|
||||
eProsima_user_DllExport bool compute_key(
|
||||
const void* const data,
|
||||
eprosima::fastdds::rtps::InstanceHandle_t& ihandle,
|
||||
bool force_md5 = false) override;
|
||||
|
||||
eProsima_user_DllExport void* create_data() override;
|
||||
|
||||
eProsima_user_DllExport void delete_data(
|
||||
void* data) override;
|
||||
|
||||
//Register TypeObject representation in Fast DDS TypeObjectRegistry
|
||||
eProsima_user_DllExport void register_type_object_representation() override;
|
||||
|
||||
#ifdef TOPIC_DATA_TYPE_API_HAS_IS_BOUNDED
|
||||
eProsima_user_DllExport inline bool is_bounded() const override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif // TOPIC_DATA_TYPE_API_HAS_IS_BOUNDED
|
||||
|
||||
#ifdef TOPIC_DATA_TYPE_API_HAS_IS_PLAIN
|
||||
|
||||
eProsima_user_DllExport inline bool is_plain(
|
||||
eprosima::fastdds::dds::DataRepresentationId_t data_representation) const override
|
||||
{
|
||||
static_cast<void>(data_representation);
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif // TOPIC_DATA_TYPE_API_HAS_IS_PLAIN
|
||||
|
||||
#ifdef TOPIC_DATA_TYPE_API_HAS_CONSTRUCT_SAMPLE
|
||||
eProsima_user_DllExport inline bool construct_sample(
|
||||
void* memory) const override
|
||||
{
|
||||
static_cast<void>(memory);
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif // TOPIC_DATA_TYPE_API_HAS_CONSTRUCT_SAMPLE
|
||||
|
||||
private:
|
||||
|
||||
eprosima::fastdds::MD5 md5_;
|
||||
unsigned char* key_buffer_;
|
||||
|
||||
};
|
||||
} // namespace XNSimStatus
|
||||
namespace XNSimControl
|
||||
{
|
||||
|
||||
/*!
|
||||
* @brief This class represents the TopicDataType of the type XNRuntimeControl defined by the user in the IDL file.
|
||||
* @ingroup XNSimStatus
|
||||
*/
|
||||
class XNRuntimeControlPubSubType : public eprosima::fastdds::dds::TopicDataType
|
||||
{
|
||||
public:
|
||||
|
||||
typedef XNRuntimeControl type;
|
||||
|
||||
eProsima_user_DllExport XNRuntimeControlPubSubType();
|
||||
|
||||
eProsima_user_DllExport ~XNRuntimeControlPubSubType() override;
|
||||
|
||||
eProsima_user_DllExport bool serialize(
|
||||
const void* const data,
|
||||
eprosima::fastdds::rtps::SerializedPayload_t& payload,
|
||||
eprosima::fastdds::dds::DataRepresentationId_t data_representation) override;
|
||||
|
||||
eProsima_user_DllExport bool deserialize(
|
||||
eprosima::fastdds::rtps::SerializedPayload_t& payload,
|
||||
void* data) override;
|
||||
|
||||
eProsima_user_DllExport uint32_t calculate_serialized_size(
|
||||
const void* const data,
|
||||
eprosima::fastdds::dds::DataRepresentationId_t data_representation) override;
|
||||
|
||||
eProsima_user_DllExport bool compute_key(
|
||||
eprosima::fastdds::rtps::SerializedPayload_t& payload,
|
||||
eprosima::fastdds::rtps::InstanceHandle_t& ihandle,
|
||||
bool force_md5 = false) override;
|
||||
|
||||
eProsima_user_DllExport bool compute_key(
|
||||
const void* const data,
|
||||
eprosima::fastdds::rtps::InstanceHandle_t& ihandle,
|
||||
bool force_md5 = false) override;
|
||||
|
||||
eProsima_user_DllExport void* create_data() override;
|
||||
|
||||
eProsima_user_DllExport void delete_data(
|
||||
void* data) override;
|
||||
|
||||
//Register TypeObject representation in Fast DDS TypeObjectRegistry
|
||||
eProsima_user_DllExport void register_type_object_representation() override;
|
||||
|
||||
#ifdef TOPIC_DATA_TYPE_API_HAS_IS_BOUNDED
|
||||
eProsima_user_DllExport inline bool is_bounded() const override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif // TOPIC_DATA_TYPE_API_HAS_IS_BOUNDED
|
||||
|
||||
#ifdef TOPIC_DATA_TYPE_API_HAS_IS_PLAIN
|
||||
|
||||
eProsima_user_DllExport inline bool is_plain(
|
||||
eprosima::fastdds::dds::DataRepresentationId_t data_representation) const override
|
||||
{
|
||||
static_cast<void>(data_representation);
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif // TOPIC_DATA_TYPE_API_HAS_IS_PLAIN
|
||||
|
||||
#ifdef TOPIC_DATA_TYPE_API_HAS_CONSTRUCT_SAMPLE
|
||||
eProsima_user_DllExport inline bool construct_sample(
|
||||
void* memory) const override
|
||||
{
|
||||
static_cast<void>(memory);
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif // TOPIC_DATA_TYPE_API_HAS_CONSTRUCT_SAMPLE
|
||||
|
||||
private:
|
||||
|
||||
eprosima::fastdds::MD5 md5_;
|
||||
unsigned char* key_buffer_;
|
||||
|
||||
};
|
||||
} // namespace XNSimControl
|
||||
} // namespace XNSim
|
||||
|
||||
#endif // FAST_DDS_GENERATED__XNSIM_XNSIMCONTROL_XNSIMSTATUS_PUBSUBTYPES_HPP
|
||||
|
1214
XNCore_Win/XNIDL/XNSimStatusTypeObjectSupport.cxx
Normal file
1214
XNCore_Win/XNIDL/XNSimStatusTypeObjectSupport.cxx
Normal file
File diff suppressed because it is too large
Load Diff
117
XNCore_Win/XNIDL/XNSimStatusTypeObjectSupport.hpp
Normal file
117
XNCore_Win/XNIDL/XNSimStatusTypeObjectSupport.hpp
Normal file
@ -0,0 +1,117 @@
|
||||
// Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima).
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/*!
|
||||
* @file XNSimStatusTypeObjectSupport.hpp
|
||||
* Header file containing the API required to register the TypeObject representation of the described types in the IDL file
|
||||
*
|
||||
* This file was generated by the tool fastddsgen.
|
||||
*/
|
||||
|
||||
#ifndef FAST_DDS_GENERATED__XNSIM_XNSIMCONTROL_XNSIMSTATUS_TYPE_OBJECT_SUPPORT_HPP
|
||||
#define FAST_DDS_GENERATED__XNSIM_XNSIMCONTROL_XNSIMSTATUS_TYPE_OBJECT_SUPPORT_HPP
|
||||
|
||||
#include <fastdds/dds/xtypes/type_representation/TypeObject.hpp>
|
||||
|
||||
|
||||
#if defined(_WIN32)
|
||||
#if defined(EPROSIMA_USER_DLL_EXPORT)
|
||||
#define eProsima_user_DllExport __declspec( dllexport )
|
||||
#else
|
||||
#define eProsima_user_DllExport
|
||||
#endif // EPROSIMA_USER_DLL_EXPORT
|
||||
#else
|
||||
#define eProsima_user_DllExport
|
||||
#endif // _WIN32
|
||||
|
||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS_PUBLIC
|
||||
|
||||
namespace XNSim {
|
||||
namespace XNSimStatus {
|
||||
/**
|
||||
* @brief Register XNCoreStatus related TypeIdentifier.
|
||||
* Fully-descriptive TypeIdentifiers are directly registered.
|
||||
* Hash TypeIdentifiers require to fill the TypeObject information and hash it, consequently, the TypeObject is
|
||||
* indirectly registered as well.
|
||||
*
|
||||
* @param[out] TypeIdentifier of the registered type.
|
||||
* The returned TypeIdentifier corresponds to the complete TypeIdentifier in case of hashed TypeIdentifiers.
|
||||
* Invalid TypeIdentifier is returned in case of error.
|
||||
*/
|
||||
eProsima_user_DllExport void register_XNCoreStatus_type_identifier(
|
||||
eprosima::fastdds::dds::xtypes::TypeIdentifierPair& type_ids);
|
||||
|
||||
/**
|
||||
* @brief Register XNEngineStatus related TypeIdentifier.
|
||||
* Fully-descriptive TypeIdentifiers are directly registered.
|
||||
* Hash TypeIdentifiers require to fill the TypeObject information and hash it, consequently, the TypeObject is
|
||||
* indirectly registered as well.
|
||||
*
|
||||
* @param[out] TypeIdentifier of the registered type.
|
||||
* The returned TypeIdentifier corresponds to the complete TypeIdentifier in case of hashed TypeIdentifiers.
|
||||
* Invalid TypeIdentifier is returned in case of error.
|
||||
*/
|
||||
eProsima_user_DllExport void register_XNEngineStatus_type_identifier(
|
||||
eprosima::fastdds::dds::xtypes::TypeIdentifierPair& type_ids);
|
||||
|
||||
/**
|
||||
* @brief Register XNThreadStatus related TypeIdentifier.
|
||||
* Fully-descriptive TypeIdentifiers are directly registered.
|
||||
* Hash TypeIdentifiers require to fill the TypeObject information and hash it, consequently, the TypeObject is
|
||||
* indirectly registered as well.
|
||||
*
|
||||
* @param[out] TypeIdentifier of the registered type.
|
||||
* The returned TypeIdentifier corresponds to the complete TypeIdentifier in case of hashed TypeIdentifiers.
|
||||
* Invalid TypeIdentifier is returned in case of error.
|
||||
*/
|
||||
eProsima_user_DllExport void register_XNThreadStatus_type_identifier(
|
||||
eprosima::fastdds::dds::xtypes::TypeIdentifierPair& type_ids);
|
||||
|
||||
/**
|
||||
* @brief Register XNModelStatus related TypeIdentifier.
|
||||
* Fully-descriptive TypeIdentifiers are directly registered.
|
||||
* Hash TypeIdentifiers require to fill the TypeObject information and hash it, consequently, the TypeObject is
|
||||
* indirectly registered as well.
|
||||
*
|
||||
* @param[out] TypeIdentifier of the registered type.
|
||||
* The returned TypeIdentifier corresponds to the complete TypeIdentifier in case of hashed TypeIdentifiers.
|
||||
* Invalid TypeIdentifier is returned in case of error.
|
||||
*/
|
||||
eProsima_user_DllExport void register_XNModelStatus_type_identifier(
|
||||
eprosima::fastdds::dds::xtypes::TypeIdentifierPair& type_ids);
|
||||
|
||||
} // namespace XNSimStatus
|
||||
|
||||
namespace XNSimControl {
|
||||
/**
|
||||
* @brief Register XNRuntimeControl related TypeIdentifier.
|
||||
* Fully-descriptive TypeIdentifiers are directly registered.
|
||||
* Hash TypeIdentifiers require to fill the TypeObject information and hash it, consequently, the TypeObject is
|
||||
* indirectly registered as well.
|
||||
*
|
||||
* @param[out] TypeIdentifier of the registered type.
|
||||
* The returned TypeIdentifier corresponds to the complete TypeIdentifier in case of hashed TypeIdentifiers.
|
||||
* Invalid TypeIdentifier is returned in case of error.
|
||||
*/
|
||||
eProsima_user_DllExport void register_XNRuntimeControl_type_identifier(
|
||||
eprosima::fastdds::dds::xtypes::TypeIdentifierPair& type_ids);
|
||||
|
||||
} // namespace XNSimControl
|
||||
|
||||
} // namespace XNSim
|
||||
|
||||
|
||||
#endif // DOXYGEN_SHOULD_SKIP_THIS_PUBLIC
|
||||
|
||||
#endif // FAST_DDS_GENERATED__XNSIM_XNSIMCONTROL_XNSIMSTATUS_TYPE_OBJECT_SUPPORT_HPP
|
6
XNCore_Win/XNLogger/CMakeLists.txt
Normal file
6
XNCore_Win/XNLogger/CMakeLists.txt
Normal file
@ -0,0 +1,6 @@
|
||||
set(XNLOGGER_SOURCES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XNLogger.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XNLogger.cpp
|
||||
)
|
||||
|
||||
set(XNCORE_SOURCES ${XNCORE_SOURCES} ${XNLOGGER_SOURCES} PARENT_SCOPE)
|
116
XNCore_Win/XNLogger/XNLogger.cpp
Normal file
116
XNCore_Win/XNLogger/XNLogger.cpp
Normal file
@ -0,0 +1,116 @@
|
||||
#include "XNLogger.h"
|
||||
|
||||
namespace XNSim {
|
||||
|
||||
XNLogger::XNLogger()
|
||||
: consoleOutputEnabled{true, true, true, true},
|
||||
fileOutputEnabled{true, true, true, true} {
|
||||
// 获取当前工作目录
|
||||
XN_PATH currentDir = getCurrentPath();
|
||||
XN_PATH logDirPath = currentDir / "log";
|
||||
|
||||
// 创建 log 文件夹
|
||||
if (!std::filesystem::exists(logDirPath)) {
|
||||
std::filesystem::create_directories(logDirPath);
|
||||
}
|
||||
|
||||
// 创建以当前日期和时间命名的日志文件
|
||||
auto now = std::chrono::system_clock::now();
|
||||
auto time = std::chrono::system_clock::to_time_t(now);
|
||||
std::stringstream ss;
|
||||
ss << std::put_time(std::localtime(&time), "%Y%m%d_%H%M%S");
|
||||
std::string logFileName = "log_" + ss.str() + ".log";
|
||||
|
||||
logFilePath = (logDirPath / logFileName).string();
|
||||
logFile.open(logFilePath, std::ios::app);
|
||||
}
|
||||
|
||||
XNLogger::~XNLogger() {
|
||||
if (logFile.is_open()) {
|
||||
logFile.close();
|
||||
}
|
||||
}
|
||||
|
||||
std::string XNLogger::getCurrentTimeString() const {
|
||||
auto now = std::chrono::system_clock::now();
|
||||
auto time = std::chrono::system_clock::to_time_t(now);
|
||||
auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
now.time_since_epoch()) %
|
||||
1000;
|
||||
|
||||
std::stringstream ss;
|
||||
ss << std::put_time(std::localtime(&time), "%Y-%m-%d %H:%M:%S");
|
||||
ss << '.' << std::setfill('0') << std::setw(3) << ms.count();
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
void XNLogger::log(LogLevel level, const std::string &message) {
|
||||
std::lock_guard<std::mutex> locker(mutex);
|
||||
std::string logMessage = "[" + getCurrentTimeString() + "] [" +
|
||||
logLevelToString(level) + "] " + message;
|
||||
|
||||
std::string coloredMessage;
|
||||
|
||||
// 根据日志等级设置颜色
|
||||
switch (level) {
|
||||
case Debug:
|
||||
coloredMessage = COLOR_DEBUG + logMessage + COLOR_RESET;
|
||||
break;
|
||||
case Info:
|
||||
coloredMessage = COLOR_INFO + logMessage + COLOR_RESET;
|
||||
break;
|
||||
case Warning:
|
||||
coloredMessage = COLOR_WARNING + logMessage + COLOR_RESET;
|
||||
break;
|
||||
case Error:
|
||||
coloredMessage = COLOR_ERROR + logMessage + COLOR_RESET;
|
||||
break;
|
||||
default:
|
||||
coloredMessage = logMessage; // 默认无颜色
|
||||
break;
|
||||
}
|
||||
|
||||
// 控制台输出
|
||||
if (consoleOutputEnabled[level]) {
|
||||
if (level == Time) {
|
||||
// 如果是时间日志,则不换行,回退到该行开始
|
||||
std::cout << coloredMessage << "\r" << std::flush;
|
||||
} else {
|
||||
std::cout << coloredMessage << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
// 文件输出
|
||||
if (fileOutputEnabled[level] && logFile.is_open()) {
|
||||
if (level == Time) {
|
||||
logFile << logMessage << "\r" << std::flush;
|
||||
} else {
|
||||
logFile << logMessage << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void XNLogger::enableConsoleOutput(LogLevel level, bool enable) {
|
||||
consoleOutputEnabled[level] = enable;
|
||||
}
|
||||
|
||||
void XNLogger::enableFileOutput(LogLevel level, bool enable) {
|
||||
fileOutputEnabled[level] = enable;
|
||||
}
|
||||
|
||||
std::string XNLogger::logLevelToString(LogLevel level) const {
|
||||
switch (level) {
|
||||
case Debug:
|
||||
return "DEBUG";
|
||||
case Info:
|
||||
return "INFO";
|
||||
case Warning:
|
||||
return "WARNING";
|
||||
case Error:
|
||||
return "ERROR";
|
||||
case Time:
|
||||
return "TIME";
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
} // namespace XNSim
|
247
XNCore_Win/XNLogger/XNLogger.h
Normal file
247
XNCore_Win/XNLogger/XNLogger.h
Normal file
@ -0,0 +1,247 @@
|
||||
/**
|
||||
* @file XNLogger.h
|
||||
* @author jinchao
|
||||
* @brief 日志类
|
||||
* @version 1.0
|
||||
* @date 2025-01-08
|
||||
*
|
||||
* @copyright Copyright (c) 2025 COMAC
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
#include <XNGlobalDefine/XNDefine.h>
|
||||
|
||||
namespace XNSim {
|
||||
/**
|
||||
* @brief 日志类
|
||||
*/
|
||||
class XNLogger {
|
||||
public:
|
||||
/**
|
||||
* @brief 日志等级
|
||||
*/
|
||||
enum LogLevel { Debug, Info, Warning, Error, Time };
|
||||
|
||||
/**
|
||||
* @brief 获取日志类实例
|
||||
* @return 日志类实例
|
||||
*/
|
||||
static XNLogger &instance() {
|
||||
static XNLogger instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 日志输出
|
||||
* @param level 日志等级
|
||||
* @param message 日志消息
|
||||
*/
|
||||
void log(LogLevel level, const XN_STRING &message);
|
||||
|
||||
/**
|
||||
* @brief 启用控制台输出
|
||||
* @param level 日志等级
|
||||
* @param enable 是否启用
|
||||
*/
|
||||
void enableConsoleOutput(LogLevel level, XN_BOOL enable);
|
||||
|
||||
/**
|
||||
* @brief 启用文件输出
|
||||
* @param level 日志等级
|
||||
* @param enable 是否启用
|
||||
*/
|
||||
void enableFileOutput(LogLevel level, XN_BOOL enable);
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief 构造函数
|
||||
*/
|
||||
XNLogger();
|
||||
|
||||
/**
|
||||
* @brief 析构函数
|
||||
*/
|
||||
~XNLogger();
|
||||
|
||||
/**
|
||||
* @brief 禁止拷贝构造
|
||||
*/
|
||||
XNLogger(const XNLogger &) = delete;
|
||||
|
||||
/**
|
||||
* @brief 禁止赋值
|
||||
*/
|
||||
XNLogger &operator=(const XNLogger &) = delete;
|
||||
|
||||
/**
|
||||
* @brief 日志文件路径
|
||||
*/
|
||||
XN_STRING logFilePath;
|
||||
|
||||
/**
|
||||
* @brief 控制台输出控制
|
||||
*/
|
||||
XN_BOOL consoleOutputEnabled[5];
|
||||
|
||||
/**
|
||||
* @brief 文件输出控制
|
||||
*/
|
||||
XN_BOOL fileOutputEnabled[5];
|
||||
|
||||
/**
|
||||
* @brief 日志文件
|
||||
*/
|
||||
XN_OFSTREAM logFile;
|
||||
|
||||
/**
|
||||
* @brief 互斥锁
|
||||
*/
|
||||
XN_MUTEX mutex;
|
||||
|
||||
/**
|
||||
* @brief 日志等级转换为字符串
|
||||
* @param level 日志等级
|
||||
* @return 日志等级字符串
|
||||
*/
|
||||
XN_STRING logLevelToString(LogLevel level) const;
|
||||
|
||||
/**
|
||||
* @brief 获取当前时间字符串
|
||||
* @return 格式化的时间字符串
|
||||
*/
|
||||
XN_STRING getCurrentTimeString() const;
|
||||
|
||||
/**
|
||||
* @brief 控制台输出字体恢复颜色常量
|
||||
*/
|
||||
const XN_STRING COLOR_RESET = "\033[0m";
|
||||
|
||||
/**
|
||||
* @brief 调试颜色常量
|
||||
*/
|
||||
const XN_STRING COLOR_DEBUG = "\033[34m"; // 蓝色
|
||||
|
||||
/**
|
||||
* @brief 信息颜色常量
|
||||
*/
|
||||
const XN_STRING COLOR_INFO = "\033[32m"; // 绿色
|
||||
|
||||
/**
|
||||
* @brief 警告颜色常量
|
||||
*/
|
||||
const XN_STRING COLOR_WARNING = "\033[33m"; // 黄色
|
||||
|
||||
/**
|
||||
* @brief 错误颜色常量
|
||||
*/
|
||||
const XN_STRING COLOR_ERROR = "\033[31m"; // 红色
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 日志辅助类
|
||||
*/
|
||||
class XNLoggerHelper {
|
||||
public:
|
||||
/**
|
||||
* @brief 带参数的日志输出
|
||||
* @tparam Args 参数类型
|
||||
* @param level 日志等级
|
||||
* @param message 日志消息
|
||||
* @param args 参数
|
||||
*/
|
||||
template <typename... Args>
|
||||
inline static typename std::enable_if<(sizeof...(Args) > 0), void>::type
|
||||
log(XNLogger::LogLevel level, const XN_STRING &message, Args... args) {
|
||||
XN_STRING formattedMessage = formatMessage(message, args...);
|
||||
XNLogger::instance().log(level, formattedMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 不带参数的日志输出
|
||||
* @param level 日志等级
|
||||
* @param message 日志消息
|
||||
*/
|
||||
inline static void log(XNLogger::LogLevel level, const XN_STRING &message) {
|
||||
XNLogger::instance().log(level, message);
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief 将参数转换为字符串
|
||||
* @tparam T 参数类型
|
||||
* @param arg 要转换的参数
|
||||
* @return 转换后的字符串
|
||||
*/
|
||||
template <typename T> static XN_STRING convertToString(const T &arg) {
|
||||
if constexpr (XNSim::is_arithmetic_v<T>) {
|
||||
return std::to_string(arg); // 处理数值类型
|
||||
} else if constexpr (XNSim::is_same_v<T, XN_STRING>) {
|
||||
return arg;
|
||||
} else if constexpr (XNSim::is_convertible_v<T, XN_STRING>) {
|
||||
return XN_STRING(arg);
|
||||
} else if constexpr (XNSim::is_same_v<T, char *> ||
|
||||
XNSim::is_same_v<T, const char *>) {
|
||||
return XN_STRING(arg);
|
||||
} else {
|
||||
static_assert(XNSim::is_arithmetic_v<T> ||
|
||||
XNSim::is_same_v<T, XN_STRING> ||
|
||||
XNSim::is_convertible_v<T, XN_STRING> ||
|
||||
XNSim::is_same_v<T, XN_CHAR *> ||
|
||||
XNSim::is_same_v<T, const XN_CHAR *>,
|
||||
"A01021001: 不支持的类型转换,详见XNLogger.cpp:line 199");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 格式化日志消息,顺序替换%1、%2、%3……
|
||||
* @tparam Args 参数类型
|
||||
* @param message 日志消息
|
||||
* @param args 参数包
|
||||
* @return 格式化后的消息
|
||||
*/
|
||||
template <typename... Args>
|
||||
static XN_STRING formatMessage(const XN_STRING &message, Args &&...args) {
|
||||
static_assert(
|
||||
sizeof...(Args) <= 9,
|
||||
"A01021002: 单条日志参数数量超过限制,详见XNLogger.cpp:line 216");
|
||||
|
||||
XN_STRING result = message;
|
||||
// 使用初始化列表展开参数包
|
||||
int index = 1;
|
||||
// 使用lambda和std::initializer_list展开参数包
|
||||
(void)std::initializer_list<int>{(
|
||||
[&result, &index](const auto &value) {
|
||||
XN_STRING placeholder = "%" + ToXNString(index++);
|
||||
size_t pos = result.find(placeholder);
|
||||
if (pos != XN_STRING::npos) {
|
||||
result.replace(pos, placeholder.length(), convertToString(value));
|
||||
}
|
||||
}(args),
|
||||
0)...};
|
||||
return result;
|
||||
}
|
||||
};
|
||||
} // namespace XNSim
|
||||
/**
|
||||
* @brief 宏定义,用于输出调试日志
|
||||
*/
|
||||
#define LOG_DEBUG(message, ...) \
|
||||
XNLoggerHelper::log(XNLogger::Debug, message, ##__VA_ARGS__)
|
||||
|
||||
/**
|
||||
* @brief 宏定义,用于输出信息日志
|
||||
*/
|
||||
#define LOG_INFO(message, ...) \
|
||||
XNLoggerHelper::log(XNLogger::Info, message, ##__VA_ARGS__)
|
||||
|
||||
/**
|
||||
* @brief 宏定义,用于输出警告日志
|
||||
*/
|
||||
#define LOG_WARNING(message, ...) \
|
||||
XNLoggerHelper::log(XNLogger::Warning, message, ##__VA_ARGS__)
|
||||
|
||||
/**
|
||||
* @brief 宏定义,用于输出错误日志
|
||||
*/
|
||||
#define LOG_ERROR(message, ...) \
|
||||
XNLoggerHelper::log(XNLogger::Error, message, ##__VA_ARGS__)
|
7
XNCore_Win/XNModelManager/CMakeLists.txt
Normal file
7
XNCore_Win/XNModelManager/CMakeLists.txt
Normal file
@ -0,0 +1,7 @@
|
||||
set(XNMODELMANAGER_SOURCES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XNModelManager.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XNModelManager_p.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XNModelManager.cpp
|
||||
)
|
||||
|
||||
set(XNCORE_SOURCES ${XNCORE_SOURCES} ${XNMODELMANAGER_SOURCES} PARENT_SCOPE)
|
174
XNCore_Win/XNModelManager/XNModelManager.cpp
Normal file
174
XNCore_Win/XNModelManager/XNModelManager.cpp
Normal file
@ -0,0 +1,174 @@
|
||||
/**
|
||||
* @file XNModelManager.cpp
|
||||
* @author jinchao
|
||||
* @brief 模型管理器类源文件
|
||||
* @version 1.0
|
||||
* @date 2024-11-06
|
||||
*
|
||||
* @copyright Copyright (c) 2024 XN
|
||||
*
|
||||
*/
|
||||
#include "XNModelManager.h"
|
||||
#include "XNFramework/XNFramework.h"
|
||||
#include "XNModelManager_p.h"
|
||||
#include "XNModelObject/XNModelObject.h"
|
||||
#include "XNThreadManager/XNThreadManager.h"
|
||||
|
||||
|
||||
namespace XNSim {
|
||||
// 构造函数
|
||||
XNModelManager::XNModelManager()
|
||||
: XNBaseFrameObject(new XNModelManagerPrivate()) {
|
||||
SetUniqueId(enumValue(XNCoreObjectID::ModelManager));
|
||||
SetObjectName("XNModelManager");
|
||||
T_D();
|
||||
d->ModelIDAssigned.resize(XN_MODEL_ID_SIZE, false);
|
||||
}
|
||||
|
||||
// 析构函数
|
||||
XNModelManager::~XNModelManager() {}
|
||||
|
||||
XNModelManager::XNModelManager(PrivateType *p) : XNBaseFrameObject(p) {}
|
||||
|
||||
// 运行前最后准备
|
||||
XN_BOOL XNModelManager::PrepareForExecute() {
|
||||
T_D();
|
||||
for (auto &model : d->ModelMap) {
|
||||
model.second->PrepareForExecute();
|
||||
}
|
||||
d->_status = XNFrameObjectStatus::Ready;
|
||||
LOG_INFO("XNModelManager is prepared!");
|
||||
return true;
|
||||
}
|
||||
|
||||
XN_BOOL XNModelManager::Initialize() {
|
||||
T_D();
|
||||
LOG_INFO("XNModelManager Initialize Success!");
|
||||
d->_status = XNFrameObjectStatus::Initialized;
|
||||
return true;
|
||||
}
|
||||
|
||||
void XNModelManager::LoadModel(const XN_STRING &modelPath,
|
||||
const XN_STRING &className,
|
||||
const XN_STRING &modelVersion,
|
||||
const XN_STRING &planeName,
|
||||
XN_UINT32 initialType, XN_UINT32 threadID) {
|
||||
T_D();
|
||||
XN_HANDLE handle = loadLibrary(modelPath);
|
||||
if (handle) {
|
||||
typedef XNModelObjectPtr (*InitialModelFunc)();
|
||||
XN_STRING initialModelName = "Initial" + className;
|
||||
InitialModelFunc initialModel =
|
||||
(InitialModelFunc)getSymbol(handle, initialModelName.c_str());
|
||||
if (initialModel) {
|
||||
XNModelObjectPtr model = initialModel();
|
||||
if (model) {
|
||||
XN_UINT32 modelID = RegisterModel();
|
||||
if (modelID == 0) {
|
||||
LOG_WARNING("0x2174 Assign Model ID Failed, Model ID is used up!");
|
||||
closeLibrary(handle);
|
||||
return;
|
||||
}
|
||||
model->SetUniqueId(modelID);
|
||||
model->SetObjectName(className);
|
||||
model->SetFramework(GetFramework());
|
||||
model->SetInitializeType(initialType);
|
||||
model->SetThreadID(threadID);
|
||||
XN_STRING workPath = GetFramework()->GetWorkPath() + "/Packages/";
|
||||
model->SetLibPath(workPath);
|
||||
if (initialType == 0) {
|
||||
// 使用std::filesystem处理路径
|
||||
XN_PATH configPath = XN_PATH(modelPath).parent_path() /
|
||||
(className + "_V" + modelVersion + ".mcfg");
|
||||
model->SetXmlPath(configPath.string());
|
||||
} else if (initialType == 1) {
|
||||
model->SetXmlPath(planeName + "," + className + "," + modelVersion);
|
||||
}
|
||||
|
||||
// 注册模型到管理器
|
||||
d->ModelMap[modelID] = model;
|
||||
|
||||
// 初始化模型
|
||||
model->Initialize();
|
||||
|
||||
// 注册到线程管理器
|
||||
if (threadID != 0) {
|
||||
auto framework = GetFramework();
|
||||
if (framework) {
|
||||
// 注册到线程管理器 (重复注册了,暂删除)
|
||||
// framework->GetThreadManager()->RegisterFunction(
|
||||
// modelID, std::bind(&XNModelObject::StepUpdate, model.get()),
|
||||
// threadID, model->GetRunFreq(), model->GetRunNode(),
|
||||
// model->GetRunPriority()); 设置模型设置频率
|
||||
XN_DOUBLE threadFreq =
|
||||
framework->GetThreadManager()->GetThreadFreqByID(threadID);
|
||||
XN_DOUBLE modelSetFreq =
|
||||
threadFreq / (double)(1 << model->GetRunFreq());
|
||||
model->SetSetFreq(modelSetFreq);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
LOG_WARNING("0x2173 Model %s Not found in dynamic link library %s!",
|
||||
className.c_str(), modelPath.c_str());
|
||||
closeLibrary(handle);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
LOG_WARNING(
|
||||
"0x2177 InitialModel function not found in dynamic link library %s!",
|
||||
modelPath);
|
||||
closeLibrary(handle);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
LOG_WARNING(
|
||||
"0x2172 Model %s Dynamic link library loading failed! Error: %s",
|
||||
className, LoadError());
|
||||
}
|
||||
}
|
||||
|
||||
// 模型注册
|
||||
XN_UINT32 XNModelManager::RegisterModel() {
|
||||
T_D();
|
||||
// 从10000~19999的编号中分配ID
|
||||
for (XN_UINT32 i = 0; i < XN_MODEL_ID_SIZE; i++) {
|
||||
if (d->ModelIDAssigned[i])
|
||||
continue;
|
||||
else {
|
||||
d->ModelIDAssigned[i] = true;
|
||||
return i + XN_MODEL_ID_START;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 获取模型指针
|
||||
XNModelObjectPtr XNModelManager::GetModel(XN_UINT32 modelID) {
|
||||
T_D();
|
||||
if (d->ModelIDAssigned[modelID - XN_MODEL_ID_START]) {
|
||||
auto model = d->ModelMap.find(modelID);
|
||||
if (model != d->ModelMap.end()) {
|
||||
return model->second;
|
||||
}
|
||||
return nullptr;
|
||||
} else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void XNModelManager::RegisterFunction(XN_UINT32 id, XNCallBack fun,
|
||||
XN_UINT32 threadID, XN_UINT32 freqGroup,
|
||||
XN_UINT32 RunPos, XN_UINT32 RunPriorty) {
|
||||
T_D();
|
||||
if (d->ModelIDAssigned[id - 10000]) {
|
||||
auto framework = GetFramework();
|
||||
if (framework) {
|
||||
framework->GetThreadManager()->RegisterFunction(
|
||||
id, fun, threadID, freqGroup, RunPos, RunPriorty);
|
||||
}
|
||||
} else {
|
||||
LOG_WARNING("0x2177 Submission of periodic function was rejected, model ID "
|
||||
"%1 is not registered!",
|
||||
id);
|
||||
}
|
||||
}
|
||||
} // namespace XNSim
|
99
XNCore_Win/XNModelManager/XNModelManager.h
Normal file
99
XNCore_Win/XNModelManager/XNModelManager.h
Normal file
@ -0,0 +1,99 @@
|
||||
/**
|
||||
* @file XNModelManager.h
|
||||
* @author jinchao
|
||||
* @brief 模型管理器类头文件
|
||||
* @version 1.0
|
||||
* @date 2024-11-06
|
||||
*
|
||||
* @copyright Copyright (c) 2024 XN
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
#include "XNBaseFrameObject/XNBaseFrameObject.h"
|
||||
|
||||
namespace XNSim {
|
||||
struct XNModelManagerPrivate;
|
||||
|
||||
/**
|
||||
* @brief 模型管理器类
|
||||
* @details
|
||||
* 用于管理仿真系统中所有加载的模型,为模型分配唯一ID。其它组件或模型可以通过该唯一ID访问或控制该模型。
|
||||
*/
|
||||
class XNModelManager : public XNBaseFrameObject {
|
||||
XN_METATYPE(XNModelManager, XNBaseFrameObject)
|
||||
XN_DECLARE_PRIVATE(XNModelManager)
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief 模型管理器类默认构造函数
|
||||
*/
|
||||
XNModelManager();
|
||||
|
||||
/**
|
||||
* @brief 模型管理器类默认析构函数
|
||||
*/
|
||||
virtual ~XNModelManager();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief 模型管理器带参构造函数
|
||||
* @param p:私有结构体指针
|
||||
* @details 子类构造时调用此构造函数,传入子类的私有结构体指针
|
||||
*/
|
||||
XNModelManager(PrivateType *p);
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief 系统开始运行前的最后准备工作
|
||||
* @details 系统运行前模型管理器做最后处理的接口
|
||||
*/
|
||||
virtual XN_BOOL PrepareForExecute() override;
|
||||
|
||||
/**
|
||||
* @brief 初始化模型管理器
|
||||
* @details 模型管理器的初始化接口
|
||||
*/
|
||||
virtual XN_BOOL Initialize() override;
|
||||
|
||||
/**
|
||||
* @brief 加载模型
|
||||
* @param modelPath: QString类型,模型动态链接库路径
|
||||
* @param className: QString类型,模型类名
|
||||
* @param modelVersion: QString类型,模型版本号
|
||||
* @param initialType: UINT32类型,初始化类型
|
||||
* @param threadID: UINT32类型,线程ID
|
||||
* @details 加载模型
|
||||
*/
|
||||
void LoadModel(const XN_STRING &modelPath, const XN_STRING &className,
|
||||
const XN_STRING &modelVersion, const XN_STRING &planeName,
|
||||
XN_UINT32 initialType, XN_UINT32 threadID);
|
||||
|
||||
/**
|
||||
* @brief 注册模型信息
|
||||
* @return UINT32: 模型的全局唯一ID
|
||||
* @details 模型通过此接口注册自身,并获取自身全局唯一ID
|
||||
*/
|
||||
uint32_t RegisterModel();
|
||||
|
||||
/**
|
||||
* @brief 获取模型指针
|
||||
* @param modelID: UINT32类型,模型全局唯一ID
|
||||
* @return XNModelObjectPtr: 模型基类指针
|
||||
*/
|
||||
XNModelObjectPtr GetModel(XN_UINT32 modelID);
|
||||
|
||||
/**
|
||||
* @brief 注册模型函数
|
||||
* @param ModelID: UINT32类型,模型全局唯一ID
|
||||
* @param fun: 函数指针
|
||||
* @param freqGroup:
|
||||
* UINT32类型,提交的函数运行频率组,0为基频,1为半频,2为1/4频,3为1/8频,4为1/16频,5为1/32频
|
||||
* @param RunPos: UINT32类型,提交的函数运行节点号,<2^(freqGroup)
|
||||
* @param RunPriorty:
|
||||
* UINT32类型,提交的函数运行优先级,99~0,优先级数值越大,优先级越高
|
||||
*/
|
||||
void RegisterFunction(XN_UINT32 id, XNCallBack fun, XN_UINT32 threadID,
|
||||
XN_UINT32 freqGroup, XN_UINT32 RunPos,
|
||||
XN_UINT32 RunPriorty);
|
||||
};
|
||||
} // namespace XNSim
|
19
XNCore_Win/XNModelManager/XNModelManager_p.h
Normal file
19
XNCore_Win/XNModelManager/XNModelManager_p.h
Normal file
@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
#include "XNBaseFrameObject/XNBaseFrameObject_p.h"
|
||||
|
||||
namespace XNSim {
|
||||
using XNModelMap = std::map<XN_UINT32, XNModelObjectPtr>;
|
||||
|
||||
struct XNModelManagerPrivate : public XNBaseFrameObjectPrivate {
|
||||
/**
|
||||
* @brief 模型ID库
|
||||
* @details 所有模型已用ID的存储库
|
||||
*/
|
||||
XNAsignedIDFlag ModelIDAssigned;
|
||||
/**
|
||||
* @brief 模型ID与模型指针的映射表
|
||||
* @details 所有模型ID与模型指针的映射表
|
||||
*/
|
||||
XNModelMap ModelMap;
|
||||
};
|
||||
} // namespace XNSim
|
7
XNCore_Win/XNModelObject/CMakeLists.txt
Normal file
7
XNCore_Win/XNModelObject/CMakeLists.txt
Normal file
@ -0,0 +1,7 @@
|
||||
set(XNMODELOBJECT_SOURCES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XNModelObject.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XNModelObject_p.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XNModelObject.cpp
|
||||
)
|
||||
|
||||
set(XNCORE_SOURCES ${XNCORE_SOURCES} ${XNMODELOBJECT_SOURCES} PARENT_SCOPE)
|
478
XNCore_Win/XNModelObject/XNModelObject.cpp
Normal file
478
XNCore_Win/XNModelObject/XNModelObject.cpp
Normal file
@ -0,0 +1,478 @@
|
||||
/**
|
||||
* @file XNModelObject.cpp
|
||||
* @author jinchao
|
||||
* @brief 模型基类源文件
|
||||
* @version 1.0
|
||||
* @date 2024-11-07
|
||||
*
|
||||
* @copyright Copyright (c) 2024 XN
|
||||
*
|
||||
*/
|
||||
#include "XNModelObject.h"
|
||||
#include "XNDDSManager/XNDDSManager.h"
|
||||
#include "XNFramework/XNFramework.h"
|
||||
#include "XNIDL/XNSimStatusPubSubTypes.hpp"
|
||||
#include "XNModelManager/XNModelManager.h"
|
||||
#include "XNModelObject_p.h"
|
||||
#include "XNThreadManager/XNThreadManager.h"
|
||||
|
||||
namespace XNSim {
|
||||
// 默认构造函数
|
||||
XNModelObject::XNModelObject() : XNObject(new XNModelObjectPrivate()) {}
|
||||
|
||||
// 默认析构函数
|
||||
XNModelObject::~XNModelObject() {}
|
||||
|
||||
XNModelObject::XNModelObject(PrivateType *p) : XNObject(p) {}
|
||||
|
||||
void XNModelObject::SetFramework(XNFrameworkPtr framework) {
|
||||
T_D();
|
||||
d->_framework = framework;
|
||||
}
|
||||
|
||||
XNFrameworkPtr XNModelObject::GetFramework() const {
|
||||
T_D();
|
||||
return d->_framework;
|
||||
}
|
||||
|
||||
// 获取模型描述
|
||||
const XN_STRING &XNModelObject::GetDescription() {
|
||||
T_D();
|
||||
return d->_sDescription;
|
||||
}
|
||||
|
||||
// 设置模型描述
|
||||
void XNModelObject::SetDescription(const XN_STRING &sDescription) {
|
||||
T_D();
|
||||
d->_sDescription = sDescription;
|
||||
}
|
||||
|
||||
// 获取作者
|
||||
const XN_STRING &XNModelObject::GetAuthor() {
|
||||
T_D();
|
||||
return d->_sAuthor;
|
||||
}
|
||||
|
||||
// 设置作者
|
||||
void XNModelObject::SetAuthor(const XN_STRING &sAuthor) {
|
||||
T_D();
|
||||
d->_sAuthor = sAuthor;
|
||||
}
|
||||
|
||||
// 获取模型配置文件路径
|
||||
const XN_STRING &XNModelObject::GetXmlPath() {
|
||||
T_D();
|
||||
return d->_sXmlPath;
|
||||
}
|
||||
|
||||
// 设置模型配置文件路径
|
||||
void XNModelObject::SetXmlPath(const XN_STRING &sXmlPath) {
|
||||
T_D();
|
||||
d->_sXmlPath = sXmlPath;
|
||||
}
|
||||
|
||||
// 获取模型创建时间
|
||||
const XNTimePoint &XNModelObject::GetCreateTime() {
|
||||
T_D();
|
||||
return d->_cCreatTime;
|
||||
}
|
||||
|
||||
// 设置模型创建时间
|
||||
void XNModelObject::SetCreateTime(const XNTimePoint &cTime) {
|
||||
T_D();
|
||||
d->_cCreatTime = cTime;
|
||||
}
|
||||
|
||||
// 获取模型修改时间
|
||||
const XNTimePoint &XNModelObject::GetChangeTime() {
|
||||
T_D();
|
||||
return d->_cChangeTime;
|
||||
}
|
||||
|
||||
// 设置模型修改时间
|
||||
void XNModelObject::SetChangeTime(const XNTimePoint &cTime) {
|
||||
T_D();
|
||||
d->_cChangeTime = cTime;
|
||||
}
|
||||
|
||||
// 获取模型版本号
|
||||
const XN_STRING &XNModelObject::GetVersion() {
|
||||
T_D();
|
||||
return d->_sVersion;
|
||||
}
|
||||
|
||||
// 设置模型版本号
|
||||
void XNModelObject::SetVersion(const XN_STRING &sVersion) {
|
||||
T_D();
|
||||
d->_sVersion = sVersion;
|
||||
}
|
||||
|
||||
void XNModelObject::SetInitializeType(XN_UINT32 initialType) {
|
||||
T_D();
|
||||
d->_initialType = initialType;
|
||||
}
|
||||
|
||||
void XNModelObject::SetThreadID(XN_UINT32 threadID) {
|
||||
T_D();
|
||||
d->_threadID = threadID;
|
||||
}
|
||||
|
||||
XN_UINT32 XNModelObject::GetThreadID() const {
|
||||
T_D();
|
||||
return d->_threadID;
|
||||
}
|
||||
|
||||
XN_UINT32 XNModelObject::GetRunFreq() const {
|
||||
T_D();
|
||||
return d->_runFreq;
|
||||
}
|
||||
|
||||
void XNModelObject::SetRunFreq(XN_UINT32 runFreq) {
|
||||
T_D();
|
||||
d->_runFreq = runFreq;
|
||||
}
|
||||
|
||||
XN_UINT32 XNModelObject::GetRunNode() const {
|
||||
T_D();
|
||||
return d->_runNode;
|
||||
}
|
||||
|
||||
void XNModelObject::SetRunNode(XN_UINT32 runNode) {
|
||||
T_D();
|
||||
d->_runNode = runNode;
|
||||
}
|
||||
|
||||
XN_UINT32 XNModelObject::GetRunPriority() const {
|
||||
T_D();
|
||||
return d->_runPriority;
|
||||
}
|
||||
|
||||
void XNModelObject::SetRunPriority(XN_UINT32 runPriority) {
|
||||
T_D();
|
||||
d->_runPriority = runPriority;
|
||||
}
|
||||
|
||||
XN_DOUBLE XNModelObject::GetSetFreq() const {
|
||||
T_D();
|
||||
return d->_setFreq;
|
||||
}
|
||||
|
||||
void XNModelObject::SetSetFreq(XN_DOUBLE setFreq) {
|
||||
T_D();
|
||||
d->_setFreq = setFreq;
|
||||
}
|
||||
|
||||
const XN_STRING &XNModelObject::GetLibPath() {
|
||||
T_D();
|
||||
return d->_sLibPath;
|
||||
}
|
||||
|
||||
void XNModelObject::SetLibPath(const XN_STRING &sLibPath) {
|
||||
T_D();
|
||||
d->_sLibPath = sLibPath;
|
||||
}
|
||||
|
||||
// 初始化函数
|
||||
void XNModelObject::Initialize() {
|
||||
T_D();
|
||||
if (d->_initialType == 0) {
|
||||
ParseXml();
|
||||
} else {
|
||||
ParseConfig();
|
||||
}
|
||||
}
|
||||
|
||||
void XNModelObject::ParseXml() {
|
||||
T_D();
|
||||
// 读取配置文件,设置循环执行函数
|
||||
XN_XMLDocument doc;
|
||||
if (LoadXmlFile(GetXmlPath(), doc) != 0) {
|
||||
LOG_WARNING("0x2161 Failed to parse model configuration file: %1!",
|
||||
GetXmlPath());
|
||||
return;
|
||||
}
|
||||
|
||||
XN_XMLElement *rootNode = GetRootElement(doc);
|
||||
if (!rootNode) {
|
||||
LOG_WARNING("0x2161 Failed to parse model configuration file: %1!",
|
||||
GetXmlPath());
|
||||
return;
|
||||
}
|
||||
// 读取配置文件的模型参数
|
||||
XN_STRING modelName = GetFirstChildElementText(rootNode, "Name");
|
||||
if (modelName.empty() || modelName != GetObjectName()) {
|
||||
LOG_WARNING("0x2162 The model name in the configuration file of model %1 "
|
||||
"is not consistent "
|
||||
"with the model name in the configuration file of model %2!",
|
||||
GetObjectName(), modelName.empty() ? "null" : modelName);
|
||||
return;
|
||||
}
|
||||
d->_sDescription = GetFirstChildElementText(rootNode, "Description");
|
||||
d->_sAuthor = GetFirstChildElementText(rootNode, "Author");
|
||||
d->_sVersion = GetFirstChildElementText(rootNode, "Version");
|
||||
|
||||
// 使用标准C++时间处理
|
||||
XN_STRING createTimeStr = GetFirstChildElementText(rootNode, "CreateTime");
|
||||
XN_STRING changeTimeStr = GetFirstChildElementText(rootNode, "ChangeTime");
|
||||
d->_cCreatTime = parseISOTime(createTimeStr);
|
||||
d->_cChangeTime = parseISOTime(changeTimeStr);
|
||||
|
||||
XN_STRING funcNode = GetFirstChildElementText(rootNode, "Node");
|
||||
d->_runPriority = XNSafe_stoi(GetFirstChildElementText(rootNode, "Priority"));
|
||||
|
||||
// 检查运行节点是否是 "x-x" 形式
|
||||
XN_SIZE tmp = funcNode.find('-');
|
||||
if (tmp == std::string::npos || tmp == 0) {
|
||||
LOG_WARNING("0x2162 The value of the run node attribute in the "
|
||||
"configuration file of model "
|
||||
"%1 is not in the x-x format, registration not executed!",
|
||||
GetObjectName());
|
||||
return;
|
||||
}
|
||||
|
||||
// 使用标准C++字符串处理
|
||||
d->_runFreq = XNSafe_stoi(funcNode.substr(0, tmp));
|
||||
d->_runNode = XNSafe_stoi(funcNode.substr(tmp + 1));
|
||||
|
||||
// 注册周期性函数
|
||||
auto framework = GetFramework();
|
||||
if (framework) {
|
||||
auto threadManager = framework->GetThreadManager();
|
||||
if (threadManager) {
|
||||
threadManager->RegisterFunction(
|
||||
GetUniqueId(), std::bind(&XNModelObject::StepUpdate, this),
|
||||
d->_threadID, d->_runFreq, d->_runNode, d->_runPriority);
|
||||
}
|
||||
}
|
||||
|
||||
// 加载动态库
|
||||
XN_STRING mathlib = GetFirstChildElementText(rootNode, "MathLib");
|
||||
if (!mathlib.empty()) {
|
||||
// 使用标准C++文件路径处理
|
||||
XN_PATH xmlPath(GetXmlPath());
|
||||
d->_sLibPath = xmlPath.parent_path().string() + "/" + mathlib;
|
||||
|
||||
// 使用标准C++动态库加载
|
||||
d->_dynamicLib = loadLibrary(d->_sLibPath);
|
||||
if (d->_dynamicLib) { // 动态库加载成功
|
||||
LOG_INFO(
|
||||
"0x2163 Model %1 loaded algorithm dynamic library %2 successfully!",
|
||||
GetObjectName(), d->_sLibPath);
|
||||
} else {
|
||||
LOG_WARNING("0x2160 Model %1 failed to find algorithm dynamic library "
|
||||
"%2, will not call "
|
||||
"algorithm!",
|
||||
GetObjectName(), d->_sLibPath);
|
||||
d->_dynamicLib = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// 处理指令列表
|
||||
XN_XMLElement *nodeCmds = GetFirstChildElement(rootNode, "CommandList");
|
||||
if (nodeCmds) {
|
||||
for (XN_XMLElement *nodeCmd = GetFirstChildElement(nodeCmds, "Command");
|
||||
nodeCmd != nullptr;
|
||||
nodeCmd = GetNextSiblingElement(nodeCmd, "Command")) {
|
||||
XN_STRING cmdName = GetAttribute(nodeCmd, "Name");
|
||||
XN_STRING cmdDescription = GetAttribute(nodeCmd, "Description");
|
||||
XN_STRING cmdCall = GetAttribute(nodeCmd, "Call");
|
||||
// TODO: 处理命令列表
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void XNModelObject::ParseConfig() {
|
||||
T_D();
|
||||
XN_STRINGLIST nameAndVersion = XNSplit(GetXmlPath(), ",");
|
||||
XN_STRING planeName = nameAndVersion[0];
|
||||
XN_STRING modelName = nameAndVersion[1];
|
||||
XN_STRING modelVersion = nameAndVersion[2];
|
||||
// 获取数据库路径
|
||||
XN_STRING dbPath = getEnv("XNCore");
|
||||
if (dbPath.empty()) {
|
||||
LOG_ERROR("0x1015 未设置XNCore环境变量, 引擎将退出!");
|
||||
return;
|
||||
}
|
||||
dbPath += "/database/XNSim.db";
|
||||
|
||||
// 打开数据库
|
||||
XN_DB_PTR db = openDatabase(dbPath);
|
||||
if (db == nullptr) {
|
||||
LOG_ERROR("0x1016 打开数据库失败: %1", sqlite3_errmsg(db));
|
||||
return;
|
||||
}
|
||||
|
||||
// 准备SQL语句
|
||||
XN_STRING sql = "SELECT * FROM XNModelsVersion WHERE PlaneName = ? AND "
|
||||
"ClassName = ? AND Version = ?";
|
||||
XN_DB_STMT_PTR stmt = prepareSql(db, sql);
|
||||
if (stmt == nullptr) {
|
||||
LOG_ERROR("0x1017 准备SQL语句失败: %1", sqlite3_errmsg(db));
|
||||
closeDatabase(db);
|
||||
return;
|
||||
}
|
||||
|
||||
// 绑定参数
|
||||
if (!bindText(stmt, 1, planeName) || !bindText(stmt, 2, modelName) ||
|
||||
!bindText(stmt, 3, modelVersion)) {
|
||||
LOG_ERROR("0x1018 绑定参数失败: %1", sqlite3_errmsg(db));
|
||||
finalizeSql(stmt);
|
||||
closeDatabase(db);
|
||||
return;
|
||||
}
|
||||
|
||||
// 执行查询
|
||||
if (!stepSql(stmt)) {
|
||||
LOG_ERROR("0x1019 未找到机型为%1,模型名称为%2,版本号%3的记录",
|
||||
planeName.c_str(), modelName.c_str(), modelVersion.c_str());
|
||||
finalizeSql(stmt);
|
||||
closeDatabase(db);
|
||||
return;
|
||||
}
|
||||
|
||||
d->_sDescription = getStringFromSqlite3(stmt, 7);
|
||||
d->_sAuthor = getStringFromSqlite3(stmt, 6);
|
||||
d->_sVersion = getStringFromSqlite3(stmt, 2);
|
||||
|
||||
// 解析时间
|
||||
XN_STRING createTimeStr = getStringFromSqlite3(stmt, 8);
|
||||
XN_STRING changeTimeStr = getStringFromSqlite3(stmt, 9);
|
||||
d->_cCreatTime = parseISOTime(createTimeStr);
|
||||
d->_cChangeTime = parseISOTime(changeTimeStr);
|
||||
d->_runFreq = XNSafe_stoi(getStringFromSqlite3(stmt, 10));
|
||||
d->_runNode = XNSafe_stoi(getStringFromSqlite3(stmt, 11));
|
||||
d->_runPriority = XNSafe_stoi(getStringFromSqlite3(stmt, 12));
|
||||
|
||||
// 注册周期性函数
|
||||
auto framework = GetFramework();
|
||||
if (framework) {
|
||||
auto threadManager = framework->GetThreadManager();
|
||||
if (threadManager) {
|
||||
threadManager->RegisterFunction(
|
||||
GetUniqueId(), std::bind(&XNModelObject::StepUpdate, this),
|
||||
d->_threadID, d->_runFreq, d->_runNode, d->_runPriority);
|
||||
}
|
||||
}
|
||||
|
||||
// 加载动态库
|
||||
XN_STRING mathlib = getStringFromSqlite3(stmt, 13);
|
||||
if (mathlib.length() > 0) {
|
||||
// 使用标准C++文件路径处理
|
||||
// std::filesystem::path xmlPath(GetXmlPath());
|
||||
// d->_sLibPath = xmlPath.parent_path().string() + "/" + mathlib;
|
||||
XN_STRING libPath = d->_sLibPath + "/" + mathlib;
|
||||
// 使用标准C++动态库加载
|
||||
d->_dynamicLib = loadLibrary(libPath);
|
||||
if (d->_dynamicLib) { // 动态库加载成功
|
||||
LOG_INFO("0x2163 模型 %1 加载数据包模型动态库 %2 成功!", GetObjectName(),
|
||||
libPath);
|
||||
} else {
|
||||
LOG_WARNING(
|
||||
"0x2160 模型 %1 未找到数据包模型动态库 %2, 将不调用数据包模型!",
|
||||
GetObjectName(), libPath);
|
||||
d->_dynamicLib = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: 读取模型命令列表
|
||||
// 清理资源
|
||||
finalizeSql(stmt);
|
||||
closeDatabase(db);
|
||||
}
|
||||
|
||||
// 单步执行函数
|
||||
void XNModelObject::StepUpdate() {
|
||||
T_D();
|
||||
XN_UINT32 setFreq = d->_setFreq < 1.0 ? 1 : (XN_UINT32)d->_setFreq;
|
||||
if (d->_dataWriter != nullptr && d->_runCnt > 0 &&
|
||||
d->_runCnt % setFreq == 0) {
|
||||
XNSim::XNSimStatus::XNModelStatus modelStatus;
|
||||
modelStatus.XNModelName(GetObjectName());
|
||||
modelStatus.XNModelID(GetUniqueId());
|
||||
modelStatus.XNModelSt(1);
|
||||
modelStatus.XNModelThID(d->_threadID);
|
||||
modelStatus.XNModelNode(d->_runNode);
|
||||
modelStatus.XNModelPro(d->_runPriority);
|
||||
modelStatus.XNModelRunCnt(d->_runCnt);
|
||||
XN_TIMESPEC now;
|
||||
getCurrentRTTime(&now);
|
||||
double time_diff = calculateRTTime(&now, &d->_lastRunTime);
|
||||
modelStatus.XNMdlCurFreq(d->_setFreq / time_diff);
|
||||
modelStatus.XNMdlSetFreq(d->_setFreq);
|
||||
d->_dataWriter->write(&modelStatus);
|
||||
d->_lastRunTime = now;
|
||||
LOG_DEBUG("Model: %1 Write DDS!", GetObjectName());
|
||||
}
|
||||
d->_runCnt++;
|
||||
}
|
||||
|
||||
// 运行前最后准备函数
|
||||
void XNModelObject::PrepareForExecute() {
|
||||
T_D();
|
||||
d->_runCnt = 0;
|
||||
// 注册DDS
|
||||
RegisterDDSParticipant();
|
||||
getCurrentRTTime(&d->_lastRunTime);
|
||||
}
|
||||
|
||||
void XNModelObject::RegisterDDSParticipant() {
|
||||
T_D();
|
||||
auto framework = GetFramework();
|
||||
if (framework == nullptr) {
|
||||
LOG_WARNING("Failed to get Framework!");
|
||||
return;
|
||||
}
|
||||
auto ddsManager = framework->GetDDSManager();
|
||||
if (ddsManager == nullptr) {
|
||||
LOG_WARNING("Failed to get DDSManager!");
|
||||
return;
|
||||
}
|
||||
XN_UINT32 MyID = GetUniqueId();
|
||||
d->_dataWriter =
|
||||
ddsManager
|
||||
->RegisterPublisher<XNSim::XNSimStatus::XNModelStatusPubSubType>(
|
||||
"XNSim::XNSimStatus::XNModelStatus", MyID);
|
||||
}
|
||||
|
||||
XN_INT32 XNModelObject::RegisterEventHandler(const XN_STRING &eventName,
|
||||
XNEventCallback callback,
|
||||
bool async,
|
||||
XNEvent::Priority priority) {
|
||||
// 获取事件管理器
|
||||
auto framework = GetFramework();
|
||||
if (framework == nullptr) {
|
||||
LOG_WARNING("Failed to get Framework!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
XNEventManagerPtr eventManager = framework->GetEventManager();
|
||||
if (eventManager == nullptr) {
|
||||
LOG_WARNING("Failed to get EventManager!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 注册事件处理器
|
||||
return eventManager->RegisterEventHandler(eventName, callback, GetUniqueId(),
|
||||
async, priority);
|
||||
}
|
||||
|
||||
void XNModelObject::TriggerEvent(const XN_STRING &eventName,
|
||||
const XN_ANY &eventData, XN_BOOL forceAsync,
|
||||
XNEvent::Priority priority) {
|
||||
// 获取事件管理器
|
||||
auto framework = GetFramework();
|
||||
if (framework == nullptr) {
|
||||
LOG_WARNING("Failed to get Framework!");
|
||||
return;
|
||||
}
|
||||
|
||||
XNEventManagerPtr eventManager = framework->GetEventManager();
|
||||
if (eventManager == nullptr) {
|
||||
LOG_WARNING("Failed to get EventManager!");
|
||||
return;
|
||||
}
|
||||
|
||||
// 触发事件
|
||||
eventManager->TriggerEvent(eventName, eventData, forceAsync, priority);
|
||||
}
|
||||
} // namespace XNSim
|
267
XNCore_Win/XNModelObject/XNModelObject.h
Normal file
267
XNCore_Win/XNModelObject/XNModelObject.h
Normal file
@ -0,0 +1,267 @@
|
||||
/**
|
||||
* @file XNModelObject.h
|
||||
* @author jinchao
|
||||
* @brief 模型基类头文件
|
||||
* @version 1.0
|
||||
* @date 2024-11-07
|
||||
*
|
||||
* @copyright Copyright (c) 2024 XN
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
#include "XNEventManager/XNEventManager.h"
|
||||
#include "XNObject/XNObject.h"
|
||||
|
||||
namespace XNSim {
|
||||
struct XNModelObjectPrivate;
|
||||
|
||||
/**
|
||||
* @brief 模型基类
|
||||
* @details 所有模型系统中模型的基类,预先实现了部分模型共有的功能。
|
||||
*/
|
||||
class XNModelObject : public XNObject {
|
||||
XN_METATYPE(XNModelObject, XNObject)
|
||||
XN_DECLARE_PRIVATE(XNModelObject)
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief 模型基类默认构造函数
|
||||
*/
|
||||
XNModelObject();
|
||||
|
||||
/**
|
||||
* @brief 模型基类默认析构函数
|
||||
*/
|
||||
virtual ~XNModelObject();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief 模型基类带参构造函数
|
||||
* @param p:XNModelObjectPrivate类型,私有结构体指针
|
||||
* @details 子类构造时调用此构造函数,传入子类的私有结构体指针
|
||||
*/
|
||||
XNModelObject(PrivateType *p);
|
||||
|
||||
public:
|
||||
void SetFramework(XNFrameworkPtr framework);
|
||||
|
||||
protected:
|
||||
XNFrameworkPtr GetFramework() const;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief 获取模型描述
|
||||
* @return const QString&:模型描述
|
||||
*/
|
||||
const XN_STRING &GetDescription();
|
||||
|
||||
/**
|
||||
* @brief 设置模型描述
|
||||
* @param sDescription:QString类型,模型描述
|
||||
*/
|
||||
void SetDescription(const XN_STRING &sDescription);
|
||||
|
||||
/**
|
||||
* @brief 获取作者
|
||||
* @return const QString&: 作者
|
||||
*/
|
||||
const XN_STRING &GetAuthor();
|
||||
|
||||
/**
|
||||
* @brief 设置作者
|
||||
* @param sAuthor: QString类型,作者
|
||||
*/
|
||||
void SetAuthor(const XN_STRING &sAuthor);
|
||||
|
||||
/**
|
||||
* @brief 获取模型配置文件路径
|
||||
* @return const QString&: 模型配置文件路径
|
||||
*/
|
||||
const XN_STRING &GetXmlPath();
|
||||
|
||||
/**
|
||||
* @brief 设置模型配置文件路径
|
||||
* @param sXmlPath:QString类型,模型配置文件路径
|
||||
*/
|
||||
void SetXmlPath(const XN_STRING &sXmlPath);
|
||||
|
||||
/**
|
||||
* @brief 获取模型创建时间
|
||||
* @return const XNTimePoint&:模型创建时间
|
||||
*/
|
||||
const XNTimePoint &GetCreateTime();
|
||||
|
||||
/**
|
||||
* @brief 设置模型创建时间
|
||||
* @param cTime: XNTimePoint类型,模型创建时间
|
||||
*/
|
||||
void SetCreateTime(const XNTimePoint &cTime);
|
||||
|
||||
/**
|
||||
* @brief 获取模型修改时间
|
||||
* @return const XNTimePoint&:模型修改时间
|
||||
*/
|
||||
const XNTimePoint &GetChangeTime();
|
||||
|
||||
/**
|
||||
* @brief 设置模型修改时间
|
||||
* @param cTime: XNTimePoint类型,模型修改时间
|
||||
*/
|
||||
void SetChangeTime(const XNTimePoint &cTime);
|
||||
|
||||
/**
|
||||
* @brief 获取模型版本号
|
||||
* @return const XNString&: 模型版本号
|
||||
*/
|
||||
const XN_STRING &GetVersion();
|
||||
|
||||
/**
|
||||
* @brief 设置模型版本号
|
||||
* @param sVersion: std::string类型,模型版本号
|
||||
*/
|
||||
void SetVersion(const XN_STRING &sVersion);
|
||||
|
||||
/**
|
||||
* @brief 获取模型运行频率组
|
||||
* @return uint32_t: 模型运行频率组
|
||||
*/
|
||||
XN_UINT32 GetRunFreq() const;
|
||||
|
||||
/**
|
||||
* @brief 设置模型运行频率组
|
||||
* @param runFreq: uint32_t类型,模型运行频率组
|
||||
*/
|
||||
void SetRunFreq(XN_UINT32 runFreq);
|
||||
|
||||
/**
|
||||
* @brief 获取模型运行节点
|
||||
* @return uint32_t: 模型运行节点
|
||||
*/
|
||||
XN_UINT32 GetRunNode() const;
|
||||
|
||||
/**
|
||||
* @brief 设置模型运行节点
|
||||
* @param runNode: uint32_t类型,模型运行节点
|
||||
*/
|
||||
void SetRunNode(XN_UINT32 runNode);
|
||||
|
||||
/**
|
||||
* @brief 获取模型运行优先级
|
||||
* @return uint32_t: 模型运行优先级
|
||||
*/
|
||||
XN_UINT32 GetRunPriority() const;
|
||||
|
||||
/**
|
||||
* @brief 设置模型运行优先级
|
||||
* @param runPriority: uint32_t类型,模型运行优先级
|
||||
*/
|
||||
void SetRunPriority(XN_UINT32 runPriority);
|
||||
|
||||
/**
|
||||
* @brief 获取模型设置频率
|
||||
* @return double: 模型设置频率
|
||||
*/
|
||||
XN_DOUBLE GetSetFreq() const;
|
||||
|
||||
/**
|
||||
* @brief 设置模型设置频率
|
||||
* @param setFreq: double类型,模型设置频率
|
||||
*/
|
||||
void SetSetFreq(XN_DOUBLE setFreq);
|
||||
|
||||
/**
|
||||
* @brief 获取模型动态库路径
|
||||
* @return const std::string&: 模型动态库路径
|
||||
*/
|
||||
const XN_STRING &GetLibPath();
|
||||
|
||||
/**
|
||||
* @brief 设置模型动态库路径
|
||||
* @param sLibPath: std::string类型,模型动态库路径
|
||||
*/
|
||||
void SetLibPath(const XN_STRING &sLibPath);
|
||||
|
||||
/**
|
||||
* @brief 单步执行函数
|
||||
* @details 模型默认的周期性执行函数
|
||||
*/
|
||||
virtual void StepUpdate();
|
||||
|
||||
/**
|
||||
* @brief 注册事件处理器
|
||||
* @param eventName: 事件名称
|
||||
* @param callback: 事件处理回调函数
|
||||
* @param async: 是否异步处理
|
||||
* @return: 返回处理器ID,失败返回-1
|
||||
*/
|
||||
int RegisterEventHandler(
|
||||
const XN_STRING &eventName, XNEventCallback callback,
|
||||
XN_BOOL async = false,
|
||||
XNEvent::Priority priority = XNEvent::Priority::Normal);
|
||||
|
||||
/**
|
||||
* @brief 触发事件
|
||||
* @param eventName: 要触发的事件名称
|
||||
* @param eventData: 事件携带的数据
|
||||
* @param forceAsync: 强制异步处理
|
||||
*/
|
||||
void TriggerEvent(const XN_STRING &eventName,
|
||||
const XN_ANY &eventData = XN_ANY(),
|
||||
XN_BOOL forceAsync = false,
|
||||
XNEvent::Priority priority = XNEvent::Priority::Normal);
|
||||
|
||||
/**
|
||||
* @brief 注册实时事件处理器
|
||||
* @param eventName: 事件名称
|
||||
* @param callback: 事件处理回调函数
|
||||
* @return: 返回处理器ID,失败返回-1
|
||||
*/
|
||||
int RegisterRTEventHandler(const XN_STRING &eventName,
|
||||
XNEventCallback callback) {
|
||||
return RegisterEventHandler(eventName, callback, true,
|
||||
XNEvent::Priority::RealTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 触发实时事件
|
||||
* @param eventName: 要触发的事件名称
|
||||
* @param eventData: 事件携带的数据
|
||||
*/
|
||||
void TriggerRTEvent(const XN_STRING &eventName,
|
||||
const XN_ANY &eventData = XN_ANY()) {
|
||||
TriggerEvent(eventName, eventData, true, XNEvent::Priority::RealTime);
|
||||
}
|
||||
|
||||
void SetInitializeType(XN_UINT32 initialType);
|
||||
|
||||
void SetThreadID(XN_UINT32 threadID);
|
||||
|
||||
XN_UINT32 GetThreadID() const;
|
||||
|
||||
/**
|
||||
* @brief 初始化函数
|
||||
* @details
|
||||
* 模型的初始化函数接口,子类继承时要调用父类初始化接口,或在此函数中使用AddMyFunction方法注册需要被线程调用的函数
|
||||
*/
|
||||
virtual void Initialize();
|
||||
|
||||
/**
|
||||
* @brief 仿真系统运行前做最后处理
|
||||
* @details 系统运行前模型做最后处理的接口
|
||||
*/
|
||||
virtual void PrepareForExecute();
|
||||
|
||||
public:
|
||||
virtual void RegisterDDSParticipant();
|
||||
|
||||
private:
|
||||
void ParseXml();
|
||||
void ParseConfig();
|
||||
};
|
||||
} // namespace XNSim
|
||||
|
||||
#define XN_MODEL_INITIALIZE(ClassName) \
|
||||
extern "C" XNSim::XNModelObjectPtr Initial##ClassName() { \
|
||||
XNSim::ClassName##Ptr obj = std::make_shared<XNSim::ClassName>(); \
|
||||
return obj; \
|
||||
}
|
98
XNCore_Win/XNModelObject/XNModelObject_p.h
Normal file
98
XNCore_Win/XNModelObject/XNModelObject_p.h
Normal file
@ -0,0 +1,98 @@
|
||||
/**
|
||||
* @file XNModelObject_p.h
|
||||
* @author jinchao
|
||||
* @brief 模型基类私有头文件
|
||||
* @version 1.0
|
||||
* @date 2024-11-07
|
||||
*
|
||||
* @copyright Copyright (c) 2024 XN
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
#include "XNObject/XNObject_p.h"
|
||||
|
||||
namespace XNSim {
|
||||
/**
|
||||
* @brief 模型基类私有结构体
|
||||
*/
|
||||
struct XNModelObjectPrivate : public XNObjectPrivate {
|
||||
XNFrameworkPtr _framework;
|
||||
/**
|
||||
* @brief 模型描述
|
||||
*/
|
||||
XN_STRING _sDescription;
|
||||
/**
|
||||
* @brief 模型作者
|
||||
*/
|
||||
XN_STRING _sAuthor;
|
||||
/**
|
||||
* @brief 模型配置文件路径
|
||||
*/
|
||||
XN_STRING _sXmlPath;
|
||||
/**
|
||||
* @brief 数据包模型动态库路径
|
||||
*/
|
||||
XN_STRING _sLibPath;
|
||||
/**
|
||||
* @brief 模型创建时间
|
||||
*/
|
||||
XNTimePoint _cCreatTime;
|
||||
/**
|
||||
* @brief 模型修改时间
|
||||
*/
|
||||
XNTimePoint _cChangeTime;
|
||||
/**
|
||||
* @brief 模型版本号
|
||||
*/
|
||||
XN_STRING _sVersion;
|
||||
/**
|
||||
* @brief 数据包模型动态库句柄
|
||||
*/
|
||||
XN_HANDLE _dynamicLib = nullptr;
|
||||
|
||||
/**
|
||||
* @brief 发布者信息
|
||||
*/
|
||||
XNDDSDataWriterPtr _dataWriter;
|
||||
|
||||
/**
|
||||
* @brief 模型运行时间
|
||||
*/
|
||||
XN_TIMESPEC _lastRunTime;
|
||||
|
||||
/**
|
||||
* @brief 模型运行次数
|
||||
*/
|
||||
XN_UINT64 _runCnt;
|
||||
|
||||
/**
|
||||
* @brief 模型运行频率
|
||||
*/
|
||||
XN_UINT32 _runFreq;
|
||||
|
||||
/**
|
||||
* @brief 模型运行节点
|
||||
*/
|
||||
XN_UINT32 _runNode;
|
||||
|
||||
/**
|
||||
* @brief 模型运行优先级
|
||||
*/
|
||||
XN_UINT32 _runPriority;
|
||||
|
||||
/**
|
||||
* @brief 模型设置频率
|
||||
*/
|
||||
XN_DOUBLE _setFreq;
|
||||
|
||||
/**
|
||||
* @brief 模型初始化类型
|
||||
*/
|
||||
XN_UINT32 _initialType;
|
||||
|
||||
/**
|
||||
* @brief 模型线程ID
|
||||
*/
|
||||
XN_UINT32 _threadID;
|
||||
};
|
||||
} // namespace XNSim
|
7
XNCore_Win/XNObject/CMakeLists.txt
Normal file
7
XNCore_Win/XNObject/CMakeLists.txt
Normal file
@ -0,0 +1,7 @@
|
||||
set(XNOBJECT_SOURCES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XNObject.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XNObject_p.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XNObject.cpp
|
||||
)
|
||||
|
||||
set(XNCORE_SOURCES ${XNCORE_SOURCES} ${XNOBJECT_SOURCES} PARENT_SCOPE)
|
33
XNCore_Win/XNObject/XNObject.cpp
Normal file
33
XNCore_Win/XNObject/XNObject.cpp
Normal file
@ -0,0 +1,33 @@
|
||||
#include "XNObject.h"
|
||||
#include "XNObject_p.h"
|
||||
|
||||
namespace XNSim {
|
||||
XNObject::XNObject() : _Private_Ptr(new XNObjectPrivate()) {
|
||||
_Private_Ptr->_Public_Ptr = this;
|
||||
}
|
||||
|
||||
XNObject::XNObject(PrivateType *p) : _Private_Ptr(p) {
|
||||
_Private_Ptr->_Public_Ptr = this;
|
||||
}
|
||||
|
||||
XNObject::~XNObject() {
|
||||
if (_Private_Ptr) {
|
||||
delete _Private_Ptr;
|
||||
}
|
||||
_Private_Ptr = nullptr;
|
||||
}
|
||||
|
||||
XNObjectPrivate::~XNObjectPrivate() { _Public_Ptr = nullptr; }
|
||||
|
||||
XN_UINT32 XNObject::GetUniqueId() { return _Private_Ptr->uUniqueID; }
|
||||
|
||||
void XNObject::SetUniqueId(const XN_UINT32 &uniqueId) {
|
||||
_Private_Ptr->uUniqueID = uniqueId;
|
||||
}
|
||||
|
||||
const XN_STRING &XNObject::GetObjectName() { return _Private_Ptr->sObjectName; }
|
||||
|
||||
void XNObject::SetObjectName(const XN_STRING &name) {
|
||||
_Private_Ptr->sObjectName = name;
|
||||
}
|
||||
} // namespace XNSim
|
99
XNCore_Win/XNObject/XNObject.h
Normal file
99
XNCore_Win/XNObject/XNObject.h
Normal file
@ -0,0 +1,99 @@
|
||||
/**
|
||||
* @file XNObject.h
|
||||
* @author jinchao
|
||||
* @brief 基础对象类
|
||||
* @version 1.0
|
||||
* @date 2025-01-08
|
||||
*
|
||||
* @copyright Copyright (c) 2025 COMAC
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "XNGlobalDefine/XNDefine.h"
|
||||
#include "XNLogger/XNLogger.h"
|
||||
|
||||
namespace XNSim {
|
||||
struct XNObjectPrivate;
|
||||
|
||||
/**
|
||||
* @brief 基础对象类
|
||||
*/
|
||||
class XNCORE_EXPORT XNObject : public std::enable_shared_from_this<XNObject> {
|
||||
XN_METATYPE_P(XNObject)
|
||||
XN_NOCOPYABLE(XNObject)
|
||||
protected:
|
||||
using PrivateType = XNObjectPrivate;
|
||||
/**
|
||||
* @brief 私有数据成员
|
||||
*/
|
||||
PrivateType *_Private_Ptr;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief 构造函数
|
||||
*/
|
||||
XNObject();
|
||||
|
||||
/**
|
||||
* @brief 析构函数
|
||||
*/
|
||||
virtual ~XNObject();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief 构造函数
|
||||
* @param p 私有数据成员
|
||||
*/
|
||||
XNObject(PrivateType *p);
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief 获取唯一ID
|
||||
* @return 唯一ID
|
||||
*/
|
||||
XN_UINT32 GetUniqueId();
|
||||
|
||||
/**
|
||||
* @brief 设置唯一ID
|
||||
* @param uniqueId 唯一ID
|
||||
*/
|
||||
void SetUniqueId(const XN_UINT32 &uniqueId);
|
||||
|
||||
/**
|
||||
* @brief 获取对象名称
|
||||
* @return 对象名称
|
||||
*/
|
||||
const XN_STRING &GetObjectName();
|
||||
|
||||
/**
|
||||
* @brief 设置对象名称
|
||||
* @param name 对象名称
|
||||
*/
|
||||
void SetObjectName(const XN_STRING &name);
|
||||
};
|
||||
|
||||
class XNFramework;
|
||||
class XNDDSManager;
|
||||
class XNEventManager;
|
||||
class XNModelManager;
|
||||
class XNServiceManager;
|
||||
class XNThreadManager;
|
||||
class XNTimeManager;
|
||||
class XNConfigManager;
|
||||
class XNThreadObject;
|
||||
class XNModelObject;
|
||||
class XNServiceObject;
|
||||
|
||||
XNCLASS_PTR_DECLARE(XNFramework)
|
||||
XNCLASS_PTR_DECLARE(XNDDSManager)
|
||||
XNCLASS_PTR_DECLARE(XNEventManager)
|
||||
XNCLASS_PTR_DECLARE(XNModelManager)
|
||||
XNCLASS_PTR_DECLARE(XNServiceManager)
|
||||
XNCLASS_PTR_DECLARE(XNThreadManager)
|
||||
XNCLASS_PTR_DECLARE(XNTimeManager)
|
||||
XNCLASS_PTR_DECLARE(XNConfigManager)
|
||||
XNCLASS_PTR_DECLARE(XNThreadObject)
|
||||
XNCLASS_PTR_DECLARE(XNModelObject)
|
||||
XNCLASS_PTR_DECLARE(XNServiceObject)
|
||||
} // namespace XNSim
|
36
XNCore_Win/XNObject/XNObject_p.h
Normal file
36
XNCore_Win/XNObject/XNObject_p.h
Normal file
@ -0,0 +1,36 @@
|
||||
/**
|
||||
* @file XNObject_p.h
|
||||
* @author jinchao
|
||||
* @brief 基础对象类的私有数据成员
|
||||
* @version 1.0
|
||||
* @date 2025-01-08
|
||||
*
|
||||
* @copyright Copyright (c) 2025 COMAC
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "XNObject.h"
|
||||
|
||||
namespace XNSim {
|
||||
/**
|
||||
* @brief 基础对象类的私有数据成员
|
||||
*/
|
||||
struct XNObjectPrivate {
|
||||
virtual ~XNObjectPrivate();
|
||||
/**
|
||||
* @brief 基础对象类指针
|
||||
*/
|
||||
XNObject *_Public_Ptr;
|
||||
|
||||
/**
|
||||
* @brief 唯一ID
|
||||
*/
|
||||
XN_UINT32 uUniqueID;
|
||||
|
||||
/**
|
||||
* @brief 对象名称
|
||||
*/
|
||||
XN_STRING sObjectName;
|
||||
};
|
||||
} // namespace XNSim
|
7
XNCore_Win/XNServiceManager/CMakeLists.txt
Normal file
7
XNCore_Win/XNServiceManager/CMakeLists.txt
Normal file
@ -0,0 +1,7 @@
|
||||
set(XNSERVICEMANAGER_SOURCES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XNServiceManager.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XNServiceManager_p.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XNServiceManager.cpp
|
||||
)
|
||||
|
||||
set(XNCORE_SOURCES ${XNCORE_SOURCES} ${XNSERVICEMANAGER_SOURCES} PARENT_SCOPE)
|
122
XNCore_Win/XNServiceManager/XNServiceManager.cpp
Normal file
122
XNCore_Win/XNServiceManager/XNServiceManager.cpp
Normal file
@ -0,0 +1,122 @@
|
||||
#include "XNServiceManager.h"
|
||||
#include "XNServiceManager_p.h"
|
||||
#include "XNServiceObject/XNServiceObject.h"
|
||||
|
||||
namespace XNSim {
|
||||
XNServiceManager::XNServiceManager()
|
||||
: XNBaseFrameObject(new XNServiceManagerPrivate()) {
|
||||
SetUniqueId(enumValue(XNCoreObjectID::ServiceManager));
|
||||
SetObjectName("XNServiceManager");
|
||||
T_D();
|
||||
d->ServiceIDAssigned.resize(XN_SERVICE_ID_SIZE, false);
|
||||
}
|
||||
|
||||
XNServiceManager::~XNServiceManager() {}
|
||||
|
||||
XNServiceManager::XNServiceManager(PrivateType *p) : XNBaseFrameObject(p) {}
|
||||
|
||||
bool XNServiceManager::Initialize() {
|
||||
T_D();
|
||||
LOG_INFO("XNServiceManager Initialize Success!");
|
||||
d->_status = XNFrameObjectStatus::Initialized;
|
||||
return true;
|
||||
}
|
||||
|
||||
XN_BOOL XNServiceManager::PrepareForExecute() {
|
||||
T_D();
|
||||
for (auto &service : d->ServiceList) {
|
||||
service.second->PrepareForExecute();
|
||||
}
|
||||
d->_status = XNFrameObjectStatus::Ready;
|
||||
LOG_INFO("XNServiceManager is prepared!");
|
||||
return true;
|
||||
}
|
||||
|
||||
void XNServiceManager::LoadService(const XN_STRING &servicePath,
|
||||
const XN_STRING &serviceName,
|
||||
const XN_STRING &serviceVersion,
|
||||
XN_UINT32 initialType) {
|
||||
T_D();
|
||||
XN_HANDLE handle = loadLibrary(servicePath);
|
||||
if (handle) {
|
||||
typedef XNServiceObjectPtr (*InitialServiceFunc)();
|
||||
XN_STRING initialServiceName = "Initial" + serviceName;
|
||||
InitialServiceFunc initialService =
|
||||
(InitialServiceFunc)getSymbol(handle, initialServiceName);
|
||||
if (initialService) {
|
||||
XNServiceObjectPtr service = initialService();
|
||||
if (service) {
|
||||
XN_UINT32 serviceID = RegisterService();
|
||||
if (serviceID == 0) {
|
||||
LOG_WARNING(
|
||||
"0x2174 Assign Service ID Failed, Service ID is used up!");
|
||||
closeLibrary(handle);
|
||||
return;
|
||||
}
|
||||
service->SetUniqueId(serviceID);
|
||||
service->SetObjectName(serviceName);
|
||||
service->SetFramework(GetFramework());
|
||||
if (initialType == 0) {
|
||||
// 使用std::filesystem处理路径
|
||||
XN_PATH configPath = XN_PATH(servicePath).parent_path() /
|
||||
(serviceName + "_V" + serviceVersion + ".scfg");
|
||||
service->SetXmlPath(configPath.string());
|
||||
} else if (initialType == 1) {
|
||||
LOG_INFO("0x2176 加载服务: %1", serviceName + "," + serviceVersion);
|
||||
service->SetXmlPath(serviceName + "," + serviceVersion);
|
||||
} else {
|
||||
LOG_WARNING("0x2175 InitialType Error, InitialType: %d", initialType);
|
||||
closeLibrary(handle);
|
||||
return;
|
||||
}
|
||||
|
||||
// 注册服务到管理器
|
||||
d->ServiceList[serviceID] = service;
|
||||
service->SetInitializeType(initialType);
|
||||
// 初始化服务
|
||||
LOG_INFO("0x2176 初始化服务: %1", serviceName);
|
||||
service->Initialize();
|
||||
} else {
|
||||
LOG_WARNING("0x2173 Service %s Not found in dynamic link library %s!",
|
||||
serviceName, servicePath);
|
||||
closeLibrary(handle);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
LOG_WARNING("0x2177 Service %s Initialization Failed, Function "
|
||||
"InitialService Not Found!",
|
||||
serviceName);
|
||||
closeLibrary(handle);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
LOG_WARNING(
|
||||
"0x2172 Service %s Dynamic link library loading failed! Error: %s",
|
||||
serviceName, LoadError());
|
||||
}
|
||||
}
|
||||
|
||||
XNServiceObjectPtr XNServiceManager::GetService(XN_UINT32 serviceID) {
|
||||
T_D();
|
||||
if (d->ServiceIDAssigned[serviceID - XN_SERVICE_ID_START] &&
|
||||
d->ServiceList.find(serviceID) != d->ServiceList.end()) {
|
||||
return d->ServiceList[serviceID];
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
XN_UINT32 XNServiceManager::RegisterService() {
|
||||
T_D();
|
||||
// 从20000~29999的编号中分配ID
|
||||
for (XN_UINT32 i = 0; i < XN_SERVICE_ID_SIZE; i++) {
|
||||
if (d->ServiceIDAssigned[i])
|
||||
continue;
|
||||
else {
|
||||
d->ServiceIDAssigned[i] = true;
|
||||
return i + XN_SERVICE_ID_START;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
} // namespace XNSim
|
34
XNCore_Win/XNServiceManager/XNServiceManager.h
Normal file
34
XNCore_Win/XNServiceManager/XNServiceManager.h
Normal file
@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
#include "XNBaseFrameObject/XNBaseFrameObject.h"
|
||||
|
||||
namespace XNSim {
|
||||
struct XNServiceManagerPrivate;
|
||||
|
||||
class XNServiceManager : public XNBaseFrameObject {
|
||||
XN_METATYPE(XNServiceManager, XNBaseFrameObject)
|
||||
XN_DECLARE_PRIVATE(XNServiceManager)
|
||||
public:
|
||||
/**
|
||||
* @brief 服务管理器类默认构造函数
|
||||
*/
|
||||
XNServiceManager();
|
||||
|
||||
/**
|
||||
* @brief 服务管理器类析构函数
|
||||
*/
|
||||
virtual ~XNServiceManager();
|
||||
|
||||
protected:
|
||||
XNServiceManager(PrivateType *p);
|
||||
|
||||
public:
|
||||
virtual XN_BOOL Initialize() override;
|
||||
virtual XN_BOOL PrepareForExecute() override;
|
||||
void LoadService(const XN_STRING &servicePath, const XN_STRING &serviceName,
|
||||
const XN_STRING &serviceVersion, XN_UINT32 initialType);
|
||||
|
||||
public:
|
||||
XNServiceObjectPtr GetService(XN_UINT32 serviceID);
|
||||
XN_UINT32 RegisterService();
|
||||
};
|
||||
} // namespace XNSim
|
20
XNCore_Win/XNServiceManager/XNServiceManager_p.h
Normal file
20
XNCore_Win/XNServiceManager/XNServiceManager_p.h
Normal file
@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
#include "XNBaseFrameObject/XNBaseFrameObject_p.h"
|
||||
|
||||
namespace XNSim {
|
||||
using XNServiceMap = std::map<XN_UINT32, XNServiceObjectPtr>;
|
||||
|
||||
struct XNServiceManagerPrivate : public XNBaseFrameObjectPrivate {
|
||||
/**
|
||||
* @brief 服务ID库
|
||||
* @details 所有服务已用ID的存储库
|
||||
*/
|
||||
XNAsignedIDFlag ServiceIDAssigned;
|
||||
|
||||
/**
|
||||
* @brief 服务列表
|
||||
* @details 所有服务的存储库
|
||||
*/
|
||||
XNServiceMap ServiceList;
|
||||
};
|
||||
} // namespace XNSim
|
7
XNCore_Win/XNServiceObject/CMakeLists.txt
Normal file
7
XNCore_Win/XNServiceObject/CMakeLists.txt
Normal file
@ -0,0 +1,7 @@
|
||||
set(XNSERVICEOBJECT_SOURCES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XNServiceObject.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XNServiceObject_p.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XNServiceObject.cpp
|
||||
)
|
||||
|
||||
set(XNCORE_SOURCES ${XNCORE_SOURCES} ${XNSERVICEOBJECT_SOURCES} PARENT_SCOPE)
|
294
XNCore_Win/XNServiceObject/XNServiceObject.cpp
Normal file
294
XNCore_Win/XNServiceObject/XNServiceObject.cpp
Normal file
@ -0,0 +1,294 @@
|
||||
#include "XNServiceObject.h"
|
||||
#include "XNEventManager/XNEventManager.h"
|
||||
#include "XNFramework/XNFramework.h"
|
||||
#include "XNServiceObject_p.h"
|
||||
|
||||
namespace XNSim {
|
||||
XNServiceObject::XNServiceObject() : XNObject(new XNServiceObjectPrivate()) {
|
||||
T_D();
|
||||
d->_initialType = 0;
|
||||
}
|
||||
|
||||
XNServiceObject::~XNServiceObject() {}
|
||||
|
||||
XNServiceObject::XNServiceObject(PrivateType *p) : XNObject(p) {}
|
||||
|
||||
const XN_STRING &XNServiceObject::GetVersion() {
|
||||
T_D();
|
||||
return d->_sVersion;
|
||||
}
|
||||
|
||||
const XN_STRING &XNServiceObject::GetDescription() {
|
||||
T_D();
|
||||
return d->_sDescription;
|
||||
}
|
||||
|
||||
const XN_STRING &XNServiceObject::GetAuthor() {
|
||||
T_D();
|
||||
return d->_sAuthor;
|
||||
}
|
||||
|
||||
const XN_STRING &XNServiceObject::GetXmlPath() {
|
||||
T_D();
|
||||
return d->_sXmlPath;
|
||||
}
|
||||
|
||||
const XNTimePoint &XNServiceObject::GetCreateTime() {
|
||||
T_D();
|
||||
return d->_cCreateTime;
|
||||
}
|
||||
|
||||
const XNTimePoint &XNServiceObject::GetChangeTime() {
|
||||
T_D();
|
||||
return d->_cChangeTime;
|
||||
}
|
||||
|
||||
void XNServiceObject::SetVersion(const XN_STRING &version) {
|
||||
T_D();
|
||||
d->_sVersion = version;
|
||||
}
|
||||
|
||||
void XNServiceObject::SetDescription(const XN_STRING &sDescription) {
|
||||
T_D();
|
||||
d->_sDescription = sDescription;
|
||||
}
|
||||
|
||||
void XNServiceObject::SetAuthor(const XN_STRING &sAuthor) {
|
||||
T_D();
|
||||
d->_sAuthor = sAuthor;
|
||||
}
|
||||
|
||||
void XNServiceObject::SetXmlPath(const XN_STRING &sXmlPath) {
|
||||
T_D();
|
||||
d->_sXmlPath = sXmlPath;
|
||||
}
|
||||
|
||||
void XNServiceObject::SetCreateTime(const XNTimePoint &cTime) {
|
||||
T_D();
|
||||
d->_cCreateTime = cTime;
|
||||
}
|
||||
|
||||
void XNServiceObject::SetChangeTime(const XNTimePoint &cTime) {
|
||||
T_D();
|
||||
d->_cChangeTime = cTime;
|
||||
}
|
||||
|
||||
XN_INT32 XNServiceObject::RegisterEventHandler(const XN_STRING &eventName,
|
||||
XNEventCallback callback,
|
||||
bool async,
|
||||
XNEvent::Priority priority) {
|
||||
// 注册事件处理器
|
||||
T_D();
|
||||
auto framework = GetFramework();
|
||||
if (framework) {
|
||||
auto eventManager = framework->GetEventManager();
|
||||
if (eventManager) {
|
||||
return eventManager->RegisterEventHandler(eventName, callback,
|
||||
GetUniqueId(), async, priority);
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void XNServiceObject::TriggerEvent(const XN_STRING &eventName,
|
||||
const XN_ANY &eventData, bool forceAsync,
|
||||
XNEvent::Priority priority) {
|
||||
// 触发事件
|
||||
T_D();
|
||||
auto framework = GetFramework();
|
||||
if (framework) {
|
||||
auto eventManager = framework->GetEventManager();
|
||||
if (eventManager) {
|
||||
eventManager->TriggerEvent(eventName, eventData, forceAsync, priority);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
XN_INT32 XNServiceObject::RegisterRTEventHandler(const XN_STRING &eventName,
|
||||
XNEventCallback callback) {
|
||||
return RegisterEventHandler(eventName, callback, true,
|
||||
XNEvent::Priority::RealTime);
|
||||
}
|
||||
|
||||
void XNServiceObject::TriggerRTEvent(const XN_STRING &eventName,
|
||||
const XN_ANY &eventData) {
|
||||
TriggerEvent(eventName, eventData, true, XNEvent::Priority::RealTime);
|
||||
}
|
||||
|
||||
void XNServiceObject::SetInitializeType(XN_UINT32 initialType) {
|
||||
T_D();
|
||||
d->_initialType = initialType;
|
||||
}
|
||||
|
||||
void XNServiceObject::Initialize() {
|
||||
T_D();
|
||||
if (d->_initialType == 0) {
|
||||
ParseXml();
|
||||
} else {
|
||||
ParseConfig();
|
||||
}
|
||||
}
|
||||
|
||||
void XNServiceObject::ParseXml() {
|
||||
T_D();
|
||||
XN_XMLDocument doc;
|
||||
if (LoadXmlFile(GetXmlPath(), doc) != 0) {
|
||||
LOG_WARNING("Failed to open the service configuration file: %1!",
|
||||
GetXmlPath());
|
||||
return;
|
||||
}
|
||||
|
||||
XN_XMLElement *rootNode = GetRootElement(doc);
|
||||
if (!rootNode) {
|
||||
LOG_WARNING("Invalid XML file format: %1!", GetXmlPath());
|
||||
return;
|
||||
}
|
||||
|
||||
XN_STRING serviceName = GetFirstChildElementText(rootNode, "Name");
|
||||
if (serviceName != GetObjectName()) {
|
||||
LOG_WARNING(
|
||||
"The service name in the configuration file of service %1 is not "
|
||||
"consistent "
|
||||
"with the service name in the configuration file of service %2!",
|
||||
GetObjectName(), serviceName);
|
||||
return;
|
||||
}
|
||||
|
||||
d->_sDescription = GetFirstChildElementText(rootNode, "Description");
|
||||
d->_sAuthor = GetFirstChildElementText(rootNode, "Author");
|
||||
d->_sVersion = GetFirstChildElementText(rootNode, "Version");
|
||||
|
||||
// 解析时间
|
||||
XN_STRING createTimeStr = GetFirstChildElementText(rootNode, "CreateTime");
|
||||
XN_STRING changeTimeStr = GetFirstChildElementText(rootNode, "ChangeTime");
|
||||
d->_cCreateTime = parseISOTime(createTimeStr);
|
||||
d->_cChangeTime = parseISOTime(changeTimeStr);
|
||||
|
||||
XN_XMLElement *nodeCmds = GetFirstChildElement(rootNode, "CommandList");
|
||||
if (nodeCmds) {
|
||||
for (XN_XMLElement *nodeCmd = GetFirstChildElement(nodeCmds, "Command");
|
||||
nodeCmd != nullptr;
|
||||
nodeCmd = GetNextSiblingElement(nodeCmd, "Command")) {
|
||||
XN_STRING cmdName = GetAttribute(nodeCmd, "Name");
|
||||
XN_STRING cmdDescription = GetAttribute(nodeCmd, "Description");
|
||||
XN_STRING cmdCall = GetAttribute(nodeCmd, "Call");
|
||||
// TODO: 处理命令信息
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void XNServiceObject::ParseConfig() {
|
||||
T_D();
|
||||
XN_STRINGLIST nameAndVersion = XNSplit(GetXmlPath(), ",");
|
||||
XN_STRING serviceName = nameAndVersion[0];
|
||||
XN_STRING serviceVersion = nameAndVersion[1];
|
||||
// 获取数据库路径
|
||||
XN_STRING dbPath = getEnv("XNCore");
|
||||
if (dbPath.empty()) {
|
||||
LOG_ERROR("0x1015 未设置XNCore环境变量, 引擎将退出!");
|
||||
return;
|
||||
}
|
||||
dbPath += "/database/XNSim.db";
|
||||
|
||||
// 打开数据库
|
||||
XN_DB_PTR db = openDatabase(dbPath);
|
||||
if (db == nullptr) {
|
||||
LOG_ERROR("0x1016 打开数据库失败: %1", dbPath);
|
||||
return;
|
||||
}
|
||||
|
||||
// 准备SQL语句
|
||||
XN_STRING sql =
|
||||
"SELECT * FROM XNServiceVersion WHERE ClassName = ? AND Version = ?";
|
||||
XN_DB_STMT_PTR stmt = prepareSql(db, sql);
|
||||
if (stmt == nullptr) {
|
||||
LOG_ERROR("0x1017 准备SQL语句失败: %1", sql);
|
||||
closeDatabase(db);
|
||||
return;
|
||||
}
|
||||
|
||||
// 绑定参数
|
||||
if (!bindText(stmt, 1, serviceName) || !bindText(stmt, 2, serviceVersion)) {
|
||||
LOG_ERROR("0x1018 绑定参数失败: %1", sqlite3_errmsg(db));
|
||||
finalizeSql(stmt);
|
||||
closeDatabase(db);
|
||||
return;
|
||||
}
|
||||
|
||||
// 执行查询
|
||||
if (!stepSql(stmt)) {
|
||||
LOG_ERROR("0x1019 未找到服务名称为%1,版本号%2的记录", serviceName.c_str(),
|
||||
serviceVersion.c_str());
|
||||
finalizeSql(stmt);
|
||||
closeDatabase(db);
|
||||
return;
|
||||
}
|
||||
d->_sDescription = getStringFromSqlite3(stmt, 5);
|
||||
d->_sAuthor = getStringFromSqlite3(stmt, 4);
|
||||
d->_sVersion = getStringFromSqlite3(stmt, 2);
|
||||
|
||||
// 解析时间
|
||||
XN_STRING createTimeStr = getStringFromSqlite3(stmt, 6);
|
||||
XN_STRING changeTimeStr = getStringFromSqlite3(stmt, 7);
|
||||
d->_cCreateTime = parseISOTime(createTimeStr);
|
||||
d->_cChangeTime = parseISOTime(changeTimeStr);
|
||||
|
||||
// 读取服务命令列表
|
||||
XN_STRING commandListStr = getStringFromSqlite3(stmt, 8);
|
||||
if (!commandListStr.empty()) {
|
||||
try {
|
||||
XN_JSON commandList = parseJson(commandListStr);
|
||||
if (commandList.is_array()) {
|
||||
for (const auto &cmd : commandList) {
|
||||
if (cmd.contains("Name") && cmd.contains("Description") &&
|
||||
cmd.contains("Call")) {
|
||||
LOG_INFO("0x1021 服务命令: %1", cmd["Name"].get<std::string>());
|
||||
// TODO: 处理服务命令信息
|
||||
// d->_commandList.emplace_back(
|
||||
// cmd["Name"].get<std::string>(),
|
||||
// cmd["Description"].get<std::string>(),
|
||||
// cmd["Call"].get<std::string>()
|
||||
// );
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (const std::exception &e) {
|
||||
LOG_WARNING("0x1020 解析服务命令列表失败: %1", e.what());
|
||||
}
|
||||
}
|
||||
|
||||
// 读取其他参数
|
||||
XN_STRING otherParamsStr = getStringFromSqlite3(stmt, 9);
|
||||
if (!otherParamsStr.empty()) {
|
||||
try {
|
||||
d->_otherParams = parseJson(otherParamsStr);
|
||||
} catch (const std::exception &e) {
|
||||
LOG_WARNING("0x1020 解析其他参数失败: %1", e.what());
|
||||
}
|
||||
}
|
||||
|
||||
// 清理资源
|
||||
finalizeSql(stmt);
|
||||
closeDatabase(db);
|
||||
}
|
||||
|
||||
void XNServiceObject::PrepareForExecute() {
|
||||
T_D();
|
||||
RegisterDDSParticipant();
|
||||
}
|
||||
|
||||
void XNServiceObject::RegisterDDSParticipant() {
|
||||
T_D();
|
||||
// TODO 注册服务状态主题参与者
|
||||
}
|
||||
|
||||
XNFrameworkPtr XNServiceObject::GetFramework() const {
|
||||
T_D();
|
||||
return d->pFramework;
|
||||
}
|
||||
|
||||
void XNServiceObject::SetFramework(XNFrameworkPtr framework) {
|
||||
T_D();
|
||||
d->pFramework = framework;
|
||||
}
|
||||
} // namespace XNSim
|
74
XNCore_Win/XNServiceObject/XNServiceObject.h
Normal file
74
XNCore_Win/XNServiceObject/XNServiceObject.h
Normal file
@ -0,0 +1,74 @@
|
||||
#pragma once
|
||||
|
||||
#include "XNEventManager/XNEventManager.h"
|
||||
#include "XNObject/XNObject.h"
|
||||
#include "XNServiceManager/XNServiceManager.h"
|
||||
|
||||
namespace XNSim {
|
||||
struct XNServiceObjectPrivate;
|
||||
|
||||
class XNServiceObject : public XNObject {
|
||||
XN_METATYPE(XNServiceObject, XNObject)
|
||||
XN_DECLARE_PRIVATE(XNServiceObject)
|
||||
public:
|
||||
XNServiceObject();
|
||||
virtual ~XNServiceObject();
|
||||
|
||||
protected:
|
||||
XNServiceObject(PrivateType *p);
|
||||
|
||||
public:
|
||||
const XN_STRING &GetVersion();
|
||||
const XN_STRING &GetDescription();
|
||||
const XN_STRING &GetAuthor();
|
||||
const XN_STRING &GetXmlPath();
|
||||
const XNTimePoint &GetCreateTime();
|
||||
const XNTimePoint &GetChangeTime();
|
||||
|
||||
void SetVersion(const XN_STRING &version);
|
||||
void SetDescription(const XN_STRING &description);
|
||||
void SetAuthor(const XN_STRING &author);
|
||||
void SetXmlPath(const XN_STRING &xmlPath);
|
||||
void SetCreateTime(const XNTimePoint &createTime);
|
||||
void SetChangeTime(const XNTimePoint &changeTime);
|
||||
|
||||
XN_INT32
|
||||
RegisterEventHandler(const XN_STRING &eventName, XNEventCallback callback,
|
||||
bool async = false,
|
||||
XNEvent::Priority priority = XNEvent::Priority::Normal);
|
||||
|
||||
void TriggerEvent(const XN_STRING &eventName,
|
||||
const XN_ANY &eventData = XN_ANY(), bool forceAsync = false,
|
||||
XNEvent::Priority priority = XNEvent::Priority::Normal);
|
||||
|
||||
XN_INT32 RegisterRTEventHandler(const XN_STRING &eventName,
|
||||
XNEventCallback callback);
|
||||
|
||||
void TriggerRTEvent(const XN_STRING &eventName,
|
||||
const XN_ANY &eventData = XN_ANY());
|
||||
|
||||
void SetInitializeType(XN_UINT32 initialType);
|
||||
|
||||
virtual void Initialize();
|
||||
virtual void PrepareForExecute();
|
||||
|
||||
virtual void RegisterDDSParticipant();
|
||||
|
||||
void SetFramework(XNFrameworkPtr framework);
|
||||
|
||||
protected:
|
||||
XNFrameworkPtr GetFramework() const;
|
||||
|
||||
private:
|
||||
void ParseXml();
|
||||
void ParseConfig();
|
||||
};
|
||||
|
||||
XNCLASS_PTR_DECLARE(XNServiceObject)
|
||||
} // namespace XNSim
|
||||
|
||||
#define XN_SERVICE_INITIALIZE(ClassName) \
|
||||
extern "C" XNSim::XNServiceObjectPtr Initial##ClassName() { \
|
||||
XNSim::ClassName##Ptr obj = std::make_shared<XNSim::ClassName>(); \
|
||||
return obj; \
|
||||
}
|
18
XNCore_Win/XNServiceObject/XNServiceObject_p.h
Normal file
18
XNCore_Win/XNServiceObject/XNServiceObject_p.h
Normal file
@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
#include "XNObject/XNObject_p.h"
|
||||
|
||||
namespace XNSim {
|
||||
struct XNServiceObjectPrivate : public XNObjectPrivate {
|
||||
XN_STRING _sDescription;
|
||||
XN_STRING _sAuthor;
|
||||
XN_STRING _sXmlPath;
|
||||
XNTimePoint _cCreateTime;
|
||||
XNTimePoint _cChangeTime;
|
||||
XN_STRING _sVersion;
|
||||
XNDDSDataWriterMap _dataWriters;
|
||||
XNFrameworkPtr pFramework;
|
||||
uint32_t _initialType;
|
||||
XN_JSON _otherParams;
|
||||
};
|
||||
|
||||
} // namespace XNSim
|
7
XNCore_Win/XNThreadManager/CMakeLists.txt
Normal file
7
XNCore_Win/XNThreadManager/CMakeLists.txt
Normal file
@ -0,0 +1,7 @@
|
||||
set(XNTHREADMANAGER_SOURCES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XNThreadManager.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XNThreadManager_p.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XNThreadManager.cpp
|
||||
)
|
||||
|
||||
set(XNCORE_SOURCES ${XNCORE_SOURCES} ${XNTHREADMANAGER_SOURCES} PARENT_SCOPE)
|
236
XNCore_Win/XNThreadManager/XNThreadManager.cpp
Normal file
236
XNCore_Win/XNThreadManager/XNThreadManager.cpp
Normal file
@ -0,0 +1,236 @@
|
||||
/**
|
||||
* @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) {
|
||||
// 如果频率分组不是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 > (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
|
167
XNCore_Win/XNThreadManager/XNThreadManager.h
Normal file
167
XNCore_Win/XNThreadManager/XNThreadManager.h
Normal file
@ -0,0 +1,167 @@
|
||||
/**
|
||||
* @file XNThreadManager.h
|
||||
* @author jinchao
|
||||
* @brief 线程管理器类头文件
|
||||
* @version 1.0
|
||||
* @date 2024-11-06
|
||||
*
|
||||
* @copyright Copyright (c) 2024 XN
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
#include "XNBaseFrameObject/XNBaseFrameObject.h"
|
||||
|
||||
namespace XNSim {
|
||||
struct XNThreadManagerPrivate;
|
||||
|
||||
/**
|
||||
* @brief 线程管理器类
|
||||
* @details
|
||||
* 主要负责创建、管理与控制模型调度线程,并向调度线程中添加需要调度执行的模型周期性函数
|
||||
*/
|
||||
class XNThreadManager : public XNBaseFrameObject {
|
||||
XN_METATYPE(XNThreadManager, XNBaseFrameObject)
|
||||
XN_DECLARE_PRIVATE(XNThreadManager)
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief 线程管理器类默认构造函数
|
||||
*/
|
||||
XNThreadManager();
|
||||
|
||||
/**
|
||||
* @brief 线程管理器类析构函数
|
||||
*/
|
||||
virtual ~XNThreadManager();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief 线程管理器类带参构造函数
|
||||
* @param dd:XNThreadManagerPrivate类型,私有结构体指针
|
||||
* @param parent:QObject类型,父对象指针
|
||||
* @details 子类构造时调用此构造函数,传入子类的私有结构体指针
|
||||
*/
|
||||
XNThreadManager(PrivateType *p);
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief 开始控制
|
||||
* @details 控制线程管理器开始运行接口
|
||||
*/
|
||||
void Start();
|
||||
|
||||
/**
|
||||
* @brief 停止控制
|
||||
* @details 控制线程管理器停止运行接口
|
||||
*/
|
||||
void Abort();
|
||||
|
||||
/**
|
||||
* @brief 暂停控制
|
||||
* @details 控制线程管理器暂停运行接口
|
||||
*/
|
||||
void Pause();
|
||||
|
||||
/**
|
||||
* @brief 继续控制
|
||||
* @details 控制线程管理器继续运行接口
|
||||
*/
|
||||
void Continue();
|
||||
|
||||
/**
|
||||
* @brief 初始化线程管理器
|
||||
* @return true: 初始化成功
|
||||
* @return false: 初始化失败
|
||||
* @details 线程管理器的初始化接口函数
|
||||
*/
|
||||
virtual XN_BOOL Initialize() override;
|
||||
|
||||
/**
|
||||
* @brief 仿真运行前最后处理
|
||||
* @note 线程管理器在所有线程开始执行前的准备工作
|
||||
*/
|
||||
virtual XN_BOOL PrepareForExecute() override;
|
||||
|
||||
/**
|
||||
* @brief 设置线程频率
|
||||
* @param threadID: UINT32类型,线程ID
|
||||
* @param freq: double类型,线程频率
|
||||
* @details 设置线程频率接口
|
||||
*/
|
||||
void SetThreadFreqByID(XN_UINT32 threadID, XN_DOUBLE freq);
|
||||
|
||||
/**
|
||||
* @brief 获取线程频率
|
||||
* @param threadID: UINT32类型,线程ID
|
||||
* @return double: 线程频率
|
||||
* @details 获取线程频率接口
|
||||
*/
|
||||
XN_DOUBLE GetThreadFreqByID(XN_UINT32 threadID);
|
||||
|
||||
/**
|
||||
* @brief 仿真控制
|
||||
* @param objectId: 对象ID
|
||||
* @param cmd: 仿真控制命令
|
||||
*/
|
||||
void SimControl(XN_UINT32 objectId, SimControlCmd cmd);
|
||||
|
||||
/**
|
||||
* @brief 获取运行状态
|
||||
* @return RunStatus: 枚举类,线程运行状态
|
||||
* @details 获取线程管理器运行状态接口
|
||||
*/
|
||||
RunStatus GetStatus();
|
||||
|
||||
/**
|
||||
* @brief 获取线程数量
|
||||
* @return quint32: 线程数量
|
||||
*/
|
||||
XN_UINT32 GetThreadCount();
|
||||
|
||||
/**
|
||||
* @brief 添加一个线程
|
||||
* @param name: XNString类型,线程名称
|
||||
* @param freq: double类型,线程运行频率,单位Hz
|
||||
* @param priority:
|
||||
* UINT32类型,线程运行优先级,99~0,优先级数值越大,优先级越高
|
||||
* @param CPUAff:
|
||||
* UINT32类型,线程的CPU亲和性掩码,按位表示某CPU核是否使用,从低到高,0表示不使用,1表示使用。
|
||||
* 例如:0x00000003表示使用0,1号CPU
|
||||
* @details 按照设置的参数创建线程
|
||||
*/
|
||||
virtual XN_UINT32 AddThreadPool(XN_STRING name, XN_DOUBLE freq,
|
||||
XN_UINT32 priority, XN_UINT32 CPUAff);
|
||||
|
||||
/**
|
||||
* @brief 向线程中添加周期性函数
|
||||
* @param id: UINT32类型,模型全局唯一ID
|
||||
* @param fun: XNCallBack函数包装器类型,需要提交的函数的包装
|
||||
* @param threadID: UINT32类型,线程ID
|
||||
* @param freqGroup:
|
||||
* UINT32类型,提交的函数运行频率组,0为基频,1为半频,2为1/4频,3为1/8频,4为1/16频,5为1/32频
|
||||
* @param RunPos: UINT32类型,提交的函数运行节点号,<2^(freqGroup)
|
||||
* @param RunPriorty:
|
||||
* UINT32类型,提交的函数运行优先级,99~0,优先级数值越大,优先级越高
|
||||
* @return true: 添加成功
|
||||
* @return false: 添加失败
|
||||
* @details 根据运行频率组和节点号向对应的线程中添加周期性函数
|
||||
*/
|
||||
void RegisterFunction(XN_UINT32 id, XNCallBack fun, XN_UINT32 threadID,
|
||||
XN_UINT32 freqGroup, XN_UINT32 RunPos,
|
||||
XN_UINT32 RunPriorty);
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief 注册函数校验
|
||||
* @param freqGroup:
|
||||
* UINT32类型,提交的函数运行频率组,0为基频,1为半频,2为1/4频,3为1/8频,4为1/16频,5为1/32频
|
||||
* @param RunPos: UINT32类型,提交的函数运行节点号,<2^(freqGroup)
|
||||
* @return true:提交的函数频率与节点号符合规则
|
||||
* @return false:提交的函数频率与节点号不符合规则
|
||||
*/
|
||||
bool IsFunParamRight(XN_UINT32 ModelID, XN_UINT32 freqGroup,
|
||||
XN_UINT32 RunPos);
|
||||
|
||||
XN_UINT32 AllocateThreadID();
|
||||
};
|
||||
} // namespace XNSim
|
72
XNCore_Win/XNThreadManager/XNThreadManager_p.h
Normal file
72
XNCore_Win/XNThreadManager/XNThreadManager_p.h
Normal file
@ -0,0 +1,72 @@
|
||||
/**
|
||||
* @file XNThreadManager_p.h
|
||||
* @author jinchao
|
||||
* @brief 线程管理器类私有头文件
|
||||
* @version 1.0
|
||||
* @date 2024-11-07
|
||||
*
|
||||
* @copyright Copyright (c) 2024 XN
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
#include "XNBaseFrameObject/XNBaseFrameObject_p.h"
|
||||
|
||||
namespace XNSim {
|
||||
/**
|
||||
* @brief 周期性函数存储结构体
|
||||
*/
|
||||
struct XNFunInfo {
|
||||
/**
|
||||
* @brief 周期性函数包装器
|
||||
*/
|
||||
XNCallBack fun;
|
||||
/**
|
||||
* @brief 线程ID
|
||||
*/
|
||||
XN_UINT32 threadID;
|
||||
/**
|
||||
* @brief 运行频率组
|
||||
*/
|
||||
XN_UINT32 freqGroup;
|
||||
/**
|
||||
* @brief 运行节点
|
||||
*/
|
||||
XN_UINT32 RunPos;
|
||||
/**
|
||||
* @brief 运行优先级
|
||||
*/
|
||||
XN_UINT32 RunPriority;
|
||||
};
|
||||
/**
|
||||
* @brief 声明周期性函数存储结构体的智能指针
|
||||
*/
|
||||
using XNFunInfoPtr = std::shared_ptr<XNFunInfo>;
|
||||
|
||||
using XNFunInfoMap = std::map<XN_UINT32, std::vector<XNFunInfoPtr>>;
|
||||
|
||||
using XNThreadMap = std::map<XN_UINT32, XNThreadObjectPtr>;
|
||||
|
||||
using XNThreadIDSet = std::set<XN_UINT32>;
|
||||
|
||||
/**
|
||||
* @brief 线程管理器类私有结构体
|
||||
*/
|
||||
struct XNThreadManagerPrivate : public XNBaseFrameObjectPrivate {
|
||||
/**
|
||||
* @brief 所有线程运行状态
|
||||
*/
|
||||
RunStatus _eRunStatus;
|
||||
/**
|
||||
* @brief 线程列表
|
||||
*/
|
||||
XNThreadMap _threadList;
|
||||
/**
|
||||
* @brief 周期性函数存储列表
|
||||
*/
|
||||
XNFunInfoMap _funList;
|
||||
/**
|
||||
* @brief 线程ID
|
||||
*/
|
||||
XNThreadIDSet _threadIDMap;
|
||||
};
|
||||
} // namespace XNSim
|
7
XNCore_Win/XNThreadObject/CMakeLists.txt
Normal file
7
XNCore_Win/XNThreadObject/CMakeLists.txt
Normal file
@ -0,0 +1,7 @@
|
||||
set(XNTHREADOBJECT_SOURCES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XNThreadObject.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XNThreadObject_p.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XNThreadObject.cpp
|
||||
)
|
||||
|
||||
set(XNCORE_SOURCES ${XNCORE_SOURCES} ${XNTHREADOBJECT_SOURCES} PARENT_SCOPE)
|
438
XNCore_Win/XNThreadObject/XNThreadObject.cpp
Normal file
438
XNCore_Win/XNThreadObject/XNThreadObject.cpp
Normal file
@ -0,0 +1,438 @@
|
||||
/**
|
||||
* @file XNThreadObject.cpp
|
||||
* @author jinchao
|
||||
* @brief 线程类源文件
|
||||
* @version 1.0
|
||||
* @date 2024-11-07
|
||||
*
|
||||
* @copyright Copyright (c) 2024 XN
|
||||
*
|
||||
*/
|
||||
#include "XNThreadObject.h"
|
||||
#include "XNDDSManager/XNDDSManager.h"
|
||||
#include "XNFramework/XNFramework.h"
|
||||
#include "XNIDL/XNSimStatusPubSubTypes.hpp"
|
||||
#include "XNLogger/XNLogger.h"
|
||||
#include "XNThreadManager/XNThreadManager.h"
|
||||
#include "XNThreadObject_p.h"
|
||||
|
||||
|
||||
namespace XNSim {
|
||||
XNThreadObject::XNThreadObject(XN_STRING name, XN_DOUBLE freq,
|
||||
XN_UINT32 priority, XN_UINT32 CPUAff)
|
||||
: XNObject(new XNThreadObjectPrivate()) {
|
||||
SetObjectName(name);
|
||||
T_D();
|
||||
d->_uPriority = priority;
|
||||
d->_uAffinity = CPUAff;
|
||||
d->_pinfo.period_ns = 1.0E9 / freq;
|
||||
d->_setFreq = freq;
|
||||
d->_funVec.resize(32);
|
||||
// InitialFunPool();
|
||||
}
|
||||
|
||||
// 默认析构函数
|
||||
XNThreadObject::~XNThreadObject(void) {}
|
||||
|
||||
XNFrameworkPtr XNThreadObject::GetFramework() {
|
||||
T_D();
|
||||
return d->_framework;
|
||||
}
|
||||
|
||||
void XNThreadObject::SetFramework(XNFrameworkPtr framework) {
|
||||
T_D();
|
||||
d->_framework = framework;
|
||||
}
|
||||
|
||||
// 初始化函数
|
||||
XN_BOOL XNThreadObject::Initialize() {
|
||||
T_D();
|
||||
XN_INT32 ret;
|
||||
#ifdef XN_WINDOWS
|
||||
d->_thread = std::thread(&XNThreadObject::ThreadFunction, this);
|
||||
HANDLE h_thread = d->_thread.native_handle();
|
||||
if (h_thread != nullptr) {
|
||||
bool bRet = SetThreadPriority(h_thread, THREAD_PRIORITY_TIME_CRITICAL);
|
||||
if (!bRet) {
|
||||
LOG_ERROR("0x2210 Thread: %1 Set Thread Priority Failed!",
|
||||
GetObjectName());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef XN_LINUX
|
||||
// 初始化线程参数
|
||||
ret = pthread_attr_init(&(d->_attr));
|
||||
if (ret) {
|
||||
LOG_ERROR("0x2210 Thread: %1 Initialize Attribute Failed!",
|
||||
GetObjectName());
|
||||
return false;
|
||||
}
|
||||
|
||||
// 设置线程栈空间大小
|
||||
ret = pthread_attr_setstacksize(&(d->_attr), PTHREAD_STACK_MIN * 20);
|
||||
if (ret) {
|
||||
LOG_ERROR("0x2211 Thread: %1 Set Stack Space Failed!", GetObjectName());
|
||||
return false;
|
||||
}
|
||||
|
||||
// 设置线程调度策略
|
||||
ret = pthread_attr_setschedpolicy(&(d->_attr), SCHED_FIFO);
|
||||
if (ret) {
|
||||
LOG_ERROR("0x2212 Thread: %1 Set Scheduling Policy Failed!",
|
||||
GetObjectName());
|
||||
return false;
|
||||
}
|
||||
|
||||
// 设置线程优先级
|
||||
d->_param.sched_priority = d->_uPriority;
|
||||
ret = pthread_attr_setschedparam(&(d->_attr), &d->_param);
|
||||
if (ret) {
|
||||
LOG_ERROR("0x2213 Thread: %1 Set Priority Failed!", GetObjectName());
|
||||
return false;
|
||||
}
|
||||
|
||||
// 设置调度器继承
|
||||
ret = pthread_attr_setinheritsched(&(d->_attr), PTHREAD_EXPLICIT_SCHED);
|
||||
if (ret) {
|
||||
LOG_ERROR("0x2214 Thread: %1 Set Scheduler Inheritance Failed!",
|
||||
GetObjectName());
|
||||
return false;
|
||||
}
|
||||
|
||||
// 线程创建
|
||||
ret = pthread_create(&d->_thread, &d->_attr, ThreadFunction, this);
|
||||
if (ret) {
|
||||
LOG_ERROR("0x2215 Thread: %1 Create Failed!", GetObjectName());
|
||||
return false;
|
||||
}
|
||||
|
||||
// 设置亲和性
|
||||
if (!OnSetCPUAffinity()) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
XNFrameworkPtr framework = GetFramework();
|
||||
if (!framework) {
|
||||
LOG_WARNING("0x2216 Thread: %1 get Framework Failed!", GetObjectName());
|
||||
return true;
|
||||
}
|
||||
|
||||
XNDDSManagerPtr ddsManager = framework->GetDDSManager();
|
||||
if (!ddsManager) {
|
||||
LOG_WARNING("0x2216 Thread: %1 get DDSManager Failed!", GetObjectName());
|
||||
return true;
|
||||
}
|
||||
|
||||
d->_writer =
|
||||
ddsManager
|
||||
->RegisterPublisher<XNSim::XNSimStatus::XNThreadStatusPubSubType>(
|
||||
"XNSim::XNSimStatus::XNThreadStatus", d->_threadID);
|
||||
if (d->_writer == nullptr) {
|
||||
LOG_WARNING("0x2217 Thread: %1 get DDS Writer Failed!", GetObjectName());
|
||||
return true;
|
||||
}
|
||||
LOG_INFO("Thread: %1 is prepared!", GetObjectName());
|
||||
return true;
|
||||
}
|
||||
|
||||
// 仿真控制
|
||||
void XNThreadObject::SimControl(XN_UINT32 objectId, SimControlCmd cmd) {
|
||||
T_D();
|
||||
if (objectId == 0) {
|
||||
switch (cmd) {
|
||||
case SimControlCmd::Start:
|
||||
Start();
|
||||
break;
|
||||
case SimControlCmd::Suspend:
|
||||
Pause();
|
||||
break;
|
||||
case SimControlCmd::Continue:
|
||||
Continue();
|
||||
break;
|
||||
case SimControlCmd::Abort:
|
||||
Stop(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 开始执行
|
||||
void XNThreadObject::Start() {
|
||||
T_D();
|
||||
XNThreadMutexLock(&d->_mtx);
|
||||
// 设置运行状态
|
||||
if (d->_eRunStatus == RunStatus::NotStart ||
|
||||
d->_eRunStatus == RunStatus::Suspend) {
|
||||
d->_eRunStatus = RunStatus::Runing;
|
||||
}
|
||||
XNThreadCVNotifyOne(&d->_cond);
|
||||
XNThreadMutexUnlock(&d->_mtx);
|
||||
LOG_INFO("Thread: %1 Start!", GetObjectName());
|
||||
}
|
||||
|
||||
// 暂停执行
|
||||
void XNThreadObject::Pause() {
|
||||
T_D();
|
||||
XNThreadMutexLock(&d->_mtx);
|
||||
// 设置运行状态
|
||||
if (d->_eRunStatus == RunStatus::Runing) {
|
||||
d->_eRunStatus = RunStatus::Suspend;
|
||||
}
|
||||
XNThreadMutexUnlock(&d->_mtx);
|
||||
LOG_INFO("Thread: %1 Pause!", GetObjectName());
|
||||
}
|
||||
|
||||
// 继续执行
|
||||
void XNThreadObject::Continue() {
|
||||
T_D();
|
||||
XNThreadMutexLock(&d->_mtx);
|
||||
// 设置运行状态
|
||||
if (d->_eRunStatus == RunStatus::Suspend) {
|
||||
d->_eRunStatus = RunStatus::Runing;
|
||||
}
|
||||
XNThreadCVNotifyOne(&d->_cond);
|
||||
XNThreadMutexUnlock(&d->_mtx);
|
||||
}
|
||||
|
||||
// 停止执行
|
||||
void XNThreadObject::Stop(bool force) {
|
||||
T_D();
|
||||
if (force) {
|
||||
XNThreadMutexLock(&d->_mtx);
|
||||
// 设置运行状态
|
||||
d->_eRunStatus = RunStatus::Aborted;
|
||||
XNThreadCVNotifyOne(&d->_cond);
|
||||
XNThreadMutexUnlock(&d->_mtx);
|
||||
Join();
|
||||
} else {
|
||||
XNThreadMutexLock(&d->_mtx);
|
||||
// 设置运行状态
|
||||
d->_eRunStatus = RunStatus::Finished;
|
||||
XNThreadCVNotifyOne(&d->_cond);
|
||||
XNThreadMutexUnlock(&d->_mtx);
|
||||
Join();
|
||||
}
|
||||
LOG_INFO("Thread: %1 Stop!", GetObjectName());
|
||||
}
|
||||
|
||||
// 加入线程
|
||||
void XNThreadObject::Join() {
|
||||
T_D();
|
||||
XNThreadJoin(d->_thread);
|
||||
}
|
||||
|
||||
// 分离线程
|
||||
void XNThreadObject::Detach() {
|
||||
T_D();
|
||||
XNThreadDetach(d->_thread);
|
||||
}
|
||||
|
||||
// 获取线程运行状态
|
||||
RunStatus XNThreadObject::GetRunStatus() {
|
||||
T_D();
|
||||
return d->_eRunStatus;
|
||||
}
|
||||
|
||||
// 向线程添加周期性函数
|
||||
void XNThreadObject::AddFunction(XNCallBack fun, FreqLevel freq, XN_UINT32 pos,
|
||||
XN_UINT32 priorty) {
|
||||
T_D();
|
||||
for (XN_INT32 i = 0; i < d->_funVec.size();) {
|
||||
if (i + pos >= d->_funVec.size())
|
||||
break;
|
||||
d->_funVec[i + pos][priorty].push_back(fun);
|
||||
switch (freq) {
|
||||
case FreqLevel::BaseFreq:
|
||||
i++;
|
||||
break;
|
||||
case FreqLevel::HalfFreq:
|
||||
i += 2;
|
||||
break;
|
||||
case FreqLevel::QuarterFreq:
|
||||
i += 4;
|
||||
break;
|
||||
case FreqLevel::EighthFreq:
|
||||
i += 8;
|
||||
break;
|
||||
case FreqLevel::SixteenthFreq:
|
||||
i += 16;
|
||||
break;
|
||||
case FreqLevel::ThirtyTwothFreq:
|
||||
i += 32;
|
||||
break;
|
||||
default:
|
||||
i += 32;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 获取线程运行频率
|
||||
const XN_DOUBLE &XNThreadObject::GetRunFrequecy() {
|
||||
T_D();
|
||||
return d->_setFreq;
|
||||
}
|
||||
|
||||
// 设置线程运行频率
|
||||
void XNThreadObject::SetRunFrequecy(const XN_DOUBLE &dRunFrequecy) {
|
||||
T_D();
|
||||
d->_setFreq = dRunFrequecy;
|
||||
d->_pinfo.period_ns = 1.0E9 / dRunFrequecy;
|
||||
}
|
||||
|
||||
// 获取线程运行优先级
|
||||
const XN_UINT32 &XNThreadObject::GetRunPriority() {
|
||||
T_D();
|
||||
return d->_uPriority;
|
||||
}
|
||||
|
||||
// 设置线程运行优先级
|
||||
void XNThreadObject::SetRunPriority(const XN_UINT32 &uRunPriority) {
|
||||
T_D();
|
||||
d->_uPriority = uRunPriority;
|
||||
}
|
||||
|
||||
// 获取线程CPU亲和性掩码
|
||||
const XN_UINT32 &XNThreadObject::GetCPUAffinity() {
|
||||
T_D();
|
||||
return d->_uAffinity;
|
||||
}
|
||||
|
||||
// 设置线程CPU亲和性掩码
|
||||
void XNThreadObject::SetCPUAffinity(const XN_UINT32 &uCPUAffinity) {
|
||||
T_D();
|
||||
d->_uAffinity = uCPUAffinity;
|
||||
}
|
||||
|
||||
// 设置线程运行间隔
|
||||
void XNThreadObject::SetStartTime(const XN_TIMESPEC &startTime) {
|
||||
T_D();
|
||||
#ifdef XN_WINDOWS
|
||||
d->_lastRunTime = startTime;
|
||||
#endif
|
||||
#ifdef XN_LINUX
|
||||
d->_pinfo.next_period = startTime;
|
||||
d->_lastRunTime = startTime;
|
||||
#endif
|
||||
}
|
||||
|
||||
// 执行线程CPU亲和性设置
|
||||
bool XNThreadObject::OnSetCPUAffinity() {
|
||||
T_D();
|
||||
#ifdef XN_LINUX
|
||||
cpu_set_t mask;
|
||||
CPU_ZERO(&mask);
|
||||
XN_INT32 cpuNum = sysconf(_SC_NPROCESSORS_CONF);
|
||||
for (XN_INT32 i = 0; i < cpuNum; i++) {
|
||||
if (((d->_uAffinity >> i) & 1) == 1)
|
||||
CPU_SET(i, &mask);
|
||||
}
|
||||
if (pthread_setaffinity_np(d->_thread, sizeof(mask), &mask) == -1) {
|
||||
LOG_WARNING("0x2216 线程: %1 设置CPU亲和性失败!", GetObjectName());
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
// 线程主执行函数
|
||||
#ifdef XN_WINDOWS
|
||||
void XNThreadObject::ThreadFunction() {
|
||||
T_D();
|
||||
XN_STRING name = GetObjectName();
|
||||
#endif
|
||||
#ifdef XN_LINUX
|
||||
void *XNThreadObject::ThreadFunction(void *args) {
|
||||
// 获取创建线程类的私有变量结构体指针
|
||||
ThisType *thisPtr = (ThisType *)args;
|
||||
auto d = thisPtr->GetPP();
|
||||
XN_STRING name = thisPtr->GetObjectName();
|
||||
#endif
|
||||
while (1) {
|
||||
// 加锁保护线程状态
|
||||
XNThreadMutexLock(&d->_mtx);
|
||||
// 当处于notstart或suspend时准备挂起
|
||||
while (d->_eRunStatus == RunStatus::NotStart ||
|
||||
d->_eRunStatus == RunStatus::Suspend) {
|
||||
// 如果挂起时切换为终止,则直接跳出
|
||||
if (d->_eRunStatus == RunStatus::Aborted ||
|
||||
d->_eRunStatus == RunStatus::Finished) {
|
||||
XNThreadMutexUnlock(&d->_mtx);
|
||||
break;
|
||||
}
|
||||
// 挂起线程
|
||||
XNThreadCVWait(&d->_cond, &d->_mtx);
|
||||
}
|
||||
// 如果为finished直接结束线程
|
||||
if (d->_eRunStatus == RunStatus::Finished) {
|
||||
XNThreadMutexUnlock(&d->_mtx);
|
||||
break;
|
||||
}
|
||||
// 解锁
|
||||
XNThreadMutexUnlock(&d->_mtx);
|
||||
|
||||
// 任务执行
|
||||
auto &funMap = d->_funVec[d->_RunPosition++];
|
||||
for (auto &funv : funMap) {
|
||||
for (auto &fun : funv.second) {
|
||||
fun();
|
||||
}
|
||||
}
|
||||
d->_RunPosition %= d->_funVec.size();
|
||||
|
||||
// 如果为abort等待任务执行完成再结束
|
||||
XNThreadMutexLock(&d->_mtx);
|
||||
if (d->_eRunStatus == RunStatus::Aborted) {
|
||||
XNThreadMutexUnlock(&d->_mtx);
|
||||
break;
|
||||
}
|
||||
XNThreadMutexUnlock(&d->_mtx);
|
||||
|
||||
// 填写DDS主题数据
|
||||
XN_UINT32 setFreq =
|
||||
(1.0E9 / d->_pinfo.period_ns) < 1.0 ? 1 : (XN_UINT32)d->_setFreq;
|
||||
if (d->_writer != nullptr && d->_count > 0 && d->_count % setFreq == 0) {
|
||||
XN_TIMESPEC now;
|
||||
getCurrentRTTime(&now);
|
||||
double seconds = calculateRTTime(&now, &d->_lastRunTime);
|
||||
XNSim::XNSimStatus::XNThreadStatus threadStatus;
|
||||
threadStatus.XNThreadName(name);
|
||||
threadStatus.XNThreadID(XNThreadGetID());
|
||||
threadStatus.XNThreadSt((uint32_t)d->_eRunStatus);
|
||||
threadStatus.XNThreadAff(d->_uAffinity);
|
||||
threadStatus.XNThreadPro(d->_uPriority);
|
||||
threadStatus.XNThRunCnt(d->_count);
|
||||
threadStatus.XNThSetFreq(d->_setFreq);
|
||||
threadStatus.XNThCurFreq(d->_setFreq / seconds);
|
||||
d->_writer->write(&threadStatus);
|
||||
d->_lastRunTime = now;
|
||||
LOG_DEBUG("Thread: %1 Write DDS! SetFreq: %2 Hz, CurFreq: %3 Hz", name,
|
||||
d->_setFreq, d->_setFreq / seconds);
|
||||
}
|
||||
d->_count++;
|
||||
|
||||
sleepToNextRTTime(&d->_pinfo);
|
||||
}
|
||||
#ifdef XN_WINDOWS
|
||||
}
|
||||
#endif
|
||||
#ifdef XN_LINUX
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
// 获取线程ID
|
||||
const XN_UINT32 &XNThreadObject::GetThreadID() {
|
||||
T_D();
|
||||
return d->_threadID;
|
||||
}
|
||||
|
||||
// 设置线程ID
|
||||
void XNThreadObject::SetThreadID(const XN_UINT32 &threadID) {
|
||||
T_D();
|
||||
d->_threadID = threadID;
|
||||
}
|
||||
} // namespace XNSim
|
207
XNCore_Win/XNThreadObject/XNThreadObject.h
Normal file
207
XNCore_Win/XNThreadObject/XNThreadObject.h
Normal file
@ -0,0 +1,207 @@
|
||||
/**
|
||||
* @file XNThreadObject.h
|
||||
* @author jinchao
|
||||
* @brief 调度线程类头文件
|
||||
* @version 1.0
|
||||
* @date 2024-11-07
|
||||
*
|
||||
* @copyright Copyright (c) 2024 XN
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
#include "XNObject/XNObject.h"
|
||||
|
||||
namespace XNSim {
|
||||
struct XNThreadObjectPrivate;
|
||||
|
||||
/**
|
||||
* @brief 调度线程类
|
||||
* @details 调度所有模型提交的周期性执行函数
|
||||
*/
|
||||
class XNCORE_EXPORT XNThreadObject : public XNObject {
|
||||
XN_METATYPE(XNThreadObject, XNObject)
|
||||
XN_DECLARE_PRIVATE(XNThreadObject)
|
||||
|
||||
public:
|
||||
XNThreadObject() = delete;
|
||||
|
||||
/**
|
||||
* @brief 默认析构函数
|
||||
*/
|
||||
virtual ~XNThreadObject();
|
||||
|
||||
explicit XNThreadObject(XN_STRING name = "", XN_DOUBLE freq = BASE_RUN_FREQ,
|
||||
XN_UINT32 priority = 99, XN_UINT32 CPUAff = 0);
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief 获取框架对象
|
||||
* @return 框架对象
|
||||
*/
|
||||
XNFrameworkPtr GetFramework();
|
||||
|
||||
/**
|
||||
* @brief 设置框架对象
|
||||
* @param framework 框架对象
|
||||
*/
|
||||
void SetFramework(XNFrameworkPtr framework);
|
||||
|
||||
/**
|
||||
* @brief 线程初始化
|
||||
* @return true: 初始化成功
|
||||
* @return false: 初始化失败
|
||||
*/
|
||||
XN_BOOL Initialize();
|
||||
|
||||
/**
|
||||
* @brief 仿真控制
|
||||
* @param objectId: 对象ID
|
||||
* @param cmd: 仿真控制命令
|
||||
*/
|
||||
void SimControl(XN_UINT32 objectId, SimControlCmd cmd);
|
||||
|
||||
/**
|
||||
* @brief 设置线程运行的开始时间
|
||||
* @param simTime: timespec结构体类型,用于线程纳秒睡眠计算的开始时间
|
||||
* @details 通过设置统一的开始时间,使个线程能同步执行
|
||||
*/
|
||||
void SetStartTime(const XN_TIMESPEC &simTime);
|
||||
|
||||
/**
|
||||
* @brief 加入线程
|
||||
* @details 等待线程结束
|
||||
*/
|
||||
void Join();
|
||||
|
||||
/**
|
||||
* @brief 线程脱离
|
||||
*/
|
||||
void Detach();
|
||||
|
||||
/**
|
||||
* @brief 获取线程ID
|
||||
* @return const quint32&: 线程ID
|
||||
*/
|
||||
const XN_UINT32 &GetThreadID();
|
||||
|
||||
/**
|
||||
* @brief 设置线程ID
|
||||
* @param threadID: 线程ID
|
||||
*/
|
||||
void SetThreadID(const XN_UINT32 &threadID);
|
||||
|
||||
/**
|
||||
* @brief 获取运行状态
|
||||
* @return RunStatus: 运行状态枚举
|
||||
*/
|
||||
RunStatus GetRunStatus();
|
||||
|
||||
/**
|
||||
* @brief 获取线程运行频率
|
||||
* @return const double&:线程运行频率
|
||||
*/
|
||||
const XN_DOUBLE &GetRunFrequecy();
|
||||
|
||||
/**
|
||||
* @brief 设置线程运行频率
|
||||
* @param eRunFrequecy: double类型,线程运行频率
|
||||
*/
|
||||
void SetRunFrequecy(const XN_DOUBLE &dRunFrequecy);
|
||||
|
||||
/**
|
||||
* @brief 获取线程运行优先级
|
||||
* @return const UINT32&:运行优先级,0~99,99最高
|
||||
*/
|
||||
const XN_UINT32 &GetRunPriority();
|
||||
|
||||
/**
|
||||
* @brief 设置线程运行优先级
|
||||
* @param uRunPriority: UINT32类型,运行优先级,0~99,99最高
|
||||
*/
|
||||
void SetRunPriority(const XN_UINT32 &uRunPriority);
|
||||
|
||||
/**
|
||||
* @brief 设置线程CPU亲和性掩码
|
||||
* @return const UINT32&:
|
||||
* CPU亲和性掩码,按位表示某CPU核是否使用,从低到高,0表示不使用,1表示使用。
|
||||
* 例如:0x00000003表示使用0,1号CPU
|
||||
*/
|
||||
const XN_UINT32 &GetCPUAffinity();
|
||||
|
||||
/**
|
||||
* @brief 获取线程CPU亲和性掩码
|
||||
* @param uCPUAffinity:
|
||||
* UINT32类型,CPU亲和性掩码,按位表示某CPU核是否使用,从低到高,0表示不使用,1表示使用。
|
||||
* 例如:0x00000003表示使用0,1号CPU
|
||||
*/
|
||||
void SetCPUAffinity(const XN_UINT32 &uCPUAffinity);
|
||||
|
||||
/**
|
||||
* @brief 向线程添加周期性函数
|
||||
* @param fun:XNCallBack函数包装器类型,需要提交的函数的包装
|
||||
* @param freq:FreqLevel类型,提交的函数运行频率组
|
||||
* @param pos:UINT32类型,提交的函数运行节点号
|
||||
* @param
|
||||
* priorty:UINT32类型,提交的函数运行优先级,99~0,优先级数值越大,优先级越高
|
||||
* @details 根据运行频率组和节点号向调度线程任务表中添加周期性函数
|
||||
*/
|
||||
void AddFunction(XNCallBack fun, FreqLevel freq, XN_UINT32 pos,
|
||||
XN_UINT32 priorty);
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief 控制线程开始
|
||||
* @return true: 线程启动成功
|
||||
* @return false: 线程启动失败
|
||||
*/
|
||||
void Start();
|
||||
|
||||
/**
|
||||
* @brief 控制线程暂停
|
||||
* @return true: 线程暂停成功
|
||||
* @return false: 线程暂停失败
|
||||
*/
|
||||
void Pause();
|
||||
|
||||
/**
|
||||
* @brief 控制线程继续
|
||||
* @return true: 线程继续成功
|
||||
* @return false: 线程继续失败
|
||||
*/
|
||||
void Continue();
|
||||
|
||||
/**
|
||||
* @brief 控制线程停止
|
||||
* @param force:bool类型,true = 强制停止,flase = 等待当前认为结束后停止
|
||||
* @return true: 线程停止成功
|
||||
* @return false: 线程停止失败
|
||||
*/
|
||||
void Stop(XN_BOOL force = false);
|
||||
|
||||
/**
|
||||
* @brief 执行线程CPU亲和性设置
|
||||
* @return true: 设置线程CPU亲和性成功
|
||||
* @return false: 设置线程CPU亲和性失败
|
||||
*/
|
||||
XN_BOOL OnSetCPUAffinity();
|
||||
|
||||
#ifdef XN_WINDOWS
|
||||
/**
|
||||
* @brief 线程主执行函数
|
||||
* @param args: 线程执行函数输入参数指针
|
||||
* @return void*: 线程执行函数返回值指针
|
||||
*/
|
||||
void ThreadFunction();
|
||||
#endif
|
||||
#ifdef XN_LINUX
|
||||
/**
|
||||
* @brief 线程主执行函数
|
||||
* @param args: 线程执行函数输入参数指针
|
||||
* @return void*: 线程执行函数返回值指针
|
||||
*/
|
||||
static void *ThreadFunction(void *args);
|
||||
#endif
|
||||
};
|
||||
|
||||
XNCLASS_PTR_DECLARE(XNThreadObject)
|
||||
} // namespace XNSim
|
102
XNCore_Win/XNThreadObject/XNThreadObject_p.h
Normal file
102
XNCore_Win/XNThreadObject/XNThreadObject_p.h
Normal file
@ -0,0 +1,102 @@
|
||||
#pragma once
|
||||
#include "XNObject/XNObject_p.h"
|
||||
|
||||
namespace XNSim {
|
||||
/**
|
||||
* @brief 线程类私有结构体
|
||||
*/
|
||||
struct XNThreadObjectPrivate : public XNObjectPrivate {
|
||||
/**
|
||||
* @brief 框架对象
|
||||
*/
|
||||
XNFrameworkPtr _framework;
|
||||
/**
|
||||
* @brief 线程运行优先级
|
||||
*/
|
||||
XN_UINT32 _uPriority = 0;
|
||||
/**
|
||||
* @brief 线程CPU亲和性掩码
|
||||
* @details
|
||||
* 按位表示某CPU核是否使用,从低到高,0表示不使用,1表示使用。例如:0x00000003表示使用0,1号CPU
|
||||
*/
|
||||
XN_UINT32 _uAffinity = 0;
|
||||
/**
|
||||
* @brief 线程运行频率
|
||||
*/
|
||||
XN_DOUBLE _setFreq = BASE_RUN_FREQ;
|
||||
/**
|
||||
* @brief 线程调度任务表
|
||||
*/
|
||||
std::vector<std::map<XN_UINT32, std::vector<XNCallBack>>> _funVec;
|
||||
|
||||
#ifdef XN_WINDOWS
|
||||
/**
|
||||
* @brief 线程
|
||||
*/
|
||||
XN_THREAD _thread;
|
||||
/**
|
||||
* @brief 线程控制锁
|
||||
*/
|
||||
XN_MUTEX _mutex;
|
||||
/**
|
||||
* @brief 线程控制锁
|
||||
*/
|
||||
XN_THREAD_MUTEX _mtx = std::unique_lock<XN_MUTEX>(_mutex);
|
||||
/**
|
||||
* @brief 线程控制条件变量
|
||||
*/
|
||||
XN_THREAD_CV _cond;
|
||||
#endif
|
||||
|
||||
#ifdef XN_LINUX
|
||||
/**
|
||||
* @brief pthread线程调度参数
|
||||
*/
|
||||
XN_THREAD_SCHED_PARAM _param;
|
||||
/**
|
||||
* @brief pthread线程属性
|
||||
*/
|
||||
XN_THREAD_ATTR _attr;
|
||||
/**
|
||||
* @brief pthread线程
|
||||
*/
|
||||
XN_THREAD _thread;
|
||||
/**
|
||||
* @brief 线程控制锁
|
||||
*/
|
||||
XN_THREAD_MUTEX _mtx = PTHREAD_MUTEX_INITIALIZER;
|
||||
/**
|
||||
* @brief 线程控制条件变量
|
||||
*/
|
||||
XN_THREAD_CV _cond = PTHREAD_COND_INITIALIZER;
|
||||
#endif
|
||||
/**
|
||||
* @brief 线程睡眠时间控制
|
||||
*/
|
||||
PERIOD_INFO _pinfo;
|
||||
/**
|
||||
* @brief 线程运行状态
|
||||
*/
|
||||
RunStatus _eRunStatus = RunStatus::NotStart;
|
||||
/**
|
||||
* @brief 线程执行进度
|
||||
*/
|
||||
XN_UINT32 _RunPosition = 0;
|
||||
/**
|
||||
* @brief 线程执行计数
|
||||
*/
|
||||
XN_INT32 _count = 0;
|
||||
/**
|
||||
* @brief 线程执行时间统计
|
||||
*/
|
||||
XN_TIMESPEC _lastRunTime;
|
||||
/**
|
||||
* @brief 线程运行状态主题写入器
|
||||
*/
|
||||
XN_DDS::DataWriter *_writer;
|
||||
/**
|
||||
* @brief 线程ID
|
||||
*/
|
||||
XN_UINT32 _threadID = 0;
|
||||
};
|
||||
} // namespace XNSim
|
7
XNCore_Win/XNTimeManager/CMakeLists.txt
Normal file
7
XNCore_Win/XNTimeManager/CMakeLists.txt
Normal file
@ -0,0 +1,7 @@
|
||||
set(XNTIMEMANAGER_SOURCES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XNTimeManager.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XNTimeManager_p.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XNTimeManager.cpp
|
||||
)
|
||||
|
||||
set(XNCORE_SOURCES ${XNCORE_SOURCES} ${XNTIMEMANAGER_SOURCES} PARENT_SCOPE)
|
162
XNCore_Win/XNTimeManager/XNTimeManager.cpp
Normal file
162
XNCore_Win/XNTimeManager/XNTimeManager.cpp
Normal file
@ -0,0 +1,162 @@
|
||||
/**
|
||||
* @file XNTimeManager.cpp
|
||||
* @author jinchao
|
||||
* @brief 时间管理器类源文件
|
||||
* @version 1.0
|
||||
* @date 2024-11-07
|
||||
*
|
||||
* @copyright Copyright (c) 2024 XN
|
||||
*
|
||||
*/
|
||||
#include "XNTimeManager.h"
|
||||
#include "XNDDSManager/XNDDSManager.h"
|
||||
#include "XNFramework/XNFramework.h"
|
||||
#include "XNIDL/XNSimStatusPubSubTypes.hpp"
|
||||
#include "XNThreadManager/XNThreadManager.h"
|
||||
#include "XNTimeManager_p.h"
|
||||
|
||||
|
||||
namespace XNSim {
|
||||
XNTimeManager::XNTimeManager() : XNBaseFrameObject(new XNTimeManagerPrivate()) {
|
||||
SetUniqueId(enumValue(XNCoreObjectID::TimeManager));
|
||||
SetObjectName("XNTimeManager");
|
||||
}
|
||||
|
||||
XNTimeManager::~XNTimeManager() {}
|
||||
|
||||
XNTimeManager::XNTimeManager(PrivateType *p) : XNBaseFrameObject(p) {}
|
||||
|
||||
std::chrono::system_clock::time_point XNTimeManager::GetSimTime() {
|
||||
T_D();
|
||||
XNThreadMutexLock(&(d->_mtx));
|
||||
auto simTime = d->_SimTime;
|
||||
XNThreadMutexUnlock(&(d->_mtx));
|
||||
return simTime;
|
||||
}
|
||||
|
||||
void XNTimeManager::SetStartTime(const XN_TIMESPEC &simTime) {
|
||||
T_D();
|
||||
// 将timespec转换为chrono::system_clock::time_point
|
||||
#ifdef XN_WINDOWS
|
||||
auto duration =
|
||||
std::chrono::duration_cast<std::chrono::system_clock::duration>(
|
||||
std::chrono::seconds(simTime.QuadPart) +
|
||||
std::chrono::nanoseconds(simTime.QuadPart % 1000000000));
|
||||
d->_SimStartTime = std::chrono::system_clock::time_point(duration);
|
||||
#endif
|
||||
#ifdef XN_LINUX
|
||||
auto duration = std::chrono::seconds(simTime.tv_sec) +
|
||||
std::chrono::nanoseconds(simTime.tv_nsec);
|
||||
d->_SimStartTime = std::chrono::system_clock::time_point(duration);
|
||||
#endif
|
||||
}
|
||||
|
||||
void XNTimeManager::Start() {
|
||||
T_D();
|
||||
if (d->_eRunStatus == RunStatus::NotStart) {
|
||||
LOG_INFO("XNSim Start!");
|
||||
d->_eRunStatus = RunStatus::Runing;
|
||||
} else {
|
||||
LOG_WARNING("XNSim Already Start!");
|
||||
}
|
||||
}
|
||||
|
||||
void XNTimeManager::Abort() {
|
||||
T_D();
|
||||
if (d->_eRunStatus != RunStatus::Aborted) {
|
||||
LOG_INFO("XNSim Abort!");
|
||||
d->_eRunStatus = RunStatus::Aborted;
|
||||
} else {
|
||||
LOG_WARNING("XNSim Already Abort!");
|
||||
}
|
||||
}
|
||||
|
||||
void XNTimeManager::Pause() {
|
||||
T_D();
|
||||
if (d->_eRunStatus == RunStatus::Runing) {
|
||||
LOG_INFO("XNSim Pause!");
|
||||
d->_eRunStatus = RunStatus::Suspend;
|
||||
} else {
|
||||
LOG_WARNING("XNSim is not in Runing status!");
|
||||
}
|
||||
}
|
||||
|
||||
void XNTimeManager::Continue() {
|
||||
T_D();
|
||||
if (d->_eRunStatus == RunStatus::Suspend) {
|
||||
LOG_INFO("XNSim Continue!");
|
||||
d->_eRunStatus = RunStatus::Runing;
|
||||
} else {
|
||||
LOG_WARNING("XNSim is not in Pause status!");
|
||||
}
|
||||
}
|
||||
|
||||
RunStatus XNTimeManager::GetStatus() {
|
||||
T_D();
|
||||
return d->_eRunStatus;
|
||||
}
|
||||
|
||||
void XNTimeManager::SimControl(XN_UINT32 objectId, SimControlCmd cmd) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool XNTimeManager::Initialize() {
|
||||
T_D();
|
||||
// 时间管理器线程初始化
|
||||
// XNThreadManager *threadManager = parent()->findChild<XNThreadManager
|
||||
// *>("XNThreadManager"); if (threadManager) { double dRunInter =
|
||||
// threadManager->GetBaseInter() * 32; d->_TimeManagerThread =
|
||||
// new XNThread(this, "TimeManagerThread", FreqLevel::ThirtyTwothFreq, 10, 0,
|
||||
// dRunInter); } else { d->_status = XNFrameObjectStatus::Unknown;
|
||||
// LOG_ERROR("XNTimeManager Initialize Failed!");
|
||||
// return;
|
||||
// }
|
||||
|
||||
// d->_TimeManagerThread->AddFunction(std::bind(&XNTimeManager::StepExecute,
|
||||
// this),
|
||||
// FreqLevel::ThirtyTwothFreq, 0, 90);
|
||||
|
||||
// connect(this, &XNTimeManager::SimControl, d->_TimeManagerThread,
|
||||
// &XNThread::OnSimControl); 运行状态初始化
|
||||
d->_eRunStatus =
|
||||
RunStatus::NotStart; // d->_TimeManagerThread->GetRunStatus();
|
||||
// 仿真时间初始化
|
||||
d->_SimTime = d->_SimStartTime;
|
||||
|
||||
LOG_INFO("XNTimeManager Initialize Success!");
|
||||
d->_status = XNFrameObjectStatus::Initialized;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool XNTimeManager::PrepareForExecute() {
|
||||
T_D();
|
||||
d->_status = XNFrameObjectStatus::Ready;
|
||||
LOG_INFO("XNTimeManager is prepared!");
|
||||
return true;
|
||||
}
|
||||
|
||||
void XNTimeManager::StepExecute() {
|
||||
T_D();
|
||||
// TODO 提交事件
|
||||
// 时间推进
|
||||
XNThreadMutexLock(&(d->_mtx));
|
||||
d->_SimTime +=
|
||||
std::chrono::microseconds(static_cast<int64_t>(BASE_RUN_INTER * 1.0E6));
|
||||
XNThreadMutexUnlock(&(d->_mtx));
|
||||
}
|
||||
} // namespace XNSim
|
115
XNCore_Win/XNTimeManager/XNTimeManager.h
Normal file
115
XNCore_Win/XNTimeManager/XNTimeManager.h
Normal file
@ -0,0 +1,115 @@
|
||||
/**
|
||||
* @file XNTimeManager.h
|
||||
* @author jinchao
|
||||
* @brief 时间管理器类头文件
|
||||
* @version 1.0
|
||||
* @date 2024-11-10
|
||||
*
|
||||
* @copyright Copyright (c) 2024 XN
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
#include "XNBaseFrameObject/XNBaseFrameObject.h"
|
||||
|
||||
namespace XNSim {
|
||||
struct XNTimeManagerPrivate;
|
||||
|
||||
/**
|
||||
* @brief 时间管理器类
|
||||
* @details
|
||||
* 管理仿真系统运行时的时间,在仿真系统运行时同步步进时间信息,并产生系统运行事件
|
||||
*/
|
||||
class XNCORE_EXPORT XNTimeManager : public XNBaseFrameObject {
|
||||
XN_METATYPE(XNTimeManager, XNBaseFrameObject)
|
||||
XN_DECLARE_PRIVATE(XNTimeManager)
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief 构造函数
|
||||
*/
|
||||
XNTimeManager();
|
||||
|
||||
/**
|
||||
* @brief 析构函数
|
||||
*/
|
||||
virtual ~XNTimeManager();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief 构造函数
|
||||
* @param p: 私有数据成员
|
||||
*/
|
||||
XNTimeManager(PrivateType *p);
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief 获取当前仿真时间
|
||||
* @return XNTimePoint: 当前仿真时间
|
||||
*/
|
||||
XNTimePoint GetSimTime();
|
||||
|
||||
/**
|
||||
* @brief 设置仿真开始时间
|
||||
* @param simTime: XN_TIMESPEC类型,仿真开始时间
|
||||
*/
|
||||
void SetStartTime(const XN_TIMESPEC &simTime);
|
||||
|
||||
/**
|
||||
* @brief 开始控制
|
||||
* @details 控制时间管理器线程开始运行接口
|
||||
*/
|
||||
void Start();
|
||||
|
||||
/**
|
||||
* @brief 停止控制
|
||||
* @details 控制时间管理器线程停止运行接口
|
||||
*/
|
||||
void Abort();
|
||||
|
||||
/**
|
||||
* @brief 暂停控制
|
||||
* @details 控制时间管理器线程暂停运行接口
|
||||
*/
|
||||
void Pause();
|
||||
|
||||
/**
|
||||
* @brief 继续控制
|
||||
* @details 控制时间管理器线程继续运行接口
|
||||
*/
|
||||
void Continue();
|
||||
|
||||
/**
|
||||
* @brief 初始化时间管理器
|
||||
* @return true: 初始化成功
|
||||
* @return false: 初始化失败
|
||||
* @details 时间管理器的初始化接口函数
|
||||
*/
|
||||
virtual XN_BOOL Initialize() override;
|
||||
|
||||
/**
|
||||
* @brief 仿真运行前最后处理
|
||||
* @note 时间管理器在开始执行前的准备工作
|
||||
*/
|
||||
virtual XN_BOOL PrepareForExecute() override;
|
||||
|
||||
/**
|
||||
* @brief 仿真控制
|
||||
* @param objectId: 对象ID
|
||||
* @param cmd: 仿真控制命令
|
||||
*/
|
||||
void SimControl(XN_UINT32 objectId, SimControlCmd cmd);
|
||||
|
||||
/**
|
||||
* @brief 获取运行状态
|
||||
* @return RunStatus: 枚举类,时间管理器线程运行状态
|
||||
* @details 获取时间管理器线程运行状态接口
|
||||
*/
|
||||
RunStatus GetStatus();
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief 时间管理器线程单步执行函数
|
||||
*/
|
||||
void StepExecute();
|
||||
};
|
||||
} // namespace XNSim
|
41
XNCore_Win/XNTimeManager/XNTimeManager_p.h
Normal file
41
XNCore_Win/XNTimeManager/XNTimeManager_p.h
Normal file
@ -0,0 +1,41 @@
|
||||
/**
|
||||
* @file XNTimeManager_p.h
|
||||
* @author jinchao
|
||||
* @brief 时间管理器类私有头文件
|
||||
* @version 1.0
|
||||
* @date 2024-11-07
|
||||
*
|
||||
* @copyright Copyright (c) 2024 XN
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
#include "XNBaseFrameObject/XNBaseFrameObject_p.h"
|
||||
#include "XNThreadObject/XNThreadObject.h"
|
||||
|
||||
namespace XNSim {
|
||||
/**
|
||||
* @brief 时间管理器类私有结构体
|
||||
*/
|
||||
struct XNTimeManagerPrivate : public XNBaseFrameObjectPrivate {
|
||||
/*
|
||||
* @brief 仿真运行状态
|
||||
*/
|
||||
RunStatus _eRunStatus;
|
||||
/**
|
||||
* @brief 仿真开始时间
|
||||
*/
|
||||
XNTimePoint _SimStartTime;
|
||||
/**
|
||||
* @brief 当前仿真时间
|
||||
*/
|
||||
XNTimePoint _SimTime;
|
||||
/**
|
||||
* @brief 时间管理器线程智能指针
|
||||
*/
|
||||
XNThreadObjectPtr _TimeManagerThread;
|
||||
/**
|
||||
* @brief 时间管理器线程控制锁
|
||||
*/
|
||||
XN_THREAD_MUTEX _mtx;
|
||||
};
|
||||
} // namespace XNSim
|
Loading…
x
Reference in New Issue
Block a user