XNCore重构完成,暂未测试
This commit is contained in:
parent
fc315a882c
commit
f2970327fa
@ -12,34 +12,29 @@
|
||||
|
||||
#include "XNObject.h"
|
||||
|
||||
class XNBaseFrameObjectPrivate;
|
||||
struct XNBaseFrameObjectPrivate;
|
||||
|
||||
/**
|
||||
* @brief 框架对象基类
|
||||
*/
|
||||
class XNCORE_EXPORT XNBaseFrameObject : public XNObject
|
||||
{
|
||||
/**
|
||||
* @brief 宏定义,用于支持Qt的元对象系统
|
||||
*/
|
||||
Q_OBJECT
|
||||
|
||||
/**
|
||||
* @brief 宏定义,用于禁用拷贝构造函数
|
||||
*/
|
||||
Q_DISABLE_COPY(XNBaseFrameObject)
|
||||
XN_METATYPE(XNBaseFrameObject, XNObject)
|
||||
|
||||
/**
|
||||
* @brief 宏定义,用于声明私有数据成员
|
||||
*/
|
||||
Q_DECLARE_PRIVATE(XNBaseFrameObject);
|
||||
XN_DECLARE_PRIVATE(XNBaseFrameObject)
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief 构造函数
|
||||
* @param parent 父对象
|
||||
*/
|
||||
XNBaseFrameObject(QObject *parent = nullptr);
|
||||
XNBaseFrameObject();
|
||||
|
||||
/**
|
||||
* @brief 析构函数
|
||||
@ -52,44 +47,34 @@ protected:
|
||||
* @param dd 私有数据成员
|
||||
* @param parent 父对象
|
||||
*/
|
||||
XNBaseFrameObject(XNBaseFrameObjectPrivate &dd, QObject *parent = nullptr);
|
||||
|
||||
signals:
|
||||
/**
|
||||
* @brief 初始化
|
||||
*/
|
||||
void Initialize();
|
||||
|
||||
/**
|
||||
* @brief 初始化失败
|
||||
*/
|
||||
void InitializeFailed();
|
||||
|
||||
/**
|
||||
* @brief 准备执行
|
||||
*/
|
||||
void PrepareForExecute();
|
||||
|
||||
/**
|
||||
* @brief 准备执行失败
|
||||
*/
|
||||
void PrepareForExecuteFailed();
|
||||
|
||||
public slots:
|
||||
/**
|
||||
* @brief 初始化
|
||||
*/
|
||||
virtual void OnInitialize() = 0;
|
||||
|
||||
/**
|
||||
* @brief 准备执行
|
||||
*/
|
||||
virtual void OnPrepareForExecute() = 0;
|
||||
XNBaseFrameObject(PrivateType *p);
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief 初始化
|
||||
*/
|
||||
virtual bool Initialize() = 0;
|
||||
|
||||
/**
|
||||
* @brief 准备执行
|
||||
*/
|
||||
virtual bool PrepareForExecute() = 0;
|
||||
|
||||
/**
|
||||
* @brief 获取框架对象状态
|
||||
* @return 框架对象状态
|
||||
*/
|
||||
XNFrameObjectStatus GetFrameObjectStatus();
|
||||
|
||||
/**
|
||||
* @brief 获取框架对象
|
||||
* @return 框架对象
|
||||
*/
|
||||
XNFrameworkPtr GetFramework();
|
||||
|
||||
/**
|
||||
* @brief 设置框架对象
|
||||
* @param framework 框架对象
|
||||
*/
|
||||
void SetFramework(XNFrameworkPtr framework);
|
||||
};
|
||||
|
@ -16,22 +16,13 @@
|
||||
/**
|
||||
* @brief 框架对象基类的私有数据成员
|
||||
*/
|
||||
class XNBaseFrameObjectPrivate : public XNObjectPrivate
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief 构造函数
|
||||
* @param q 框架对象基类指针
|
||||
*/
|
||||
explicit XNBaseFrameObjectPrivate(XNBaseFrameObject *q) : XNObjectPrivate(q) {}
|
||||
|
||||
/**
|
||||
* @brief 宏定义,用于声明公有数据成员
|
||||
*/
|
||||
Q_DECLARE_PUBLIC(XNBaseFrameObject)
|
||||
|
||||
struct XNBaseFrameObjectPrivate : public XNObjectPrivate {
|
||||
/**
|
||||
* @brief 框架对象状态
|
||||
*/
|
||||
XNFrameObjectStatus _status = XNFrameObjectStatus::NotReady;
|
||||
/**
|
||||
* @brief 框架对象
|
||||
*/
|
||||
XNFrameworkPtr _framework;
|
||||
};
|
||||
|
@ -1,14 +1,13 @@
|
||||
#ifndef XNCORE_GLOBAL_H
|
||||
#define XNCORE_GLOBAL_H
|
||||
|
||||
#include <QtCore/qglobal.h>
|
||||
#pragma once
|
||||
|
||||
#if defined(XNCORE_LIBRARY)
|
||||
# define XNCORE_EXPORT Q_DECL_EXPORT
|
||||
# define XNCORE_EXPORT __attribute__((visibility("default")))
|
||||
#else
|
||||
# define XNCORE_EXPORT Q_DECL_IMPORT
|
||||
# define XNCORE_EXPORT __attribute__((visibility("default")))
|
||||
#endif
|
||||
|
||||
#define FORCEINLINE __attribute__((always_inline))
|
||||
|
||||
#ifdef __linux__
|
||||
# include <pthread.h>
|
||||
# include <sched.h>
|
||||
@ -20,8 +19,34 @@
|
||||
# include <memory>
|
||||
# include <errno.h>
|
||||
# include <unistd.h>
|
||||
# include <limits.h>
|
||||
# include <functional>
|
||||
# include <map>
|
||||
# include <unordered_map>
|
||||
# include <vector>
|
||||
# include <set>
|
||||
# include <any>
|
||||
# include <string>
|
||||
# include <thread>
|
||||
# include <mutex>
|
||||
# include <condition_variable>
|
||||
# include <queue>
|
||||
# include <tinyxml2.h>
|
||||
# include <chrono>
|
||||
# include <iomanip>
|
||||
# include <sstream>
|
||||
# include <dlfcn.h>
|
||||
# include <filesystem>
|
||||
#endif
|
||||
|
||||
#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/Subscriber.hpp>
|
||||
#include <fastdds/dds/topic/TypeSupport.hpp>
|
||||
#include <fastdds/dds/subscriber/DataReaderListener.hpp>
|
||||
#define FAST_DDS_MACRO eprosima::fastdds::dds
|
||||
|
||||
/**
|
||||
@ -40,6 +65,9 @@ using XNCallBack = std::function<void()>;
|
||||
//DDS回调函数类型别名
|
||||
using XNDDSCallBack = std::function<void(void *)>;
|
||||
|
||||
//事件回调函数类型别名
|
||||
using XNEventCallback = std::function<void(const std::any &)>;
|
||||
|
||||
/**
|
||||
* @brief 纳秒睡眠相关时间结构体
|
||||
* @details 用于线程睡眠时间控制
|
||||
@ -54,6 +82,17 @@ struct PERIOD_INFO {
|
||||
*/
|
||||
long period_ns;
|
||||
};
|
||||
/**
|
||||
* @brief 系统时间点类型别名
|
||||
*/
|
||||
using XNTimePoint = std::chrono::system_clock::time_point;
|
||||
|
||||
/**
|
||||
* @brief 将ISO格式的时间字符串转换为系统时间点
|
||||
* @param timeStr ISO格式的时间字符串 (YYYY-MM-DDTHH:mm:ss)
|
||||
* @return 系统时间点
|
||||
*/
|
||||
XNTimePoint parseISOTime(const std::string &timeStr);
|
||||
|
||||
/**
|
||||
* @brief 系统运行状态枚举类
|
||||
@ -155,10 +194,63 @@ enum class XNFrameObjectStatus {
|
||||
Unknown
|
||||
};
|
||||
|
||||
#define XN_DLL_INITIALIZE(ClassName) \
|
||||
extern "C" void Initial##ClassName() \
|
||||
{ \
|
||||
qRegisterMetaType<ClassName>(#ClassName); \
|
||||
template <class ToType, class FromType>
|
||||
FORCEINLINE ToType XNStaticCastHelper(const FromType &from)
|
||||
{
|
||||
return std::static_pointer_cast<typename ToType::element_type>(from);
|
||||
}
|
||||
|
||||
#endif // XNCORE_GLOBAL_H
|
||||
template <class ToType, class FromType>
|
||||
FORCEINLINE ToType XNCastHelper(const FromType &from)
|
||||
{
|
||||
return std::dynamic_pointer_cast<typename ToType::element_type>(from);
|
||||
}
|
||||
|
||||
#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>;
|
||||
|
||||
#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()
|
||||
|
||||
struct XNNullClass {
|
||||
};
|
||||
|
||||
#define XN_METATYPE_P(cls) \
|
||||
public: \
|
||||
using ThisType = cls; \
|
||||
using SuperType = XNNullClass;
|
||||
|
||||
#define XN_METATYPE(cls, sup) \
|
||||
public: \
|
||||
using ThisType = cls; \
|
||||
using SuperType = sup;
|
||||
|
@ -45,44 +45,6 @@ public:
|
||||
XNDDSInterface() = default;
|
||||
virtual ~XNDDSInterface() = default;
|
||||
|
||||
template <typename T>
|
||||
void getByteArray(eprosima::fastcdr::optional<T> data, uint8_t *buffer, size_t bufferSize)
|
||||
{
|
||||
if (bufferSize < getTypeSize<T>())
|
||||
return;
|
||||
|
||||
if constexpr (std::is_arithmetic_v<T>) {
|
||||
if (data) {
|
||||
std::memcpy(buffer, &data.value(), sizeof(T));
|
||||
} else {
|
||||
T zero = 0;
|
||||
std::memcpy(buffer, &zero, sizeof(T));
|
||||
}
|
||||
} else if constexpr (is_std_array_v<T>) {
|
||||
if (data) {
|
||||
getByteArrayFromStdArray(data.value(), buffer, bufferSize);
|
||||
} else {
|
||||
T zero = {};
|
||||
getByteArrayFromStdArray(zero, buffer, bufferSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, std::size_t N>
|
||||
void getByteArrayFromStdArray(std::array<T, N> data, uint8_t *buffer, size_t bufferSize)
|
||||
{
|
||||
if (bufferSize < getTypeSize<T>() * N)
|
||||
return;
|
||||
|
||||
for (std::size_t i = 0; i < N; ++i) {
|
||||
if constexpr (std::is_arithmetic_v<T>) {
|
||||
std::memcpy(buffer + i * getTypeSize<T>(), &data[i], getTypeSize<T>());
|
||||
} else {
|
||||
getByteArrayFromStdArray(data[i], buffer + i * getTypeSize<T>(), getTypeSize<T>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void getUDPPackage(uint8_t *buffer, size_t bufferSize)
|
||||
{
|
||||
if (bufferSize < MAX_UDP_PACKET_SIZE)
|
||||
@ -112,42 +74,6 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::string getString(eprosima::fastcdr::optional<T> data)
|
||||
{
|
||||
if constexpr (std::is_arithmetic_v<T>) {
|
||||
if (data) {
|
||||
return std::to_string(data.value());
|
||||
} else {
|
||||
return std::to_string(0);
|
||||
}
|
||||
} else if constexpr (std::is_same_v<T, std::string>) {
|
||||
if (data) {
|
||||
return getStringFromStdArray(data.value());
|
||||
} else {
|
||||
T zero = {};
|
||||
return getStringFromStdArray(zero);
|
||||
}
|
||||
}
|
||||
return std::string();
|
||||
}
|
||||
|
||||
template <typename T, std::size_t N>
|
||||
std::string getStringFromStdArray(std::array<T, N> data)
|
||||
{
|
||||
std::stringstream ss;
|
||||
for (std::size_t i = 0; i < N; ++i) {
|
||||
if (i > 0)
|
||||
ss << ",";
|
||||
if constexpr (std::is_arithmetic_v<T>) {
|
||||
ss << data[i];
|
||||
} else {
|
||||
ss << getStringFromStdArray(data[i]);
|
||||
}
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string getData(const std::string &varName)
|
||||
{
|
||||
int index1 = -1;
|
||||
@ -221,6 +147,81 @@ public:
|
||||
return list2[index2];
|
||||
}
|
||||
|
||||
protected:
|
||||
template <typename T>
|
||||
void getByteArray(eprosima::fastcdr::optional<T> data, uint8_t *buffer, size_t bufferSize)
|
||||
{
|
||||
if (bufferSize < getTypeSize<T>())
|
||||
return;
|
||||
|
||||
if constexpr (std::is_arithmetic_v<T>) {
|
||||
if (data) {
|
||||
std::memcpy(buffer, &data.value(), sizeof(T));
|
||||
} else {
|
||||
T zero = 0;
|
||||
std::memcpy(buffer, &zero, sizeof(T));
|
||||
}
|
||||
} else if constexpr (is_std_array_v<T>) {
|
||||
if (data) {
|
||||
getByteArrayFromStdArray(data.value(), buffer, bufferSize);
|
||||
} else {
|
||||
T zero = {};
|
||||
getByteArrayFromStdArray(zero, buffer, bufferSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, std::size_t N>
|
||||
void getByteArrayFromStdArray(std::array<T, N> data, uint8_t *buffer, size_t bufferSize)
|
||||
{
|
||||
if (bufferSize < getTypeSize<T>() * N)
|
||||
return;
|
||||
|
||||
for (std::size_t i = 0; i < N; ++i) {
|
||||
if constexpr (std::is_arithmetic_v<T>) {
|
||||
std::memcpy(buffer + i * getTypeSize<T>(), &data[i], getTypeSize<T>());
|
||||
} else {
|
||||
getByteArrayFromStdArray(data[i], buffer + i * getTypeSize<T>(), getTypeSize<T>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::string getString(eprosima::fastcdr::optional<T> data)
|
||||
{
|
||||
if constexpr (std::is_arithmetic_v<T>) {
|
||||
if (data) {
|
||||
return std::to_string(data.value());
|
||||
} else {
|
||||
return std::to_string(0);
|
||||
}
|
||||
} else if constexpr (std::is_same_v<T, std::string>) {
|
||||
if (data) {
|
||||
return getStringFromStdArray(data.value());
|
||||
} else {
|
||||
T zero = {};
|
||||
return getStringFromStdArray(zero);
|
||||
}
|
||||
}
|
||||
return std::string();
|
||||
}
|
||||
|
||||
template <typename T, std::size_t N>
|
||||
std::string getStringFromStdArray(std::array<T, N> data)
|
||||
{
|
||||
std::stringstream ss;
|
||||
for (std::size_t i = 0; i < N; ++i) {
|
||||
if (i > 0)
|
||||
ss << ",";
|
||||
if constexpr (std::is_arithmetic_v<T>) {
|
||||
ss << data[i];
|
||||
} else {
|
||||
ss << getStringFromStdArray(data[i]);
|
||||
}
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
protected:
|
||||
struct ByteArrayFunc {
|
||||
std::function<void(uint8_t *, size_t)> func;
|
||||
@ -239,3 +240,47 @@ protected:
|
||||
getByteArrayFunction.push_back( \
|
||||
{[this](uint8_t *buffer, size_t size) { getByteArray(data.NAME(), buffer, size); }, \
|
||||
getTypeSize<decltype(data.NAME())>()})
|
||||
|
||||
#define ASSIGN_VALUE_GET(NAME) \
|
||||
if (data.NAME()) { \
|
||||
auto temp = data.NAME().value(); \
|
||||
if constexpr (std::is_arithmetic_v<decltype(temp)>) { \
|
||||
model_data->NAME = temp; \
|
||||
} else if constexpr (std::is_std_array_v<decltype(temp)>) { \
|
||||
size_t arraySize = std::tuple_size<decltype(temp)>::value; \
|
||||
for (size_t i = 0; i < arraySize; ++i) { \
|
||||
if constexpr (std::is_arithmetic_v<decltype(temp[i])>) { \
|
||||
model_data->NAME[i] = temp[i]; \
|
||||
} else if constexpr (std::is_std_array_v<decltype(temp[i])>) { \
|
||||
size_t arraySize2 = std::tuple_size<decltype(temp[i])>::value; \
|
||||
for (size_t j = 0; j < arraySize2; ++j) { \
|
||||
model_data->NAME[i][j] = temp[i][j]; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
#define ASSIGN_VALUE_SET(NAME) \
|
||||
if constexpr (std::is_arithmetic_v<decltype(data.NAME())::type>) { \
|
||||
data.NAME(model_data->NAME); \
|
||||
} else if constexpr (std::is_std_array_v<decltype(data.NAME())::type>) { \
|
||||
using thisType = typename decltype(data.NAME())::type; \
|
||||
thisType temp; \
|
||||
size_t arraySize1 = std::tuple_size<thisType>::value; \
|
||||
using subType = thisType::value_type; \
|
||||
if constexpr (std::is_arithmetic_v<subType>) { \
|
||||
for (size_t i = 0; i < arraySize1; ++i) { \
|
||||
temp[i] = model_data->NAME[i]; \
|
||||
} \
|
||||
} else if constexpr (std::is_std_array_v<subType>) { \
|
||||
size_t arraySize2 = std::tuple_size<subType>::value; \
|
||||
std::array<subType, arraySize1> temp; \
|
||||
for (size_t i = 0; i < arraySize1; ++i) { \
|
||||
for (size_t j = 0; j < arraySize2; ++j) { \
|
||||
temp[i][j] = model_data->NAME[i][j]; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
data.NAME(temp); \
|
||||
}
|
||||
|
@ -1,14 +1,6 @@
|
||||
#pragma once
|
||||
#include "XNBaseFrameObject.h"
|
||||
|
||||
#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/Subscriber.hpp>
|
||||
#include <fastdds/dds/topic/TypeSupport.hpp>
|
||||
#include <fastdds/dds/subscriber/DataReaderListener.hpp>
|
||||
#include "XNBaseFrameObject_p.h"
|
||||
|
||||
struct PublisherInfo {
|
||||
FAST_DDS_MACRO::Publisher *publisher;
|
||||
@ -22,8 +14,8 @@ struct SubscriberInfo {
|
||||
|
||||
struct TopicInfo {
|
||||
FAST_DDS_MACRO::Topic *topic;
|
||||
QMap<quint32, PublisherInfo> publishers_;
|
||||
QMap<quint32, SubscriberInfo> subscribers_;
|
||||
std::map<uint32_t, PublisherInfo> publishers_;
|
||||
std::map<uint32_t, SubscriberInfo> subscribers_;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
@ -46,50 +38,54 @@ private:
|
||||
std::function<void(const T &)> callback_;
|
||||
};
|
||||
|
||||
class XNDDSManagerPrivate;
|
||||
struct XNDDSManagerPrivate : public XNBaseFrameObjectPrivate {
|
||||
FAST_DDS_MACRO::DomainParticipant *participant_;
|
||||
std::map<std::string, TopicInfo> topics_;
|
||||
std::mutex mutex_;
|
||||
};
|
||||
|
||||
class XNDDSManager : public XNBaseFrameObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DECLARE_PRIVATE(XNDDSManager)
|
||||
Q_DISABLE_COPY(XNDDSManager)
|
||||
XN_METATYPE(XNDDSManager, XNBaseFrameObject)
|
||||
XN_DECLARE_PRIVATE(XNDDSManager)
|
||||
public:
|
||||
explicit XNDDSManager(QObject *parent = nullptr);
|
||||
XNDDSManager();
|
||||
~XNDDSManager();
|
||||
|
||||
protected:
|
||||
XNDDSManager(XNDDSManagerPrivate &dd, QObject *parent = nullptr);
|
||||
XNDDSManager(PrivateType *p);
|
||||
|
||||
public slots:
|
||||
virtual void OnInitialize() override;
|
||||
public:
|
||||
virtual bool Initialize() override;
|
||||
|
||||
virtual void OnPrepareForExecute() override;
|
||||
virtual bool PrepareForExecute() override;
|
||||
|
||||
void SetDomainID(quint32 domainID);
|
||||
void SetDomainID(uint32_t domainID);
|
||||
|
||||
public:
|
||||
template <typename T>
|
||||
FAST_DDS_MACRO::DataWriter *RegisterPublisher(const QString &topicName, quint32 publisherID)
|
||||
FAST_DDS_MACRO::DataWriter *RegisterPublisher(const std::string &topicName,
|
||||
uint32_t publisherID)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
if (!topics_.contains(topicName)) {
|
||||
topics_[topicName] = TopicInfo();
|
||||
TopicInfo &tmp = topics_[topicName];
|
||||
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];
|
||||
FAST_DDS_MACRO::TypeSupport typeSupport(new T());
|
||||
typeSupport.register_type(participant_);
|
||||
tmp.topic =
|
||||
participant_->create_topic(topicName.toStdString(), typeSupport.get_type_name(),
|
||||
typeSupport.register_type(d->participant_);
|
||||
tmp.topic = d->participant_->create_topic(topicName, typeSupport.get_type_name(),
|
||||
FAST_DDS_MACRO::TOPIC_QOS_DEFAULT);
|
||||
if (tmp.topic == nullptr) {
|
||||
LOG_ERROR("0x2130 Create Topic %1 Failed!", topicName);
|
||||
topics_.remove(topicName);
|
||||
d->topics_.erase(topicName);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
TopicInfo &tmp = topics_[topicName];
|
||||
TopicInfo &tmp = d->topics_[topicName];
|
||||
tmp.publishers_[publisherID] = PublisherInfo();
|
||||
tmp.publishers_[publisherID].publisher =
|
||||
participant_->create_publisher(FAST_DDS_MACRO::PUBLISHER_QOS_DEFAULT, nullptr);
|
||||
d->participant_->create_publisher(FAST_DDS_MACRO::PUBLISHER_QOS_DEFAULT, nullptr);
|
||||
if (tmp.publishers_[publisherID].publisher == nullptr) {
|
||||
LOG_ERROR("0x2131 Create Publisher %1 for Topic %2 Failed!", publisherID, topicName);
|
||||
return nullptr;
|
||||
@ -119,29 +115,28 @@ public:
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void RegisterSubscriber(const QString &topicName, quint32 subscriberID,
|
||||
void RegisterSubscriber(const std::string &topicName, uint32_t subscriberID,
|
||||
std::function<void(const typename T::type &)> fun)
|
||||
{
|
||||
Q_D(XNDDSManager);
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
if (!topics_.contains(topicName)) {
|
||||
topics_[topicName] = TopicInfo();
|
||||
TopicInfo &tmp = topics_[topicName];
|
||||
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];
|
||||
FAST_DDS_MACRO::TypeSupport typeSupport(new T());
|
||||
typeSupport.register_type(participant_);
|
||||
tmp.topic =
|
||||
participant_->create_topic(topicName.toStdString(), typeSupport.get_type_name(),
|
||||
typeSupport.register_type(d->participant_);
|
||||
tmp.topic = d->participant_->create_topic(topicName, typeSupport.get_type_name(),
|
||||
FAST_DDS_MACRO::TOPIC_QOS_DEFAULT);
|
||||
if (tmp.topic == nullptr) {
|
||||
LOG_ERROR("0x2130 Create Topic %1 Failed!", topicName);
|
||||
topics_.remove(topicName);
|
||||
d->topics_.erase(topicName);
|
||||
return;
|
||||
}
|
||||
}
|
||||
TopicInfo &tmp = topics_[topicName];
|
||||
TopicInfo &tmp = d->topics_[topicName];
|
||||
tmp.subscribers_[subscriberID] = SubscriberInfo();
|
||||
tmp.subscribers_[subscriberID].subscriber =
|
||||
participant_->create_subscriber(FAST_DDS_MACRO::SUBSCRIBER_QOS_DEFAULT, nullptr);
|
||||
d->participant_->create_subscriber(FAST_DDS_MACRO::SUBSCRIBER_QOS_DEFAULT, nullptr);
|
||||
if (tmp.subscribers_[subscriberID].subscriber == nullptr) {
|
||||
LOG_ERROR("0x2135 Create Subscriber %1 for Topic %2 Failed!", subscriberID, topicName);
|
||||
}
|
||||
@ -157,9 +152,4 @@ public:
|
||||
}
|
||||
LOG_INFO("0x2137 Create Subscriber %1 for Topic %2 Success!", subscriberID, topicName);
|
||||
}
|
||||
|
||||
private:
|
||||
FAST_DDS_MACRO::DomainParticipant *participant_;
|
||||
QMap<QString, TopicInfo> topics_;
|
||||
std::mutex mutex_;
|
||||
};
|
||||
|
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
#include "XNBaseFrameObject.h"
|
||||
#include <QVariant>
|
||||
|
||||
// 事件优先级定义
|
||||
namespace XNEvent
|
||||
{
|
||||
@ -11,19 +11,18 @@ enum class Priority {
|
||||
Low = 3 // 低优先级
|
||||
};
|
||||
}
|
||||
|
||||
// 前向声明私有类
|
||||
class XNEventManagerPrivate;
|
||||
struct XNEventManagerPrivate;
|
||||
|
||||
// 事件管理器类,继承自XNBaseFrameObject
|
||||
class XNEventManager : public XNBaseFrameObject
|
||||
{
|
||||
Q_OBJECT // 启用Qt的元对象系统
|
||||
Q_DECLARE_PRIVATE(XNEventManager) // 声明私有实现类
|
||||
Q_DISABLE_COPY(XNEventManager) // 禁用拷贝构造和赋值操作
|
||||
|
||||
XN_METATYPE(XNEventManager, XNBaseFrameObject)
|
||||
XN_DECLARE_PRIVATE(XNEventManager)
|
||||
public:
|
||||
// 构造函数,创建事件管理器实例
|
||||
explicit XNEventManager(QObject *parent = nullptr);
|
||||
XNEventManager();
|
||||
// 析构函数
|
||||
~XNEventManager();
|
||||
|
||||
@ -34,21 +33,20 @@ class XNEventManager : public XNBaseFrameObject
|
||||
// @param async: 是否异步处理该事件
|
||||
// @param priority: 事件优先级
|
||||
// @return: 返回处理器ID,失败返回-1
|
||||
int RegisterEventHandler(const QString &eventName,
|
||||
std::function<void(const QVariant &)> callback, quint32 objectId,
|
||||
bool async = false,
|
||||
int RegisterEventHandler(const std::string &eventName, XNEventCallback callback,
|
||||
uint32_t objectId, bool async = false,
|
||||
XNEvent::Priority priority = XNEvent::Priority::Normal);
|
||||
// 移除事件处理器
|
||||
// @param eventName: 事件名称
|
||||
// @param handlerId: 处理器ID
|
||||
// @return: 移除是否成功
|
||||
bool RemoveEventHandler(const QString &eventName, int handlerId);
|
||||
bool RemoveEventHandler(const std::string &eventName, int handlerId);
|
||||
// 触发指定事件
|
||||
// @param eventName: 要触发的事件名称
|
||||
// @param eventData: 事件携带的数据
|
||||
// @param forceAsync: 强制异步处理
|
||||
// @param priority: 事件优先级
|
||||
void TriggerEvent(const QString &eventName, const QVariant &eventData = QVariant(),
|
||||
void TriggerEvent(const std::string &eventName, const std::any &eventData = std::any(),
|
||||
bool forceAsync = false,
|
||||
XNEvent::Priority priority = XNEvent::Priority::Normal);
|
||||
|
||||
@ -64,17 +62,16 @@ class XNEventManager : public XNBaseFrameObject
|
||||
// 设置实时线程池参数
|
||||
void SetRTThreadPoolConfig(int maxThreads, int minPriority, int maxPriority);
|
||||
|
||||
// 事件处理完成回调
|
||||
void EventProcessed(const std::string &eventName, bool success);
|
||||
|
||||
protected:
|
||||
// 保护构造函数,用于继承实现
|
||||
XNEventManager(XNEventManagerPrivate &dd, QObject *parent = nullptr);
|
||||
XNEventManager(PrivateType *p);
|
||||
|
||||
public slots:
|
||||
public:
|
||||
// 初始化事件管理器
|
||||
virtual void OnInitialize() override;
|
||||
virtual bool Initialize() override;
|
||||
// 准备执行
|
||||
virtual void OnPrepareForExecute() override;
|
||||
|
||||
signals:
|
||||
// 事件处理完成信号
|
||||
void EventProcessed(const QString &eventName, bool success);
|
||||
virtual bool PrepareForExecute() override;
|
||||
};
|
@ -1,9 +1,6 @@
|
||||
#pragma once
|
||||
#include "XNBaseFrameObject_p.h"
|
||||
#include "XNEventManager.h"
|
||||
#include <QMap>
|
||||
#include <QMutex>
|
||||
#include <QThreadPool>
|
||||
#include <functional>
|
||||
#include <sys/types.h>
|
||||
#include <bits/pthreadtypes.h>
|
||||
@ -12,78 +9,130 @@
|
||||
#include <queue>
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
#include <string>
|
||||
#include <any>
|
||||
#include <map>
|
||||
#include <list>
|
||||
|
||||
// 事件处理器信息结构
|
||||
struct EventHandlerInfo {
|
||||
std::function<void(const QVariant &)> callback; // 回调函数
|
||||
quint32 objectId; // 对象ID
|
||||
int localId; // 本地ID
|
||||
std::function<void(const std::any &)> callback; // 回调函数
|
||||
uint32_t objectId; // 对象ID
|
||||
uint32_t localId; // 本地ID
|
||||
bool isAsync; // 是否异步处理
|
||||
XNEvent::Priority priority; // 事件优先级
|
||||
int threadPriority; // 线程优先级
|
||||
uint32_t threadPriority; // 线程优先级
|
||||
|
||||
// 获取全局处理器ID
|
||||
int GetHandlerId() const { return (objectId << 16) | (localId & 0xFFFF); }
|
||||
uint32_t GetHandlerId() const { return (objectId << 16) | (localId & 0xFFFF); }
|
||||
|
||||
// 从全局处理器ID中提取对象ID
|
||||
static quint32 GetObjectId(int handlerId) { return handlerId >> 16; }
|
||||
static uint32_t GetObjectId(uint32_t handlerId) { return handlerId >> 16; }
|
||||
|
||||
// 从全局处理器ID中提取本地ID
|
||||
static int GetLocalId(int handlerId) { return handlerId & 0xFFFF; }
|
||||
static uint32_t GetLocalId(uint32_t handlerId) { return handlerId & 0xFFFF; }
|
||||
};
|
||||
|
||||
// 事件任务基类
|
||||
class BaseEventTask : public QRunnable
|
||||
class BaseEventTask
|
||||
{
|
||||
public:
|
||||
BaseEventTask(const QString &name, const QVariant &data,
|
||||
std::function<void(const QVariant &)> callback, XNEventManager *manager)
|
||||
/**
|
||||
* @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)
|
||||
{
|
||||
setAutoDelete(true);
|
||||
}
|
||||
virtual ~BaseEventTask() = default;
|
||||
|
||||
/**
|
||||
* @brief 执行任务
|
||||
*/
|
||||
virtual void execute() = 0;
|
||||
|
||||
protected:
|
||||
QString eventName;
|
||||
QVariant eventData;
|
||||
std::function<void(const QVariant &)> eventCallback;
|
||||
std::string eventName;
|
||||
std::any eventData;
|
||||
std::function<void(const std::any &)> eventCallback;
|
||||
XNEventManager *eventManager;
|
||||
};
|
||||
|
||||
// 实时事件任务
|
||||
class RTEventTask
|
||||
// 异步事件任务
|
||||
class AsyncEventTask : public BaseEventTask
|
||||
{
|
||||
public:
|
||||
RTEventTask(const QString &name, const QVariant &data,
|
||||
std::function<void(const QVariant &)> callback, XNEventManager *manager)
|
||||
: eventName(name), eventData(data), eventCallback(callback), eventManager(manager)
|
||||
/**
|
||||
* @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)
|
||||
{
|
||||
}
|
||||
|
||||
void execute()
|
||||
/**
|
||||
* @brief 执行任务
|
||||
*/
|
||||
void execute() override
|
||||
{
|
||||
try {
|
||||
eventCallback(eventData);
|
||||
if (eventManager) {
|
||||
QMetaObject::invokeMethod(eventManager, "EventProcessed", Qt::QueuedConnection,
|
||||
Q_ARG(QString, eventName), Q_ARG(bool, true));
|
||||
eventManager->EventProcessed(eventName, true);
|
||||
}
|
||||
} catch (const std::exception &e) {
|
||||
LOG_ERROR(
|
||||
QString("RT event handler exception for %1: %2").arg(eventName).arg(e.what()));
|
||||
LOG_ERROR("Async event handler exception for " + eventName + ": " + e.what());
|
||||
if (eventManager) {
|
||||
QMetaObject::invokeMethod(eventManager, "EventProcessed", Qt::QueuedConnection,
|
||||
Q_ARG(QString, eventName), Q_ARG(bool, false));
|
||||
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)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
QString eventName;
|
||||
QVariant eventData;
|
||||
std::function<void(const QVariant &)> eventCallback;
|
||||
XNEventManager *eventManager;
|
||||
/**
|
||||
* @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);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 实时线程管理器
|
||||
@ -167,35 +216,27 @@ private:
|
||||
};
|
||||
|
||||
// 事件管理器的私有实现类
|
||||
class XNEventManagerPrivate : public XNBaseFrameObjectPrivate
|
||||
{
|
||||
public:
|
||||
// 声明公共接口类
|
||||
Q_DECLARE_PUBLIC(XNEventManager)
|
||||
|
||||
// 构造函数,初始化私有实现
|
||||
explicit XNEventManagerPrivate(XNEventManager *q) : XNBaseFrameObjectPrivate(q) {}
|
||||
|
||||
struct XNEventManagerPrivate : public XNBaseFrameObjectPrivate {
|
||||
// 存储事件及其对应的处理器信息列表
|
||||
// key: 事件名称
|
||||
// value: 该事件对应的所有处理器信息列表
|
||||
QMap<QString, QList<EventHandlerInfo>> eventHandlers;
|
||||
std::map<std::string, std::list<EventHandlerInfo>> eventHandlers;
|
||||
|
||||
// 处理器ID到事件名称的反向映射,用于快速查找
|
||||
QMap<int, QString> handlerToEvent;
|
||||
std::map<int, std::string> handlerToEvent;
|
||||
|
||||
// 本地ID计数器
|
||||
int localIdCounter = 0;
|
||||
|
||||
// 互斥锁,用于保护事件处理器表的线程安全访问
|
||||
QMutex eventMutex;
|
||||
std::mutex eventMutex;
|
||||
|
||||
// 线程池,用于异步执行事件处理器
|
||||
QThreadPool threadPool;
|
||||
|
||||
// 实时线程池
|
||||
QThreadPool rtThreadPool;
|
||||
// 线程池相关
|
||||
std::vector<std::thread> workerThreads;
|
||||
std::queue<BaseEventTask *> taskQueue;
|
||||
std::mutex taskMutex;
|
||||
std::condition_variable taskCond;
|
||||
bool running = true;
|
||||
|
||||
RTThreadManager rtManager;
|
||||
QThreadPool normalThreadPool; // 用于非实时任务
|
||||
};
|
||||
|
@ -12,195 +12,164 @@
|
||||
|
||||
#include "XNObject.h"
|
||||
|
||||
class XNFrameworkPrivate;
|
||||
struct XNFrameworkPrivate;
|
||||
|
||||
/**
|
||||
* @brief 框架类
|
||||
*/
|
||||
class XNCORE_EXPORT XNFramework : public XNObject
|
||||
{
|
||||
/**
|
||||
* @brief 宏定义,用于支持Qt的元对象系统
|
||||
*/
|
||||
Q_OBJECT
|
||||
|
||||
/**
|
||||
* @brief 宏定义,用于禁用拷贝构造函数
|
||||
*/
|
||||
Q_DISABLE_COPY(XNFramework)
|
||||
XN_METATYPE(XNFramework, XNObject)
|
||||
|
||||
/**
|
||||
* @brief 宏定义,用于声明私有数据成员
|
||||
*/
|
||||
Q_DECLARE_PRIVATE(XNFramework);
|
||||
|
||||
/**
|
||||
* @brief 宏定义,用于声明属性workPath
|
||||
*/
|
||||
Q_PROPERTY(QString workPath READ GetWorkPath WRITE SetWorkPath)
|
||||
|
||||
/**
|
||||
* @brief 宏定义,用于声明属性modelPath
|
||||
*/
|
||||
Q_PROPERTY(QString modelPath READ GetModelPath WRITE SetModelPath)
|
||||
|
||||
/**
|
||||
* @brief 宏定义,用于声明属性cpuAffinity
|
||||
*/
|
||||
Q_PROPERTY(quint32 cpuAffinity READ GetCpuAffinity WRITE SetCpuAffinity)
|
||||
|
||||
XN_DECLARE_PRIVATE(XNFramework)
|
||||
public:
|
||||
/**
|
||||
* @brief 构造函数
|
||||
* @param parent 父对象
|
||||
*/
|
||||
explicit XNFramework(QObject *parent = nullptr);
|
||||
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 场景管理器
|
||||
*/
|
||||
XNScenarioManagerPtr GetScenarioManager();
|
||||
|
||||
/**
|
||||
* @brief 获取服务管理器
|
||||
* @return 服务管理器
|
||||
*/
|
||||
XNServiceManagerPtr GetServiceManager();
|
||||
|
||||
/**
|
||||
* @brief 获取线程管理器
|
||||
* @return 线程管理器
|
||||
*/
|
||||
XNThreadManagerPtr GetThreadManager();
|
||||
|
||||
/**
|
||||
* @brief 获取时间管理器
|
||||
* @return 时间管理器
|
||||
*/
|
||||
XNTimeManagerPtr GetTimeManager();
|
||||
|
||||
/**
|
||||
* @brief 获取工作路径
|
||||
* @return 工作路径
|
||||
*/
|
||||
QString GetWorkPath();
|
||||
std::string GetWorkPath();
|
||||
|
||||
/**
|
||||
* @brief 设置工作路径
|
||||
* @param workPath 工作路径
|
||||
*/
|
||||
void SetWorkPath(const std::string &workPath);
|
||||
|
||||
/**
|
||||
* @brief 获取模型库路径
|
||||
* @return 模型库路径
|
||||
*/
|
||||
QString GetModelPath();
|
||||
std::string GetModelPath();
|
||||
|
||||
/**
|
||||
* @brief 设置模型库路径
|
||||
* @param modelPath 模型库路径
|
||||
*/
|
||||
void SetModelPath(const std::string &modelPath);
|
||||
|
||||
/**
|
||||
* @brief 获取服务库路径
|
||||
* @return 服务库路径
|
||||
*/
|
||||
QString GetServicePath();
|
||||
std::string GetServicePath();
|
||||
|
||||
/**
|
||||
* @brief 设置服务库路径
|
||||
* @param servicePath 服务库路径
|
||||
*/
|
||||
void SetServicePath(const std::string &servicePath);
|
||||
|
||||
/**
|
||||
* @brief 获取CPU亲和性
|
||||
* @return CPU亲和性
|
||||
*/
|
||||
quint32 GetCpuAffinity();
|
||||
uint32_t GetCpuAffinity();
|
||||
|
||||
/**
|
||||
* @brief 设置CPU亲和性
|
||||
* @param cpuAffinity CPU亲和性
|
||||
*/
|
||||
void SetCpuAffinity(uint32_t cpuAffinity);
|
||||
|
||||
/**
|
||||
* @brief 设置场景XML
|
||||
* @param scenarioXml 场景XML
|
||||
*/
|
||||
void SetScenarioXml(const QString &scenarioXml);
|
||||
|
||||
signals:
|
||||
/**
|
||||
* @brief 初始化
|
||||
*/
|
||||
void Initialize();
|
||||
|
||||
/**
|
||||
* @brief 初始化成功
|
||||
*/
|
||||
void InitializeSuccess(bool isSuccess);
|
||||
void SetScenarioXml(const std::string &scenarioXml);
|
||||
|
||||
/**
|
||||
* @brief 准备执行
|
||||
*/
|
||||
void PrepareForExecute();
|
||||
|
||||
/**
|
||||
* @brief 准备执行成功
|
||||
*/
|
||||
void PrepareForExecuteSuccess(bool isSuccess);
|
||||
|
||||
/**
|
||||
* @brief 分析场景XML
|
||||
* @param scenarioXml 场景XML
|
||||
*/
|
||||
void AnalyzeScenarioXml(const QString &scenarioXml);
|
||||
void AnalyzeScenarioXml(const std::string &scenarioXml);
|
||||
|
||||
/**
|
||||
* @brief 仿真控制
|
||||
* @param objectId 对象ID
|
||||
* @param cmd 命令
|
||||
*/
|
||||
void SimControl(quint32 objectId, SimControlCmd cmd);
|
||||
|
||||
public slots:
|
||||
/**
|
||||
* @brief 设置工作路径
|
||||
* @param workPath 工作路径
|
||||
*/
|
||||
void SetWorkPath(const QString &workPath);
|
||||
|
||||
/**
|
||||
* @brief 设置模型库路径
|
||||
* @param modelPath 模型库路径
|
||||
*/
|
||||
void SetModelPath(const QString &modelPath);
|
||||
|
||||
/**
|
||||
* @brief 设置服务库路径
|
||||
* @param servicePath 服务库路径
|
||||
*/
|
||||
void SetServicePath(const QString &servicePath);
|
||||
|
||||
/**
|
||||
* @brief 设置CPU亲和性
|
||||
* @param cpuAffinity CPU亲和性
|
||||
*/
|
||||
void SetCpuAffinity(quint32 cpuAffinity);
|
||||
void SimControl(uint32_t objectId, SimControlCmd cmd);
|
||||
|
||||
/**
|
||||
* @brief 初始化
|
||||
*/
|
||||
void OnInitialize();
|
||||
|
||||
/**
|
||||
* @brief 初始化成功
|
||||
*/
|
||||
void OnInitializeSuccess();
|
||||
|
||||
/**
|
||||
* @brief 初始化失败
|
||||
*/
|
||||
void OnInitializeFailed();
|
||||
|
||||
/**
|
||||
* @brief 解析配置文件成功
|
||||
*/
|
||||
void OnAnalyzeScenarioXmlSuccess();
|
||||
|
||||
/**
|
||||
* @brief 解析配置文件失败
|
||||
*/
|
||||
void OnAnalyzeScenarioXmlFailed();
|
||||
|
||||
/**
|
||||
* @brief 准备执行
|
||||
*/
|
||||
void OnPrepareForExecute();
|
||||
|
||||
/**
|
||||
* @brief 准备执行成功
|
||||
*/
|
||||
void OnPrepareForExecuteSuccess();
|
||||
|
||||
/**
|
||||
* @brief 准备执行失败
|
||||
*/
|
||||
void OnPrepareForExecuteFailed();
|
||||
void Initialize();
|
||||
|
||||
/**
|
||||
* @brief 仿真控制
|
||||
* @param cmd 命令
|
||||
*/
|
||||
void OnSimControl(quint32 objectId, SimControlCmd cmd);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief 构造函数
|
||||
* @param dd 私有数据成员
|
||||
* @param parent 父对象
|
||||
*/
|
||||
XNFramework(XNFrameworkPrivate &dd, QObject *parent = nullptr);
|
||||
void OnSimControl(uint32_t objectId, SimControlCmd cmd);
|
||||
};
|
||||
|
@ -16,43 +16,65 @@
|
||||
/**
|
||||
* @brief 框架类的私有数据成员
|
||||
*/
|
||||
class XNFrameworkPrivate : public XNObjectPrivate
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief 构造函数
|
||||
* @param q 框架类指针
|
||||
*/
|
||||
explicit XNFrameworkPrivate(XNFramework *q) : XNObjectPrivate(q) {}
|
||||
struct XNFrameworkPrivate : public XNObjectPrivate {
|
||||
|
||||
/**
|
||||
* @brief 宏定义,用于声明公有数据成员
|
||||
* @brief DDS管理器
|
||||
*/
|
||||
Q_DECLARE_PUBLIC(XNFramework)
|
||||
XNDDSManagerPtr ddsManager;
|
||||
|
||||
/**
|
||||
* @brief 事件管理器
|
||||
*/
|
||||
XNEventManagerPtr eventManager;
|
||||
|
||||
/**
|
||||
* @brief 模型管理器
|
||||
*/
|
||||
XNModelManagerPtr modelManager;
|
||||
|
||||
/**
|
||||
* @brief 场景管理器
|
||||
*/
|
||||
XNScenarioManagerPtr scenarioManager;
|
||||
|
||||
/**
|
||||
* @brief 服务管理器
|
||||
*/
|
||||
XNServiceManagerPtr serviceManager;
|
||||
|
||||
/**
|
||||
* @brief 线程管理器
|
||||
*/
|
||||
XNThreadManagerPtr threadManager;
|
||||
|
||||
/**
|
||||
* @brief 时间管理器
|
||||
*/
|
||||
XNTimeManagerPtr timeManager;
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief 工作路径
|
||||
*/
|
||||
QString workPath;
|
||||
std::string workPath;
|
||||
|
||||
/**
|
||||
* @brief 模型路径
|
||||
*/
|
||||
QString modelPath;
|
||||
std::string modelPath;
|
||||
|
||||
/**
|
||||
* @brief 服务路径
|
||||
*/
|
||||
QString servicePath;
|
||||
std::string servicePath;
|
||||
|
||||
/**
|
||||
* @brief CPU亲和性
|
||||
*/
|
||||
quint32 uCpuAffinity;
|
||||
uint32_t uCpuAffinity;
|
||||
|
||||
/**
|
||||
* @brief 场景XML
|
||||
*/
|
||||
QString scenarioXml;
|
||||
std::string scenarioXml;
|
||||
};
|
||||
|
@ -9,13 +9,15 @@
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
#include <QString>
|
||||
#include <QMutex>
|
||||
#include <QFile>
|
||||
#include <QTextStream>
|
||||
#include <QDateTime>
|
||||
#include <QDir>
|
||||
#include <string>
|
||||
#include <mutex>
|
||||
#include <fstream>
|
||||
#include <chrono>
|
||||
#include <filesystem>
|
||||
#include <type_traits>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
|
||||
/**
|
||||
* @brief 日志类
|
||||
@ -34,7 +36,6 @@ public:
|
||||
*/
|
||||
static XNLogger &instance()
|
||||
{
|
||||
// 懒汉式单例,C++11 及以上版本的标准保证了局部静态变量的初始化是线程安全的
|
||||
static XNLogger instance;
|
||||
return instance;
|
||||
}
|
||||
@ -44,7 +45,7 @@ public:
|
||||
* @param level 日志等级
|
||||
* @param message 日志消息
|
||||
*/
|
||||
void log(LogLevel level, const QString &message);
|
||||
void log(LogLevel level, const std::string &message);
|
||||
|
||||
/**
|
||||
* @brief 启用控制台输出
|
||||
@ -64,7 +65,7 @@ private:
|
||||
/**
|
||||
* @brief 构造函数
|
||||
*/
|
||||
XNLogger(); // 默认构造函数
|
||||
XNLogger();
|
||||
|
||||
/**
|
||||
* @brief 析构函数
|
||||
@ -74,17 +75,17 @@ private:
|
||||
/**
|
||||
* @brief 禁止拷贝构造
|
||||
*/
|
||||
XNLogger(const XNLogger &) = delete; // 禁止拷贝构造
|
||||
XNLogger(const XNLogger &) = delete;
|
||||
|
||||
/**
|
||||
* @brief 禁止赋值
|
||||
*/
|
||||
XNLogger &operator=(const XNLogger &) = delete; // 禁止赋值
|
||||
XNLogger &operator=(const XNLogger &) = delete;
|
||||
|
||||
/**
|
||||
* @brief 日志文件路径
|
||||
*/
|
||||
QString logFilePath;
|
||||
std::string logFilePath;
|
||||
|
||||
/**
|
||||
* @brief 控制台输出控制
|
||||
@ -99,44 +100,50 @@ private:
|
||||
/**
|
||||
* @brief 日志文件
|
||||
*/
|
||||
QFile logFile;
|
||||
std::ofstream logFile;
|
||||
|
||||
/**
|
||||
* @brief 互斥锁
|
||||
*/
|
||||
QMutex mutex;
|
||||
std::mutex mutex;
|
||||
|
||||
/**
|
||||
* @brief 日志等级转换为字符串
|
||||
* @param level 日志等级
|
||||
* @return 日志等级字符串
|
||||
*/
|
||||
QString logLevelToString(LogLevel level) const;
|
||||
std::string logLevelToString(LogLevel level) const;
|
||||
|
||||
/**
|
||||
* @brief 获取当前时间字符串
|
||||
* @return 格式化的时间字符串
|
||||
*/
|
||||
std::string getCurrentTimeString() const;
|
||||
|
||||
/**
|
||||
* @brief 控制台输出字体恢复颜色常量
|
||||
*/
|
||||
const QString COLOR_RESET = "\033[0m";
|
||||
const std::string COLOR_RESET = "\033[0m";
|
||||
|
||||
/**
|
||||
* @brief 调试颜色常量
|
||||
*/
|
||||
const QString COLOR_DEBUG = "\033[34m"; // 蓝色
|
||||
const std::string COLOR_DEBUG = "\033[34m"; // 蓝色
|
||||
|
||||
/**
|
||||
* @brief 信息颜色常量
|
||||
*/
|
||||
const QString COLOR_INFO = "\033[32m"; // 绿色
|
||||
const std::string COLOR_INFO = "\033[32m"; // 绿色
|
||||
|
||||
/**
|
||||
* @brief 警告颜色常量
|
||||
*/
|
||||
const QString COLOR_WARNING = "\033[33m"; // 黄色
|
||||
const std::string COLOR_WARNING = "\033[33m"; // 黄色
|
||||
|
||||
/**
|
||||
* @brief 错误颜色常量
|
||||
*/
|
||||
const QString COLOR_ERROR = "\033[31m"; // 红色
|
||||
const std::string COLOR_ERROR = "\033[31m"; // 红色
|
||||
};
|
||||
|
||||
/**
|
||||
@ -154,9 +161,9 @@ public:
|
||||
*/
|
||||
template <typename... Args>
|
||||
inline static typename std::enable_if<(sizeof...(Args) > 0), void>::type
|
||||
log(XNLogger::LogLevel level, const QString &message, Args... args)
|
||||
log(XNLogger::LogLevel level, const std::string &message, Args... args)
|
||||
{
|
||||
QString formattedMessage = formatMessage(message, args...);
|
||||
std::string formattedMessage = formatMessage(message, args...);
|
||||
XNLogger::instance().log(level, formattedMessage);
|
||||
}
|
||||
|
||||
@ -165,7 +172,7 @@ public:
|
||||
* @param level 日志等级
|
||||
* @param message 日志消息
|
||||
*/
|
||||
inline static void log(XNLogger::LogLevel level, const QString &message)
|
||||
inline static void log(XNLogger::LogLevel level, const std::string &message)
|
||||
{
|
||||
XNLogger::instance().log(level, message);
|
||||
}
|
||||
@ -173,27 +180,44 @@ public:
|
||||
private:
|
||||
// 辅助函数,用于格式化消息
|
||||
template <typename T>
|
||||
static QString convertToString(const T &arg)
|
||||
static std::string convertToString(const T &arg)
|
||||
{
|
||||
if constexpr (std::is_arithmetic<T>::value) {
|
||||
return QString::number(arg); // 处理数值类型
|
||||
return std::to_string(arg); // 处理数值类型
|
||||
} else {
|
||||
return arg;
|
||||
return std::string(arg);
|
||||
}
|
||||
}
|
||||
|
||||
// 递归变参函数,用于处理多个参数
|
||||
template <typename T, typename... Args>
|
||||
static QString formatMessage(const QString &message, T arg, Args... args)
|
||||
static std::string formatMessage(const std::string &message, T arg, Args... args)
|
||||
{
|
||||
return formatMessage(message.arg(convertToString(arg)), args...); // 递归调用
|
||||
// 查找下一个参数占位符
|
||||
std::string result = message;
|
||||
size_t paramIndex = 0;
|
||||
size_t pos = 0;
|
||||
|
||||
// 找到当前参数对应的占位符
|
||||
while (true) {
|
||||
std::string placeholder = "%" + std::to_string(paramIndex + 1);
|
||||
pos = result.find(placeholder);
|
||||
if (pos != std::string::npos) {
|
||||
// 替换占位符,使用placeholder的长度
|
||||
result.replace(pos, placeholder.length(), convertToString(arg));
|
||||
break;
|
||||
}
|
||||
paramIndex++;
|
||||
if (paramIndex > 100) { // 防止无限循环
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return formatMessage(result, args...);
|
||||
}
|
||||
|
||||
// 基础情况
|
||||
static QString formatMessage(const QString &message)
|
||||
{
|
||||
return message; // 处理没有参数的情况
|
||||
}
|
||||
static std::string formatMessage(const std::string &message) { return message; }
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -12,7 +12,9 @@
|
||||
#include "XNBaseFrameObject.h"
|
||||
|
||||
class XNModelObject;
|
||||
class XNModelManagerPrivate;
|
||||
XNCLASS_PTR_DECLARE(XNModelObject)
|
||||
|
||||
struct XNModelManagerPrivate;
|
||||
|
||||
/**
|
||||
* @brief 模型管理器类
|
||||
@ -20,18 +22,14 @@ class XNModelManagerPrivate;
|
||||
*/
|
||||
class XNModelManager : public XNBaseFrameObject
|
||||
{
|
||||
/**
|
||||
* @brief 使用禁止复制类宏定义自身禁止复制
|
||||
*/
|
||||
Q_OBJECT
|
||||
Q_DECLARE_PRIVATE(XNModelManager)
|
||||
Q_DISABLE_COPY(XNModelManager)
|
||||
XN_METATYPE(XNModelManager, XNBaseFrameObject)
|
||||
XN_DECLARE_PRIVATE(XNModelManager)
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief 模型管理器类默认构造函数
|
||||
*/
|
||||
explicit XNModelManager(QObject *parent = nullptr);
|
||||
XNModelManager();
|
||||
|
||||
/**
|
||||
* @brief 模型管理器类默认析构函数
|
||||
@ -44,20 +42,20 @@ protected:
|
||||
* @param p:私有结构体指针
|
||||
* @details 子类构造时调用此构造函数,传入子类的私有结构体指针
|
||||
*/
|
||||
XNModelManager(XNModelManagerPrivate &dd, QObject *parent = nullptr);
|
||||
XNModelManager(PrivateType *p);
|
||||
|
||||
public slots:
|
||||
public:
|
||||
/**
|
||||
* @brief 系统开始运行前的最后准备工作
|
||||
* @details 系统运行前模型管理器做最后处理的接口
|
||||
*/
|
||||
virtual void OnPrepareForExecute() override;
|
||||
virtual bool PrepareForExecute() override;
|
||||
|
||||
/**
|
||||
* @brief 初始化模型管理器
|
||||
* @details 模型管理器的初始化接口
|
||||
*/
|
||||
virtual void OnInitialize() override;
|
||||
virtual bool Initialize() override;
|
||||
|
||||
/**
|
||||
* @brief 加载模型
|
||||
@ -65,31 +63,23 @@ public slots:
|
||||
* @param className: QString类型,模型类名
|
||||
* @details 加载模型
|
||||
*/
|
||||
void OnLoadModel(const QString &modelPath, const QString &className);
|
||||
void LoadModel(const std::string &modelPath, const std::string &className, uint32_t initialType,
|
||||
uint32_t threadID);
|
||||
|
||||
/**
|
||||
* @brief 设置仿真系统运行基频
|
||||
* @param dBaseFreq: double类型,频率值,单位Hz
|
||||
* @details 仿真系统所有线程以此基频的 1 或 1/2 或 1/4 或 1/8 或 1/16 或 1/32 倍运行
|
||||
*/
|
||||
void OnSetBaseFreq(const double &dBaseFreq);
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief 注册模型信息
|
||||
* @return UINT32: 模型的全局唯一ID
|
||||
* @details 模型通过此接口注册自身,并获取自身全局唯一ID
|
||||
*/
|
||||
quint32 RegisterModel();
|
||||
uint32_t RegisterModel();
|
||||
|
||||
/**
|
||||
* @brief 获取模型指针
|
||||
* @param modelID: UINT32类型,模型全局唯一ID
|
||||
* @return XNModelObjectPtr: 模型基类指针
|
||||
*/
|
||||
XNModelObject *GetModel(quint32 modelID);
|
||||
XNModelObjectPtr GetModel(uint32_t modelID);
|
||||
|
||||
public slots:
|
||||
/**
|
||||
* @brief 注册模型函数
|
||||
* @param ModelID: UINT32类型,模型全局唯一ID
|
||||
@ -98,22 +88,6 @@ public slots:
|
||||
* @param RunPos: UINT32类型,提交的函数运行节点号,<2^(freqGroup)
|
||||
* @param RunPriorty: UINT32类型,提交的函数运行优先级,99~0,优先级数值越大,优先级越高
|
||||
*/
|
||||
void OnRegisterFunction(quint32 id, XNCallBack fun, quint32 freqGroup, quint32 RunPos,
|
||||
quint32 RunPriorty);
|
||||
|
||||
signals:
|
||||
/**
|
||||
* @brief 注册函数信号
|
||||
* @param id: 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(quint32 id, XNCallBack fun, quint32 freqGroup, quint32 RunPos,
|
||||
quint32 RunPriorty);
|
||||
|
||||
void InitializeSuccess();
|
||||
|
||||
void PrepareForExecuteSuccess();
|
||||
void RegisterFunction(uint32_t id, XNCallBack fun, uint32_t threadID, uint32_t freqGroup,
|
||||
uint32_t RunPos, uint32_t RunPriorty);
|
||||
};
|
@ -1,25 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include "XNBaseFrameObject_p.h"
|
||||
#include <QVector>
|
||||
#include <QHash>
|
||||
|
||||
class XNModelManagerPrivate : public XNBaseFrameObjectPrivate
|
||||
{
|
||||
public:
|
||||
Q_DECLARE_PUBLIC(XNModelManager)
|
||||
|
||||
explicit XNModelManagerPrivate(XNModelManager *q) : XNBaseFrameObjectPrivate(q) {}
|
||||
|
||||
struct XNModelManagerPrivate : public XNBaseFrameObjectPrivate {
|
||||
XNFrameworkPtr framework;
|
||||
/**
|
||||
* @brief 模型ID库
|
||||
* @details 所有模型已用ID的存储库
|
||||
*/
|
||||
QVector<bool> ModelIDAssigned;
|
||||
|
||||
std::vector<bool> ModelIDAssigned;
|
||||
/**
|
||||
* @brief 仿真系统运行基频
|
||||
* @details 仿真系统所有线程以此基频的 1 或 1/2 或 1/4 或 1/8 或 1/16 或 1/32 倍运行
|
||||
* @brief 模型ID与模型指针的映射表
|
||||
* @details 所有模型ID与模型指针的映射表
|
||||
*/
|
||||
double dBaseFreq;
|
||||
std::map<uint32_t, XNModelObjectPtr> ModelMap;
|
||||
};
|
||||
|
@ -12,7 +12,7 @@
|
||||
#include "XNObject.h"
|
||||
#include "XNEventManager.h"
|
||||
|
||||
class XNModelObjectPrivate;
|
||||
struct XNModelObjectPrivate;
|
||||
|
||||
/**
|
||||
* @brief 模型基类
|
||||
@ -20,22 +20,14 @@ class XNModelObjectPrivate;
|
||||
*/
|
||||
class XNModelObject : public XNObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY(XNModelObject)
|
||||
Q_DECLARE_PRIVATE(XNModelObject)
|
||||
|
||||
Q_PROPERTY(QString description READ GetDescription WRITE SetDescription)
|
||||
Q_PROPERTY(QString author READ GetAuthor WRITE SetAuthor)
|
||||
Q_PROPERTY(QString xmlPath READ GetXmlPath WRITE SetXmlPath)
|
||||
Q_PROPERTY(QDateTime createTime READ GetCreateTime WRITE SetCreateTime)
|
||||
Q_PROPERTY(QDateTime changeTime READ GetChangeTime WRITE SetChangeTime)
|
||||
Q_PROPERTY(QString version READ GetVersion WRITE SetVersion)
|
||||
XN_METATYPE(XNModelObject, XNObject)
|
||||
XN_DECLARE_PRIVATE(XNModelObject)
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief 模型基类默认构造函数
|
||||
*/
|
||||
XNModelObject(QObject *parent = nullptr);
|
||||
XNModelObject();
|
||||
|
||||
/**
|
||||
* @brief 模型基类默认析构函数
|
||||
@ -45,89 +37,89 @@ public:
|
||||
protected:
|
||||
/**
|
||||
* @brief 模型基类带参构造函数
|
||||
* @param dd:XNModelObjectPrivate类型,私有结构体指针
|
||||
* @param parent:QObject类型,父对象指针
|
||||
* @param p:XNModelObjectPrivate类型,私有结构体指针
|
||||
* @details 子类构造时调用此构造函数,传入子类的私有结构体指针
|
||||
*/
|
||||
XNModelObject(XNModelObjectPrivate &dd, QObject *parent = nullptr);
|
||||
XNModelObject(PrivateType *p);
|
||||
|
||||
public:
|
||||
void SetFramework(XNFrameworkPtr framework);
|
||||
|
||||
protected:
|
||||
XNFrameworkPtr GetFramework() const;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief 获取模型描述
|
||||
* @return const QString&:模型描述
|
||||
*/
|
||||
const QString &GetDescription();
|
||||
const std::string &GetDescription();
|
||||
|
||||
/**
|
||||
* @brief 设置模型描述
|
||||
* @param sDescription:QString类型,模型描述
|
||||
*/
|
||||
void SetDescription(const QString &sDescription);
|
||||
void SetDescription(const std::string &sDescription);
|
||||
|
||||
/**
|
||||
* @brief 获取作者
|
||||
* @return const QString&: 作者
|
||||
*/
|
||||
const QString &GetAuthor();
|
||||
const std::string &GetAuthor();
|
||||
|
||||
/**
|
||||
* @brief 设置作者
|
||||
* @param sAuthor: QString类型,作者
|
||||
*/
|
||||
void SetAuthor(const QString &sAuthor);
|
||||
void SetAuthor(const std::string &sAuthor);
|
||||
|
||||
/**
|
||||
* @brief 获取模型配置文件路径
|
||||
* @return const QString&: 模型配置文件路径
|
||||
*/
|
||||
const QString &GetXmlPath();
|
||||
const std::string &GetXmlPath();
|
||||
|
||||
/**
|
||||
* @brief 设置模型配置文件路径
|
||||
* @param sXmlPath:QString类型,模型配置文件路径
|
||||
*/
|
||||
void SetXmlPath(const QString &sXmlPath);
|
||||
void SetXmlPath(const std::string &sXmlPath);
|
||||
|
||||
/**
|
||||
* @brief 获取模型创建时间
|
||||
* @return const QDateTime&:模型创建时间
|
||||
* @return const XNTimePoint&:模型创建时间
|
||||
*/
|
||||
const QDateTime &GetCreateTime();
|
||||
const XNTimePoint &GetCreateTime();
|
||||
|
||||
/**
|
||||
* @brief 设置模型创建时间
|
||||
* @param cTime: QDateTime类型,模型创建时间
|
||||
* @param cTime: XNTimePoint类型,模型创建时间
|
||||
*/
|
||||
void SetCreateTime(const QDateTime &cTime);
|
||||
void SetCreateTime(const XNTimePoint &cTime);
|
||||
|
||||
/**
|
||||
* @brief 获取模型修改时间
|
||||
* @return const QDateTime&:模型修改时间
|
||||
* @return const XNTimePoint&:模型修改时间
|
||||
*/
|
||||
const QDateTime &GetChangeTime();
|
||||
const XNTimePoint &GetChangeTime();
|
||||
|
||||
/**
|
||||
* @brief 设置模型修改时间
|
||||
* @param cTime: QDateTime类型,模型修改时间
|
||||
* @param cTime: XNTimePoint类型,模型修改时间
|
||||
*/
|
||||
void SetChangeTime(const QDateTime &cTime);
|
||||
void SetChangeTime(const XNTimePoint &cTime);
|
||||
|
||||
/**
|
||||
* @brief 获取模型版本号
|
||||
* @return const XNString&: 模型版本号
|
||||
*/
|
||||
const QString &GetVersion();
|
||||
/**
|
||||
* @brief 设置模型版本号
|
||||
* @param sVersion: QString类型,模型版本号
|
||||
*/
|
||||
void SetVersion(const QString &sVersion);
|
||||
const std::string &GetVersion();
|
||||
|
||||
/**
|
||||
* @brief 设置仿真系统运行基频
|
||||
* @param dBaseFreq: double类型,频率值,单位Hz
|
||||
* @brief 设置模型版本号
|
||||
* @param sVersion: std::string类型,模型版本号
|
||||
*/
|
||||
void SetBaseFreq(const double &dBaseFreq);
|
||||
void SetVersion(const std::string &sVersion);
|
||||
|
||||
/**
|
||||
* @brief 单步执行函数
|
||||
@ -142,8 +134,8 @@ public:
|
||||
* @param async: 是否异步处理
|
||||
* @return: 返回处理器ID,失败返回-1
|
||||
*/
|
||||
int RegisterEventHandler(const QString &eventName,
|
||||
std::function<void(const QVariant &)> callback, bool async = false,
|
||||
int RegisterEventHandler(const std::string &eventName, XNEventCallback callback,
|
||||
bool async = false,
|
||||
XNEvent::Priority priority = XNEvent::Priority::Normal);
|
||||
|
||||
/**
|
||||
@ -152,7 +144,7 @@ public:
|
||||
* @param eventData: 事件携带的数据
|
||||
* @param forceAsync: 强制异步处理
|
||||
*/
|
||||
void TriggerEvent(const QString &eventName, const QVariant &eventData = QVariant(),
|
||||
void TriggerEvent(const std::string &eventName, const std::any &eventData = std::any(),
|
||||
bool forceAsync = false,
|
||||
XNEvent::Priority priority = XNEvent::Priority::Normal);
|
||||
|
||||
@ -162,8 +154,7 @@ public:
|
||||
* @param callback: 事件处理回调函数
|
||||
* @return: 返回处理器ID,失败返回-1
|
||||
*/
|
||||
int RegisterRTEventHandler(const QString &eventName,
|
||||
std::function<void(const QVariant &)> callback)
|
||||
int RegisterRTEventHandler(const std::string &eventName, XNEventCallback callback)
|
||||
{
|
||||
return RegisterEventHandler(eventName, callback, true, XNEvent::Priority::RealTime);
|
||||
}
|
||||
@ -173,37 +164,23 @@ public:
|
||||
* @param eventName: 要触发的事件名称
|
||||
* @param eventData: 事件携带的数据
|
||||
*/
|
||||
void TriggerRTEvent(const QString &eventName, const QVariant &eventData = QVariant())
|
||||
void TriggerRTEvent(const std::string &eventName, const std::any &eventData = std::any())
|
||||
{
|
||||
TriggerEvent(eventName, eventData, true, XNEvent::Priority::RealTime);
|
||||
}
|
||||
|
||||
signals:
|
||||
/**
|
||||
* @brief 注册周期性执行的函数
|
||||
* @param id: quint32类型,模型ID
|
||||
* @param fun: QFunctionPointer类型,需要提交的函数的包装
|
||||
* @param freqGroup:UINT32类型,提交的函数运行频率组,0为基频,1为半频,2为1/4频,3为1/8频,4为1/16频,5为1/32频
|
||||
* @param RunPos: UINT32类型,提交的函数运行节点号,<2^(freqGroup)
|
||||
* @param RunPriorty:INT32类型,提交的函数运行优先级,99~0,优先级数值越大,优先级越高
|
||||
* @details 向线程管理器添加要周期性执行的函数
|
||||
*/
|
||||
void RegisterFunction(quint32 id, XNCallBack fun, quint32 freqGroup, quint32 RunPos,
|
||||
quint32 RunPriorty);
|
||||
|
||||
public slots:
|
||||
/**
|
||||
* @brief 初始化函数
|
||||
* @details
|
||||
* 模型的初始化函数接口,子类继承时要调用父类初始化接口,或在此函数中使用AddMyFunction方法注册需要被线程调用的函数
|
||||
*/
|
||||
virtual void OnInitialize();
|
||||
virtual void Initialize(uint32_t initialType, uint32_t threadID);
|
||||
|
||||
/**
|
||||
* @brief 仿真系统运行前做最后处理
|
||||
* @details 系统运行前模型做最后处理的接口
|
||||
*/
|
||||
virtual void OnPrepareForExecute();
|
||||
virtual void PrepareForExecute();
|
||||
|
||||
public:
|
||||
virtual void RegisterDDSParticipant();
|
||||
@ -218,11 +195,11 @@ public:
|
||||
{ \
|
||||
XNModelObject::RegisterDDSParticipant(); \
|
||||
Q_D(class); \
|
||||
XNModelManager *modelManager = qobject_cast<XNModelManager *>(parent()); \
|
||||
if (modelManager == nullptr) \
|
||||
auto framework = GetFramework(); \
|
||||
if (!framework) \
|
||||
return; \
|
||||
XNDDSManager *ddsManager = modelManager->parent()->findChild<XNDDSManager *>(); \
|
||||
if (ddsManager == nullptr) \
|
||||
XNDDSManagerPtr ddsManager = framework->GetDDSManager(); \
|
||||
if (!ddsManager) \
|
||||
return; \
|
||||
quint32 MyID = getUniqueId();
|
||||
|
||||
@ -234,3 +211,10 @@ public:
|
||||
#topic, MyID, std::bind(fun, this, std::placeholders::_1));
|
||||
|
||||
#define XN_REGISTER_PARTICIPANT_END(class) }
|
||||
|
||||
#define XN_MODEL_INITIALIZE(ClassName) \
|
||||
extern "C" XNModelObjectPtr Initial##ClassName() \
|
||||
{ \
|
||||
ClassNamePtr obj = std::make_shared<ClassName>(); \
|
||||
return obj; \
|
||||
}
|
||||
|
@ -10,62 +10,49 @@
|
||||
*/
|
||||
#pragma once
|
||||
#include "XNObject_p.h"
|
||||
#include <QLibrary>
|
||||
#include <QFunctionPointer>
|
||||
#include <QHash>
|
||||
#include <fastdds/dds/publisher/DataWriter.hpp>
|
||||
|
||||
/**
|
||||
* @brief 模型基类私有结构体
|
||||
*/
|
||||
class XNModelObjectPrivate : public XNObjectPrivate
|
||||
{
|
||||
public:
|
||||
Q_DECLARE_PUBLIC(XNModelObject)
|
||||
|
||||
/**
|
||||
* @brief 构造函数
|
||||
* @param q 模型基类指针
|
||||
*/
|
||||
explicit XNModelObjectPrivate(XNModelObject *q) : XNObjectPrivate(q) {}
|
||||
|
||||
struct XNModelObjectPrivate : public XNObjectPrivate {
|
||||
XNFrameworkPtr _framework;
|
||||
/**
|
||||
* @brief 模型描述
|
||||
*/
|
||||
QString _sDescription;
|
||||
std::string _sDescription;
|
||||
/**
|
||||
* @brief 模型作者
|
||||
*/
|
||||
QString _sAuthor;
|
||||
std::string _sAuthor;
|
||||
/**
|
||||
* @brief 模型配置文件路径
|
||||
*/
|
||||
QString _sXmlPath;
|
||||
std::string _sXmlPath;
|
||||
/**
|
||||
* @brief 数据包模型动态库路径
|
||||
*/
|
||||
QString _sLibPath;
|
||||
std::string _sLibPath;
|
||||
/**
|
||||
* @brief 模型创建时间
|
||||
*/
|
||||
QDateTime _cCreatTime;
|
||||
XNTimePoint _cCreatTime;
|
||||
/**
|
||||
* @brief 模型修改时间
|
||||
*/
|
||||
QDateTime _cChangeTime;
|
||||
XNTimePoint _cChangeTime;
|
||||
/**
|
||||
* @brief 模型版本号
|
||||
*/
|
||||
QString _sVersion;
|
||||
std::string _sVersion;
|
||||
/**
|
||||
* @brief 数据包模型动态库句柄
|
||||
*/
|
||||
QLibrary *_dynamicLib = nullptr;
|
||||
void *_dynamicLib = nullptr;
|
||||
|
||||
/**
|
||||
* @brief 发布者信息
|
||||
*/
|
||||
QHash<QString, FAST_DDS_MACRO::DataWriter *> _dataWriters;
|
||||
std::unordered_map<std::string, FAST_DDS_MACRO::DataWriter *> _dataWriters;
|
||||
|
||||
/**
|
||||
* @brief 模型运行时间
|
||||
@ -75,25 +62,30 @@ public:
|
||||
/**
|
||||
* @brief 模型运行次数
|
||||
*/
|
||||
quint64 _runCnt;
|
||||
uint64_t _runCnt;
|
||||
|
||||
/**
|
||||
* @brief 模型运行频率
|
||||
*/
|
||||
quint32 _runFreq;
|
||||
uint32_t _runFreq;
|
||||
|
||||
/**
|
||||
* @brief 模型运行节点
|
||||
*/
|
||||
quint32 _runNode;
|
||||
uint32_t _runNode;
|
||||
|
||||
/**
|
||||
* @brief 模型运行优先级
|
||||
*/
|
||||
quint32 _runPriority;
|
||||
uint32_t _runPriority;
|
||||
|
||||
/**
|
||||
* @brief 模型设置频率
|
||||
*/
|
||||
double _setFreq;
|
||||
|
||||
/**
|
||||
* @brief 模型线程ID
|
||||
*/
|
||||
uint32_t _threadID;
|
||||
};
|
||||
|
@ -10,75 +10,83 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <QVariant>
|
||||
#include <QtXml/QDomDocument>
|
||||
|
||||
#include "XNCore_global.h"
|
||||
#include "XNLogger.h"
|
||||
|
||||
class XNObjectPrivate;
|
||||
struct XNObjectPrivate;
|
||||
|
||||
/**
|
||||
* @brief 基础对象类
|
||||
*/
|
||||
class XNCORE_EXPORT XNObject : public QObject
|
||||
class XNCORE_EXPORT XNObject : public std::enable_shared_from_this<XNObject>
|
||||
{
|
||||
XN_METATYPE_P(XNObject)
|
||||
XN_NOCOPYABLE(XNObject)
|
||||
protected:
|
||||
using PrivateType = XNObjectPrivate;
|
||||
/**
|
||||
* @brief 宏定义,用于支持Qt的元对象系统
|
||||
* @brief 私有数据成员
|
||||
*/
|
||||
Q_OBJECT
|
||||
|
||||
/**
|
||||
* @brief 宏定义,用于禁用拷贝构造函数
|
||||
*/
|
||||
Q_DISABLE_COPY(XNObject)
|
||||
|
||||
/**
|
||||
* @brief 宏定义,用于声明私有数据成员
|
||||
*/
|
||||
Q_DECLARE_PRIVATE(XNObject)
|
||||
|
||||
/**
|
||||
* @brief 宏定义,用于声明属性uniqueId
|
||||
*/
|
||||
Q_PROPERTY(quint32 UniqueId READ getUniqueId WRITE setUniqueId)
|
||||
PrivateType *_Private_Ptr;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief 构造函数
|
||||
* @param parent 父对象
|
||||
*/
|
||||
explicit XNObject(QObject *parent = nullptr);
|
||||
XNObject();
|
||||
|
||||
/**
|
||||
* @brief 析构函数
|
||||
*/
|
||||
virtual ~XNObject();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief 构造函数
|
||||
* @param p 私有数据成员
|
||||
*/
|
||||
XNObject(PrivateType *p);
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief 获取唯一ID
|
||||
* @return 唯一ID
|
||||
*/
|
||||
quint32 getUniqueId();
|
||||
uint32_t GetUniqueId();
|
||||
|
||||
/**
|
||||
* @brief 设置唯一ID
|
||||
* @param uniqueId 唯一ID
|
||||
*/
|
||||
void setUniqueId(const quint32 &uniqueId);
|
||||
void SetUniqueId(const uint32_t &uniqueId);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief 构造函数
|
||||
* @param dd 私有数据成员
|
||||
* @param parent 父对象
|
||||
* @brief 获取对象名称
|
||||
* @return 对象名称
|
||||
*/
|
||||
XNObject(XNObjectPrivate &dd, QObject *parent = nullptr);
|
||||
const std::string &GetObjectName();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief 私有数据成员
|
||||
* @brief 设置对象名称
|
||||
* @param name 对象名称
|
||||
*/
|
||||
XNObjectPrivate *d_ptr;
|
||||
void SetObjectName(const std::string &name);
|
||||
};
|
||||
|
||||
class XNFramework;
|
||||
class XNDDSManager;
|
||||
class XNEventManager;
|
||||
class XNModelManager;
|
||||
class XNScenarioManager;
|
||||
class XNServiceManager;
|
||||
class XNThreadManager;
|
||||
class XNTimeManager;
|
||||
|
||||
XNCLASS_PTR_DECLARE(XNFramework)
|
||||
XNCLASS_PTR_DECLARE(XNDDSManager)
|
||||
XNCLASS_PTR_DECLARE(XNEventManager)
|
||||
XNCLASS_PTR_DECLARE(XNModelManager)
|
||||
XNCLASS_PTR_DECLARE(XNScenarioManager)
|
||||
XNCLASS_PTR_DECLARE(XNServiceManager)
|
||||
XNCLASS_PTR_DECLARE(XNThreadManager)
|
||||
XNCLASS_PTR_DECLARE(XNTimeManager)
|
@ -15,28 +15,20 @@
|
||||
/**
|
||||
* @brief 基础对象类的私有数据成员
|
||||
*/
|
||||
class XNObjectPrivate
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief 宏定义,用于声明公有数据成员
|
||||
*/
|
||||
Q_DECLARE_PUBLIC(XNObject)
|
||||
|
||||
/**
|
||||
* @brief 构造函数
|
||||
* @param q 基础对象类指针
|
||||
*/
|
||||
explicit XNObjectPrivate(XNObject *q) : q_ptr(q) {}
|
||||
|
||||
struct XNObjectPrivate {
|
||||
virtual ~XNObjectPrivate();
|
||||
/**
|
||||
* @brief 基础对象类指针
|
||||
*/
|
||||
XNObject *q_ptr;
|
||||
XNObject *_Public_Ptr;
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief 唯一ID
|
||||
*/
|
||||
quint32 uUniqueID;
|
||||
uint32_t uUniqueID;
|
||||
|
||||
/**
|
||||
* @brief 对象名称
|
||||
*/
|
||||
std::string sObjectName;
|
||||
};
|
||||
|
@ -11,7 +11,7 @@
|
||||
#pragma once
|
||||
#include "XNBaseFrameObject.h"
|
||||
|
||||
class XNScenarioManagerPrivate;
|
||||
struct XNScenarioManagerPrivate;
|
||||
|
||||
/**
|
||||
* @brief 运行环境描述管理器类
|
||||
@ -19,14 +19,13 @@ class XNScenarioManagerPrivate;
|
||||
*/
|
||||
class XNScenarioManager : public XNBaseFrameObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DECLARE_PRIVATE(XNScenarioManager)
|
||||
Q_DISABLE_COPY(XNScenarioManager)
|
||||
XN_METATYPE(XNScenarioManager, XNBaseFrameObject)
|
||||
XN_DECLARE_PRIVATE(XNScenarioManager)
|
||||
public:
|
||||
/**
|
||||
* @brief 运行环境描述管理器类默认构造函数
|
||||
*/
|
||||
explicit XNScenarioManager(QObject *parent = nullptr);
|
||||
XNScenarioManager();
|
||||
|
||||
/**
|
||||
* @brief 运行环境描述管理器类析构函数
|
||||
@ -39,110 +38,39 @@ protected:
|
||||
* @param p:私有结构体指针
|
||||
* @details 子类构造时调用此构造函数,传入子类的私有结构体指针
|
||||
*/
|
||||
XNScenarioManager(XNScenarioManagerPrivate &dd, QObject *parent = nullptr);
|
||||
XNScenarioManager(PrivateType *p);
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief 获取运行环境名称
|
||||
* @return const XNString&: 运行环境名称
|
||||
*/
|
||||
const QString &GetSimName();
|
||||
const std::string &GetSimName();
|
||||
|
||||
/**
|
||||
* @brief 设置运行环境名称
|
||||
* @param simName: XNString类型,运行环境名称
|
||||
*/
|
||||
void SetSimName(QString &simName);
|
||||
void SetSimName(const std::string &simName);
|
||||
|
||||
/**
|
||||
* @brief 获取运行环境开始时间
|
||||
* @return const XNTime&: 运行环境开始时间
|
||||
*/
|
||||
const QDateTime &GetSimStartTime();
|
||||
|
||||
/**
|
||||
* @brief 设置运行环境开始时间
|
||||
* @param startTime: QDateTime类型,运行环境开始时间
|
||||
*/
|
||||
void SetSimStartTime(QDateTime &startTime);
|
||||
|
||||
signals:
|
||||
/**
|
||||
* @brief 信号,用于通知线程管理器添加线程
|
||||
*/
|
||||
void AddThreadPool(QString name, FreqLevel freq, quint32 priority, quint32 CPUAff,
|
||||
double RunInter);
|
||||
|
||||
/**
|
||||
* @brief 信号,用于通知模型管理器加载模型
|
||||
*/
|
||||
void LoadModel(const QString &modelPath, const QString &className);
|
||||
|
||||
/**
|
||||
* @brief 信号,用于通知服务管理器加载服务
|
||||
*/
|
||||
void LoadService(const QString &servicePath, const QString &className);
|
||||
|
||||
/**
|
||||
* @brief 信号,用于通知框架设置工作路径
|
||||
*/
|
||||
void SetWorkPath(const QString &workPath);
|
||||
|
||||
/**
|
||||
* @brief 信号,用于通知框架设置模型库路径
|
||||
*/
|
||||
void SetModelPath(const QString &modelPath);
|
||||
|
||||
/**
|
||||
* @brief 信号,用于通知框架设置服务库路径
|
||||
*/
|
||||
void SetServicePath(const QString &servicePath);
|
||||
|
||||
/**
|
||||
* @brief 信号,用于通知框架设置CPU亲和性
|
||||
*/
|
||||
void SetCpuAffinity(quint32 cpuAffinity);
|
||||
|
||||
/**
|
||||
* @brief 设置基础运行频率
|
||||
* @param freq: 基础运行频率,单位Hz
|
||||
*/
|
||||
void SetBaseFreq(const double &freq);
|
||||
|
||||
/**
|
||||
* @brief 设置DDS域ID
|
||||
* @param domainID: DDS域ID
|
||||
*/
|
||||
void SetDomainID(quint32 domainID);
|
||||
|
||||
/**
|
||||
* @brief 解析配置文件成功
|
||||
*/
|
||||
void AnalyzeScenarioXmlSuccess();
|
||||
|
||||
/**
|
||||
* @brief 解析配置文件失败
|
||||
*/
|
||||
void AnalyzeScenarioXmlFailed();
|
||||
|
||||
public slots:
|
||||
public:
|
||||
/**
|
||||
* @brief 初始化运行环境描述管理器
|
||||
* @return true: 初始化成功
|
||||
* @return false: 初始化失败
|
||||
* @details 运行环境描述管理器的初始化接口函数
|
||||
*/
|
||||
virtual void OnInitialize() override;
|
||||
virtual bool Initialize() override;
|
||||
|
||||
/**
|
||||
* @brief 仿真运行前最后处理
|
||||
* @note 运行环境描述管理器在系统运行开始前的准备工作
|
||||
*/
|
||||
virtual void OnPrepareForExecute() override;
|
||||
virtual bool PrepareForExecute() override;
|
||||
|
||||
/**
|
||||
* @brief 运行环境配置文件解析
|
||||
* @param XmlPath: QString类型,运行环境配置文件解析路径
|
||||
* @param XmlPath: std::string类型,运行环境配置文件解析路径
|
||||
*/
|
||||
virtual void AnalysisScenarioXml(const QString &XmlPath);
|
||||
virtual bool AnalysisScenarioXml(const std::string &XmlPath);
|
||||
};
|
||||
|
@ -14,19 +14,9 @@
|
||||
/**
|
||||
* @brief 运行环境描述管理器类私有结构体
|
||||
*/
|
||||
class XNScenarioManagerPrivate : public XNBaseFrameObjectPrivate
|
||||
{
|
||||
|
||||
public:
|
||||
Q_DECLARE_PUBLIC(XNScenarioManager)
|
||||
explicit XNScenarioManagerPrivate(XNScenarioManager *q) : XNBaseFrameObjectPrivate(q) {}
|
||||
struct XNScenarioManagerPrivate : public XNBaseFrameObjectPrivate {
|
||||
/**
|
||||
* @brief 运行环境名称
|
||||
*/
|
||||
QString _ScenarioName;
|
||||
|
||||
/**
|
||||
* @brief 运行环境开始时间
|
||||
*/
|
||||
QDateTime _SimStartTime;
|
||||
std::string _ScenarioName;
|
||||
};
|
||||
|
@ -3,26 +3,35 @@
|
||||
|
||||
// 添加前向声明
|
||||
class XNServiceObject;
|
||||
class XNServiceManagerPrivate;
|
||||
XNCLASS_PTR_DECLARE(XNServiceObject)
|
||||
|
||||
struct XNServiceManagerPrivate;
|
||||
|
||||
class XNServiceManager : public XNBaseFrameObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DECLARE_PRIVATE(XNServiceManager)
|
||||
Q_DISABLE_COPY(XNServiceManager)
|
||||
XN_METATYPE(XNServiceManager, XNBaseFrameObject)
|
||||
XN_DECLARE_PRIVATE(XNServiceManager)
|
||||
public:
|
||||
explicit XNServiceManager(QObject *parent = nullptr);
|
||||
/**
|
||||
* @brief 服务管理器类默认构造函数
|
||||
*/
|
||||
XNServiceManager();
|
||||
|
||||
/**
|
||||
* @brief 服务管理器类析构函数
|
||||
*/
|
||||
virtual ~XNServiceManager();
|
||||
|
||||
protected:
|
||||
XNServiceManager(XNServiceManagerPrivate &dd, QObject *parent = nullptr);
|
||||
|
||||
public slots:
|
||||
virtual void OnInitialize() override;
|
||||
virtual void OnPrepareForExecute() override;
|
||||
void OnLoadService(const QString &servicePath, const QString &serviceName);
|
||||
XNServiceManager(PrivateType *p);
|
||||
|
||||
public:
|
||||
XNServiceObject *GetService(quint32 serviceID);
|
||||
quint32 RegisterService();
|
||||
virtual bool Initialize() override;
|
||||
virtual bool PrepareForExecute() override;
|
||||
void LoadService(const std::string &servicePath, const std::string &serviceName,
|
||||
uint32_t initialType);
|
||||
|
||||
public:
|
||||
XNServiceObjectPtr GetService(uint32_t serviceID);
|
||||
uint32_t RegisterService();
|
||||
};
|
||||
|
@ -1,16 +1,16 @@
|
||||
#pragma once
|
||||
#include "XNBaseFrameObject_p.h"
|
||||
|
||||
class XNServiceManagerPrivate : public XNBaseFrameObjectPrivate
|
||||
{
|
||||
public:
|
||||
Q_DECLARE_PUBLIC(XNServiceManager)
|
||||
|
||||
explicit XNServiceManagerPrivate(XNServiceManager *q) : XNBaseFrameObjectPrivate(q) {}
|
||||
|
||||
struct XNServiceManagerPrivate : public XNBaseFrameObjectPrivate {
|
||||
/**
|
||||
* @brief 服务ID库
|
||||
* @details 所有服务已用ID的存储库
|
||||
*/
|
||||
QVector<bool> ServiceIDAssigned;
|
||||
std::vector<bool> ServiceIDAssigned;
|
||||
|
||||
/**
|
||||
* @brief 服务列表
|
||||
* @details 所有服务的存储库
|
||||
*/
|
||||
std::map<uint32_t, XNServiceObjectPtr> ServiceList;
|
||||
};
|
@ -3,68 +3,59 @@
|
||||
#include "XNObject.h"
|
||||
#include "XNServiceManager.h"
|
||||
#include "XNEventManager.h"
|
||||
|
||||
class XNServiceObjectPrivate;
|
||||
struct XNServiceObjectPrivate;
|
||||
|
||||
class XNServiceObject : public XNObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DECLARE_PRIVATE(XNServiceObject)
|
||||
Q_DISABLE_COPY(XNServiceObject)
|
||||
|
||||
Q_PROPERTY(QString description READ GetDescription WRITE SetDescription)
|
||||
Q_PROPERTY(QString author READ GetAuthor WRITE SetAuthor)
|
||||
Q_PROPERTY(QString xmlPath READ GetXmlPath WRITE SetXmlPath)
|
||||
Q_PROPERTY(QDateTime createTime READ GetCreateTime WRITE SetCreateTime)
|
||||
Q_PROPERTY(QDateTime changeTime READ GetChangeTime WRITE SetChangeTime)
|
||||
Q_PROPERTY(QString version READ GetVersion WRITE SetVersion)
|
||||
|
||||
XN_METATYPE(XNServiceObject, XNObject)
|
||||
XN_DECLARE_PRIVATE(XNServiceObject)
|
||||
public:
|
||||
explicit XNServiceObject(QObject *parent = nullptr);
|
||||
XNServiceObject();
|
||||
virtual ~XNServiceObject();
|
||||
|
||||
protected:
|
||||
explicit XNServiceObject(XNServiceObjectPrivate &dd, QObject *parent = nullptr);
|
||||
XNServiceObject(PrivateType *p);
|
||||
|
||||
public:
|
||||
const QString &GetVersion();
|
||||
const QString &GetDescription();
|
||||
const QString &GetAuthor();
|
||||
const QString &GetXmlPath();
|
||||
const QDateTime &GetCreateTime();
|
||||
const QDateTime &GetChangeTime();
|
||||
const std::string &GetVersion();
|
||||
const std::string &GetDescription();
|
||||
const std::string &GetAuthor();
|
||||
const std::string &GetXmlPath();
|
||||
const XNTimePoint &GetCreateTime();
|
||||
const XNTimePoint &GetChangeTime();
|
||||
|
||||
void SetVersion(const QString &version);
|
||||
void SetDescription(const QString &description);
|
||||
void SetAuthor(const QString &author);
|
||||
void SetXmlPath(const QString &xmlPath);
|
||||
void SetCreateTime(const QDateTime &createTime);
|
||||
void SetChangeTime(const QDateTime &changeTime);
|
||||
void SetVersion(const std::string &version);
|
||||
void SetDescription(const std::string &description);
|
||||
void SetAuthor(const std::string &author);
|
||||
void SetXmlPath(const std::string &xmlPath);
|
||||
void SetCreateTime(const XNTimePoint &createTime);
|
||||
void SetChangeTime(const XNTimePoint &changeTime);
|
||||
|
||||
int RegisterEventHandler(const QString &eventName,
|
||||
std::function<void(const QVariant &)> callback, bool async = false,
|
||||
int RegisterEventHandler(const std::string &eventName, XNEventCallback callback,
|
||||
bool async = false,
|
||||
XNEvent::Priority priority = XNEvent::Priority::Normal);
|
||||
|
||||
void TriggerEvent(const QString &eventName, const QVariant &eventData = QVariant(),
|
||||
void TriggerEvent(const std::string &eventName, const std::any &eventData = std::any(),
|
||||
bool forceAsync = false,
|
||||
XNEvent::Priority priority = XNEvent::Priority::Normal);
|
||||
|
||||
int RegisterRTEventHandler(const QString &eventName,
|
||||
std::function<void(const QVariant &)> callback);
|
||||
int RegisterRTEventHandler(const std::string &eventName, XNEventCallback callback);
|
||||
|
||||
void TriggerRTEvent(const QString &eventName, const QVariant &eventData = QVariant());
|
||||
void TriggerRTEvent(const std::string &eventName, const std::any &eventData = std::any());
|
||||
|
||||
public slots:
|
||||
virtual void OnInitialize();
|
||||
virtual void OnPrepareForExecute();
|
||||
virtual void Initialize(uint32_t initialType);
|
||||
virtual void PrepareForExecute();
|
||||
|
||||
public:
|
||||
virtual void RegisterDDSParticipant();
|
||||
|
||||
private:
|
||||
XNEventManager *GetEventManager() const;
|
||||
void SetFramework(XNFrameworkPtr framework);
|
||||
|
||||
protected:
|
||||
XNFrameworkPtr GetFramework() const;
|
||||
};
|
||||
|
||||
XNCLASS_PTR_DECLARE(XNServiceObject)
|
||||
|
||||
#define XN_DECLARE_DDS_SERVICE() \
|
||||
public: \
|
||||
virtual void RegisterDDSParticipant() override;
|
||||
@ -74,11 +65,11 @@ public:
|
||||
{ \
|
||||
XNServiceObject::RegisterDDSParticipant(); \
|
||||
Q_D(class); \
|
||||
XNServiceManager *serviceManager = qobject_cast<XNServiceManager *>(parent()); \
|
||||
if (serviceManager == nullptr) \
|
||||
auto framework = GetFramework(); \
|
||||
if (!framework) \
|
||||
return; \
|
||||
XNDDSManager *ddsManager = serviceManager->parent()->findChild<XNDDSManager *>(); \
|
||||
if (ddsManager == nullptr) \
|
||||
XNDDSManagerPtr ddsManager = framework->GetDDSManager(); \
|
||||
if (!ddsManager) \
|
||||
return; \
|
||||
quint32 MyID = getUniqueId();
|
||||
|
||||
@ -90,3 +81,10 @@ public:
|
||||
#topic, MyID, std::bind(fun, this, std::placeholders::_1));
|
||||
|
||||
#define XN_REGISTER_SERVICE_END_SERVICE(class) }
|
||||
|
||||
#define XN_SERVICE_INITIALIZE(ClassName) \
|
||||
extern "C" XNServiceObjectPtr Initial##ClassName() \
|
||||
{ \
|
||||
ClassNamePtr obj = std::make_shared<ClassName>(); \
|
||||
return obj; \
|
||||
}
|
||||
|
@ -1,21 +1,13 @@
|
||||
#pragma once
|
||||
#include "XNObject_p.h"
|
||||
#include <QHash>
|
||||
#include <fastdds/dds/publisher/DataWriter.hpp>
|
||||
#include "XNEventManager.h"
|
||||
class XNServiceObjectPrivate : public XNObjectPrivate
|
||||
{
|
||||
public:
|
||||
Q_DECLARE_PUBLIC(XNServiceObject)
|
||||
explicit XNServiceObjectPrivate(XNServiceObject *q) : XNObjectPrivate(q) {}
|
||||
|
||||
QString _sDescription;
|
||||
QString _sAuthor;
|
||||
QString _sXmlPath;
|
||||
QDateTime _cCreateTime;
|
||||
QDateTime _cChangeTime;
|
||||
QString _sVersion;
|
||||
QHash<QString, FAST_DDS_MACRO::DataWriter *> _dataWriters;
|
||||
|
||||
XNEventManager *pEventManager;
|
||||
struct XNServiceObjectPrivate : public XNObjectPrivate {
|
||||
std::string _sDescription;
|
||||
std::string _sAuthor;
|
||||
std::string _sXmlPath;
|
||||
XNTimePoint _cCreateTime;
|
||||
XNTimePoint _cChangeTime;
|
||||
std::string _sVersion;
|
||||
std::unordered_map<std::string, FAST_DDS_MACRO::DataWriter *> _dataWriters;
|
||||
XNFrameworkPtr pFramework;
|
||||
};
|
||||
|
@ -9,36 +9,43 @@
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
#include <QObject>
|
||||
#include <QThread>
|
||||
#include "XNCore_global.h"
|
||||
#include "XNObject.h"
|
||||
|
||||
class XNThreadPrivate;
|
||||
struct XNThreadPrivate;
|
||||
|
||||
/**
|
||||
* @brief 调度线程类
|
||||
* @details 调度所有模型提交的周期性执行函数
|
||||
*/
|
||||
class XNCORE_EXPORT XNThread : public QObject
|
||||
class XNCORE_EXPORT XNThread : public XNObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY(XNThread)
|
||||
Q_DECLARE_PRIVATE(XNThread)
|
||||
XN_METATYPE(XNThread, XNObject)
|
||||
XN_DECLARE_PRIVATE(XNThread)
|
||||
|
||||
public:
|
||||
explicit XNThread(QObject *parent = nullptr);
|
||||
XNThread(QObject *parent = nullptr, QString name = "", FreqLevel freq = FreqLevel::BaseFreq,
|
||||
quint32 priority = 99, quint32 CPUAff = 0, double RunInter = BASE_RUN_INTER);
|
||||
XNThread() = delete;
|
||||
|
||||
protected:
|
||||
XNThreadPrivate *d_ptr;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief 默认析构函数
|
||||
*/
|
||||
virtual ~XNThread();
|
||||
|
||||
explicit XNThread(std::string name = "", double freq = BASE_RUN_FREQ, uint32_t priority = 99,
|
||||
uint32_t CPUAff = 0);
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief 获取框架对象
|
||||
* @return 框架对象
|
||||
*/
|
||||
XNFrameworkPtr GetFramework();
|
||||
|
||||
/**
|
||||
* @brief 设置框架对象
|
||||
* @param framework 框架对象
|
||||
*/
|
||||
void SetFramework(XNFrameworkPtr framework);
|
||||
|
||||
/**
|
||||
* @brief 线程初始化
|
||||
* @return true: 初始化成功
|
||||
@ -46,26 +53,19 @@ public:
|
||||
*/
|
||||
bool Initialize();
|
||||
|
||||
public slots:
|
||||
/**
|
||||
* @brief 仿真控制
|
||||
* @param objectId: 对象ID
|
||||
* @param cmd: 仿真控制命令
|
||||
*/
|
||||
void OnSimControl(quint32 objectId, SimControlCmd cmd);
|
||||
void SimControl(uint32_t objectId, SimControlCmd cmd);
|
||||
|
||||
/**
|
||||
* @brief 设置线程运行的开始时间
|
||||
* @param simTime: timespec结构体类型,用于线程纳秒睡眠计算的开始时间
|
||||
* @details 通过设置统一的开始时间,使个线程能同步执行
|
||||
*/
|
||||
void OnSetStartTime(const timespec &simTime);
|
||||
|
||||
/**
|
||||
* @brief 设置线程运行间隔
|
||||
* @param dRunInter: double类型,线程运行间隔,单位纳秒
|
||||
*/
|
||||
void SetRunInter(const double &dRunInter);
|
||||
void SetStartTime(const timespec &simTime);
|
||||
|
||||
/**
|
||||
* @brief 加入线程
|
||||
@ -78,19 +78,73 @@ public slots:
|
||||
*/
|
||||
void Detach();
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief 获取线程ID
|
||||
* @return const quint32&: 线程ID
|
||||
*/
|
||||
const quint32 &GetThreadID();
|
||||
const uint32_t &GetThreadID();
|
||||
|
||||
/**
|
||||
* @brief 设置线程ID
|
||||
* @param threadID: 线程ID
|
||||
*/
|
||||
void SetThreadID(const quint32 &threadID);
|
||||
void SetThreadID(const uint32_t &threadID);
|
||||
|
||||
/**
|
||||
* @brief 获取运行状态
|
||||
* @return RunStatus: 运行状态枚举
|
||||
*/
|
||||
RunStatus GetRunStatus();
|
||||
|
||||
/**
|
||||
* @brief 获取线程运行频率
|
||||
* @return const double&:线程运行频率
|
||||
*/
|
||||
const double &GetRunFrequecy();
|
||||
|
||||
/**
|
||||
* @brief 设置线程运行频率
|
||||
* @param eRunFrequecy: double类型,线程运行频率
|
||||
*/
|
||||
void SetRunFrequecy(const double &dRunFrequecy);
|
||||
|
||||
/**
|
||||
* @brief 获取线程运行优先级
|
||||
* @return const UINT32&:运行优先级,0~99,99最高
|
||||
*/
|
||||
const uint32_t &GetRunPriority();
|
||||
|
||||
/**
|
||||
* @brief 设置线程运行优先级
|
||||
* @param uRunPriority: UINT32类型,运行优先级,0~99,99最高
|
||||
*/
|
||||
void SetRunPriority(const uint32_t &uRunPriority);
|
||||
|
||||
/**
|
||||
* @brief 设置线程CPU亲和性掩码
|
||||
* @return const UINT32&: CPU亲和性掩码,按位表示某CPU核是否使用,从低到高,0表示不使用,1表示使用。
|
||||
* 例如:0x00000003表示使用0,1号CPU
|
||||
*/
|
||||
const uint32_t &GetCPUAffinity();
|
||||
|
||||
/**
|
||||
* @brief 获取线程CPU亲和性掩码
|
||||
* @param uCPUAffinity: UINT32类型,CPU亲和性掩码,按位表示某CPU核是否使用,从低到高,0表示不使用,1表示使用。
|
||||
* 例如:0x00000003表示使用0,1号CPU
|
||||
*/
|
||||
void SetCPUAffinity(const uint32_t &uCPUAffinity);
|
||||
|
||||
/**
|
||||
* @brief 向线程添加周期性函数
|
||||
* @param fun:XNCallBack函数包装器类型,需要提交的函数的包装
|
||||
* @param freq:FreqLevel类型,提交的函数运行频率组
|
||||
* @param pos:UINT32类型,提交的函数运行节点号
|
||||
* @param priorty:UINT32类型,提交的函数运行优先级,99~0,优先级数值越大,优先级越高
|
||||
* @details 根据运行频率组和节点号向调度线程任务表中添加周期性函数
|
||||
*/
|
||||
void AddFunction(XNCallBack fun, FreqLevel freq, uint32_t pos, uint32_t priorty);
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief 控制线程开始
|
||||
* @return true: 线程启动成功
|
||||
@ -120,61 +174,6 @@ public:
|
||||
*/
|
||||
void Stop(bool force = false);
|
||||
|
||||
/**
|
||||
* @brief 获取运行状态
|
||||
* @return RunStatus: 运行状态枚举
|
||||
*/
|
||||
RunStatus GetRunStatus();
|
||||
|
||||
/**
|
||||
* @brief 获取线程运行频率族
|
||||
* @return const FreqLevel&:线程运行频率族
|
||||
*/
|
||||
const FreqLevel &GetRunFrequecy();
|
||||
|
||||
/**
|
||||
* @brief 设置线程运行频率族
|
||||
* @param eRunFrequecy: FreqLevel枚举类,线程运行频率族
|
||||
*/
|
||||
void SetRunFrequecy(const FreqLevel &eRunFrequecy);
|
||||
|
||||
/**
|
||||
* @brief 获取线程运行优先级
|
||||
* @return const UINT32&:运行优先级,0~99,99最高
|
||||
*/
|
||||
const quint32 &GetRunPriority();
|
||||
|
||||
/**
|
||||
* @brief 设置线程运行优先级
|
||||
* @param uRunPriority: UINT32类型,运行优先级,0~99,99最高
|
||||
*/
|
||||
void SetRunPriority(const quint32 &uRunPriority);
|
||||
|
||||
/**
|
||||
* @brief 设置线程CPU亲和性掩码
|
||||
* @return const UINT32&: CPU亲和性掩码,按位表示某CPU核是否使用,从低到高,0表示不使用,1表示使用。
|
||||
* 例如:0x00000003表示使用0,1号CPU
|
||||
*/
|
||||
const quint32 &GetCPUAffinity();
|
||||
|
||||
/**
|
||||
* @brief 获取线程CPU亲和性掩码
|
||||
* @param uCPUAffinity: UINT32类型,CPU亲和性掩码,按位表示某CPU核是否使用,从低到高,0表示不使用,1表示使用。
|
||||
* 例如:0x00000003表示使用0,1号CPU
|
||||
*/
|
||||
void SetCPUAffinity(const quint32 &uCPUAffinity);
|
||||
|
||||
/**
|
||||
* @brief 向线程添加周期性函数
|
||||
* @param fun:XNCallBack函数包装器类型,需要提交的函数的包装
|
||||
* @param freq:FreqLevel类型,提交的函数运行频率组
|
||||
* @param pos:UINT32类型,提交的函数运行节点号
|
||||
* @param priorty:UINT32类型,提交的函数运行优先级,99~0,优先级数值越大,优先级越高
|
||||
* @details 根据运行频率组和节点号向调度线程任务表中添加周期性函数
|
||||
*/
|
||||
void AddFunction(XNCallBack fun, FreqLevel freq, quint32 pos, quint32 priorty);
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief 执行线程CPU亲和性设置
|
||||
* @return true: 设置线程CPU亲和性成功
|
||||
@ -189,8 +188,10 @@ private:
|
||||
*/
|
||||
static void *ThreadFunction(void *args);
|
||||
|
||||
/**
|
||||
* @brief 初始化周期性函数表
|
||||
*/
|
||||
void InitialFunPool();
|
||||
// /**
|
||||
// * @brief 初始化周期性函数表
|
||||
// */
|
||||
//void InitialFunPool();
|
||||
};
|
||||
|
||||
XNCLASS_PTR_DECLARE(XNThread)
|
@ -11,7 +11,7 @@
|
||||
#pragma once
|
||||
#include "XNBaseFrameObject.h"
|
||||
|
||||
class XNThreadManagerPrivate;
|
||||
struct XNThreadManagerPrivate;
|
||||
|
||||
/**
|
||||
* @brief 线程管理器类
|
||||
@ -19,15 +19,14 @@ class XNThreadManagerPrivate;
|
||||
*/
|
||||
class XNThreadManager : public XNBaseFrameObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DECLARE_PRIVATE(XNThreadManager)
|
||||
Q_DISABLE_COPY(XNThreadManager)
|
||||
XN_METATYPE(XNThreadManager, XNBaseFrameObject)
|
||||
XN_DECLARE_PRIVATE(XNThreadManager)
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief 线程管理器类默认构造函数
|
||||
*/
|
||||
explicit XNThreadManager(QObject *parent = nullptr);
|
||||
XNThreadManager();
|
||||
|
||||
/**
|
||||
* @brief 线程管理器类析构函数
|
||||
@ -41,53 +40,32 @@ protected:
|
||||
* @param parent:QObject类型,父对象指针
|
||||
* @details 子类构造时调用此构造函数,传入子类的私有结构体指针
|
||||
*/
|
||||
XNThreadManager(XNThreadManagerPrivate &dd, QObject *parent = nullptr);
|
||||
XNThreadManager(PrivateType *p);
|
||||
|
||||
signals:
|
||||
/**
|
||||
* @brief 设置仿真开始时间信号
|
||||
* @param simTime: timespec结构体类型,用于线程纳秒睡眠计算的开始时间
|
||||
* @details 通过设置统一的开始时间,使个线程能同步执行
|
||||
*/
|
||||
void SetStartTime(const timespec &simTime);
|
||||
|
||||
/**
|
||||
* @brief 设置线程运行间隔信号
|
||||
* @param dRunInter: double类型,线程运行间隔,单位纳秒
|
||||
*/
|
||||
void SetRunInter(const double &dRunInter);
|
||||
|
||||
/**
|
||||
* @brief 仿真控制信号
|
||||
* @param objectId: 对象ID
|
||||
* @param cmd: 仿真控制命令
|
||||
*/
|
||||
void SimControl(quint32 objectId, SimControlCmd cmd);
|
||||
|
||||
public slots:
|
||||
public:
|
||||
/**
|
||||
* @brief 开始控制
|
||||
* @details 控制线程管理器开始运行接口
|
||||
*/
|
||||
void OnStart();
|
||||
void Start();
|
||||
|
||||
/**
|
||||
* @brief 停止控制
|
||||
* @details 控制线程管理器停止运行接口
|
||||
*/
|
||||
void OnAbort();
|
||||
void Abort();
|
||||
|
||||
/**
|
||||
* @brief 暂停控制
|
||||
* @details 控制线程管理器暂停运行接口
|
||||
*/
|
||||
void OnPause();
|
||||
void Pause();
|
||||
|
||||
/**
|
||||
* @brief 继续控制
|
||||
* @details 控制线程管理器继续运行接口
|
||||
*/
|
||||
void OnContinue();
|
||||
void Continue();
|
||||
|
||||
/**
|
||||
* @brief 初始化线程管理器
|
||||
@ -95,29 +73,21 @@ public slots:
|
||||
* @return false: 初始化失败
|
||||
* @details 线程管理器的初始化接口函数
|
||||
*/
|
||||
virtual void OnInitialize() override;
|
||||
virtual bool Initialize() override;
|
||||
|
||||
/**
|
||||
* @brief 仿真运行前最后处理
|
||||
* @note 线程管理器在所有线程开始执行前的准备工作
|
||||
*/
|
||||
virtual void OnPrepareForExecute() override;
|
||||
virtual bool PrepareForExecute() override;
|
||||
|
||||
/**
|
||||
* @brief 仿真控制
|
||||
* @param objectId: 对象ID
|
||||
* @param cmd: 仿真控制命令
|
||||
*/
|
||||
void OnSimControl(quint32 objectId, SimControlCmd cmd);
|
||||
void SimControl(uint32_t objectId, SimControlCmd cmd);
|
||||
|
||||
/**
|
||||
* @brief 设置仿真系统运行基频
|
||||
* @param dBaseFreq: double类型,频率值,单位Hz
|
||||
* @details 仿真系统所有线程以此基频的 1 或 1/2 或 1/4 或 1/8 或 1/16 或 1/32 倍运行
|
||||
*/
|
||||
void OnSetBaseFreq(const double &dBaseFreq);
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief 获取运行状态
|
||||
* @return RunStatus: 枚举类,线程运行状态
|
||||
@ -125,50 +95,29 @@ public:
|
||||
*/
|
||||
RunStatus GetStatus();
|
||||
|
||||
/**
|
||||
* @brief 获得仿真系统运行基频
|
||||
* @return const double&: 频率值,单位Hz
|
||||
*/
|
||||
const double &GetBaseFreq();
|
||||
|
||||
/**
|
||||
* @brief 获得仿真系统运行基础间隔
|
||||
* @return const double&: 运行周期值,单位纳秒
|
||||
* @details 模型基础运行间隔由基频计算获得
|
||||
*/
|
||||
const double &GetBaseInter();
|
||||
|
||||
/**
|
||||
* @brief 通过运行间隔设置基频
|
||||
* @param dBaseInter:double类型,运行周期值,单位纳秒
|
||||
* @details 使用运行间隔计算得到基频并设置
|
||||
*/
|
||||
void SetBaseFreqByInter(const double &dBaseInter);
|
||||
|
||||
/**
|
||||
* @brief 获取线程数量
|
||||
* @return quint32: 线程数量
|
||||
*/
|
||||
quint32 GetThreadCount();
|
||||
uint32_t GetThreadCount();
|
||||
|
||||
public slots:
|
||||
/**
|
||||
* @brief 添加一个线程
|
||||
* @param name: XNString类型,线程名称
|
||||
* @param freq: FreqLevel枚举类型,线程运行频率组
|
||||
* @param freq: double类型,线程运行频率,单位Hz
|
||||
* @param priority: UINT32类型,线程运行优先级,99~0,优先级数值越大,优先级越高
|
||||
* @param CPUAff: UINT32类型,线程的CPU亲和性掩码,按位表示某CPU核是否使用,从低到高,0表示不使用,1表示使用。
|
||||
* 例如:0x00000003表示使用0,1号CPU
|
||||
* @param RunInter: double类型,线程的运行周期,单位纳秒
|
||||
* @details 按照设置的参数创建线程
|
||||
*/
|
||||
virtual void OnAddThreadPool(QString name, FreqLevel freq, quint32 priority, quint32 CPUAff,
|
||||
double RunInter);
|
||||
virtual uint32_t AddThreadPool(std::string name, double freq, uint32_t priority,
|
||||
uint32_t 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,优先级数值越大,优先级越高
|
||||
@ -176,8 +125,8 @@ public slots:
|
||||
* @return false: 添加失败
|
||||
* @details 根据运行频率组和节点号向对应的线程中添加周期性函数
|
||||
*/
|
||||
void OnRegisterFunction(quint32 id, XNCallBack fun, quint32 freqGroup, quint32 RunPos,
|
||||
quint32 RunPriorty);
|
||||
void RegisterFunction(uint32_t id, XNCallBack fun, uint32_t threadID, uint32_t freqGroup,
|
||||
uint32_t RunPos, uint32_t RunPriorty);
|
||||
|
||||
private:
|
||||
/**
|
||||
@ -187,7 +136,7 @@ private:
|
||||
* @return true:提交的函数频率与节点号符合规则
|
||||
* @return false:提交的函数频率与节点号不符合规则
|
||||
*/
|
||||
bool IsFunParamRight(quint32 ModelID, quint32 freqGroup, quint32 RunPos);
|
||||
bool IsFunParamRight(uint32_t ModelID, uint32_t freqGroup, uint32_t RunPos);
|
||||
|
||||
quint32 AllocateThreadID();
|
||||
uint32_t AllocateThreadID();
|
||||
};
|
@ -20,55 +20,46 @@ struct funInfo {
|
||||
* @brief 周期性函数包装器
|
||||
*/
|
||||
XNCallBack fun;
|
||||
/**
|
||||
* @brief 线程ID
|
||||
*/
|
||||
uint32_t threadID;
|
||||
/**
|
||||
* @brief 运行频率组
|
||||
*/
|
||||
quint32 freqGroup;
|
||||
uint32_t freqGroup;
|
||||
/**
|
||||
* @brief 运行节点
|
||||
*/
|
||||
quint32 RunPos;
|
||||
uint32_t RunPos;
|
||||
/**
|
||||
* @brief 运行优先级
|
||||
*/
|
||||
quint32 RunPriority;
|
||||
uint32_t RunPriority;
|
||||
};
|
||||
/**
|
||||
* @brief 声明周期性函数存储结构体的智能指针
|
||||
*/
|
||||
using funInfoPtr = QSharedPointer<funInfo>;
|
||||
using funInfoPtr = std::shared_ptr<funInfo>;
|
||||
|
||||
/**
|
||||
* @brief 线程管理器类私有结构体
|
||||
*/
|
||||
class XNThreadManagerPrivate : public XNBaseFrameObjectPrivate
|
||||
{
|
||||
public:
|
||||
XNThreadManagerPrivate(XNThreadManager *q) : XNBaseFrameObjectPrivate(q) {}
|
||||
Q_DECLARE_PUBLIC(XNThreadManager)
|
||||
private:
|
||||
struct XNThreadManagerPrivate : public XNBaseFrameObjectPrivate {
|
||||
/**
|
||||
* @brief 所有线程运行状态
|
||||
*/
|
||||
RunStatus _eRunStatus;
|
||||
/**
|
||||
* @brief 线程列表
|
||||
*/
|
||||
std::map<uint32_t, XNThreadPtr> threadList;
|
||||
/**
|
||||
* @brief 周期性函数存储列表
|
||||
*/
|
||||
QMap<quint32, std::vector<funInfoPtr> > funList;
|
||||
/**
|
||||
* @brief 基础运行频率
|
||||
*/
|
||||
double dRunFreq = BASE_RUN_FREQ;
|
||||
/**
|
||||
* @brief 基础运行间隔
|
||||
*/
|
||||
double dRunInter = BASE_RUN_INTER;
|
||||
std::map<uint32_t, std::vector<funInfoPtr> > funList;
|
||||
/**
|
||||
* @brief 线程ID
|
||||
*/
|
||||
QSet<quint32> threadIDMap;
|
||||
/**
|
||||
* @brief 线程数量
|
||||
*/
|
||||
quint32 threadCount = 0;
|
||||
std::set<uint32_t> threadIDMap;
|
||||
};
|
||||
|
76
Release/include/XNCore/XNThread_p.h
Normal file
76
Release/include/XNCore/XNThread_p.h
Normal file
@ -0,0 +1,76 @@
|
||||
#pragma once
|
||||
#include "XNObject_p.h"
|
||||
/**
|
||||
* @brief 线程类私有结构体
|
||||
*/
|
||||
struct XNThreadPrivate : public XNObjectPrivate {
|
||||
/**
|
||||
* @brief 框架对象
|
||||
*/
|
||||
XNFrameworkPtr _framework;
|
||||
/**
|
||||
* @brief 线程运行优先级
|
||||
*/
|
||||
uint32_t _uPriority = 0;
|
||||
/**
|
||||
* @brief 线程CPU亲和性掩码
|
||||
* @details 按位表示某CPU核是否使用,从低到高,0表示不使用,1表示使用。例如:0x00000003表示使用0,1号CPU
|
||||
*/
|
||||
uint32_t _uAffinity = 0;
|
||||
/**
|
||||
* @brief 线程运行频率
|
||||
*/
|
||||
double _setFreq = BASE_RUN_FREQ;
|
||||
/**
|
||||
* @brief 线程调度任务表
|
||||
*/
|
||||
std::vector<std::map<uint32_t, std::vector<XNCallBack> > > _funVec;
|
||||
/**
|
||||
* @brief pthread线程调度参数
|
||||
*/
|
||||
sched_param param;
|
||||
/**
|
||||
* @brief pthread线程属性
|
||||
*/
|
||||
pthread_attr_t attr;
|
||||
/**
|
||||
* @brief pthread线程
|
||||
*/
|
||||
pthread_t thread;
|
||||
/**
|
||||
* @brief 线程睡眠时间控制
|
||||
*/
|
||||
PERIOD_INFO pinfo;
|
||||
/**
|
||||
* @brief 线程控制锁
|
||||
*/
|
||||
pthread_mutex_t _mtx = PTHREAD_MUTEX_INITIALIZER;
|
||||
/**
|
||||
* @brief 线程控制条件变量
|
||||
*/
|
||||
pthread_cond_t _cond = PTHREAD_COND_INITIALIZER;
|
||||
/**
|
||||
* @brief 线程运行状态
|
||||
*/
|
||||
RunStatus _eRunStatus = RunStatus::NotStart;
|
||||
/**
|
||||
* @brief 线程执行进度
|
||||
*/
|
||||
uint32_t _RunPosition = 0;
|
||||
/**
|
||||
* @brief 线程执行计数
|
||||
*/
|
||||
int count = 0;
|
||||
/**
|
||||
* @brief 线程执行时间统计
|
||||
*/
|
||||
timespec _lastRunTime;
|
||||
/**
|
||||
* @brief 线程运行状态主题写入器
|
||||
*/
|
||||
FAST_DDS_MACRO::DataWriter *writer;
|
||||
/**
|
||||
* @brief 线程ID
|
||||
*/
|
||||
uint32_t _threadID = 0;
|
||||
};
|
@ -10,9 +10,9 @@
|
||||
*/
|
||||
#pragma once
|
||||
#include "XNBaseFrameObject.h"
|
||||
#include <QDateTime>
|
||||
#include <chrono>
|
||||
|
||||
class XNTimeManagerPrivate;
|
||||
struct XNTimeManagerPrivate;
|
||||
|
||||
/**
|
||||
* @brief 时间管理器类
|
||||
@ -20,16 +20,14 @@ class XNTimeManagerPrivate;
|
||||
*/
|
||||
class XNCORE_EXPORT XNTimeManager : public XNBaseFrameObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY(XNTimeManager);
|
||||
Q_DECLARE_PRIVATE(XNTimeManager);
|
||||
XN_METATYPE(XNTimeManager, XNBaseFrameObject)
|
||||
XN_DECLARE_PRIVATE(XNTimeManager)
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief 构造函数
|
||||
* @param parent: 父对象
|
||||
*/
|
||||
explicit XNTimeManager(QObject *parent = nullptr);
|
||||
XNTimeManager();
|
||||
|
||||
/**
|
||||
* @brief 析构函数
|
||||
@ -39,63 +37,46 @@ public:
|
||||
protected:
|
||||
/**
|
||||
* @brief 构造函数
|
||||
* @param dd: 私有数据成员
|
||||
* @param parent: 父对象
|
||||
* @param p: 私有数据成员
|
||||
*/
|
||||
XNTimeManager(XNTimeManagerPrivate &dd, QObject *parent = nullptr);
|
||||
XNTimeManager(PrivateType *p);
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief 获取当前仿真时间
|
||||
* @return QDateTime: 当前仿真时间
|
||||
* @return std::chrono::system_clock::time_point: 当前仿真时间
|
||||
*/
|
||||
QDateTime GetSimTime();
|
||||
XNTimePoint GetSimTime();
|
||||
|
||||
signals:
|
||||
/**
|
||||
* @brief 设置仿真开始时间信号
|
||||
* @param simTime: timespec结构体类型,用于线程纳秒睡眠计算的开始时间
|
||||
* @details 通过设置统一的开始时间,使个线程能同步执行
|
||||
*/
|
||||
void SetStartTime(const timespec &simTime);
|
||||
|
||||
/**
|
||||
* @brief 仿真控制信号
|
||||
* @param objectId: 对象ID
|
||||
* @param cmd: 仿真控制命令
|
||||
*/
|
||||
void SimControl(quint32 objectId, SimControlCmd cmd);
|
||||
|
||||
public slots:
|
||||
/**
|
||||
* @brief 设置仿真开始时间
|
||||
* @param simTime: timespec类型,仿真开始时间
|
||||
*/
|
||||
void OnSetStartTime(const timespec &simTime);
|
||||
void SetStartTime(const timespec &simTime);
|
||||
|
||||
/**
|
||||
* @brief 开始控制
|
||||
* @details 控制时间管理器线程开始运行接口
|
||||
*/
|
||||
void OnStart();
|
||||
void Start();
|
||||
|
||||
/**
|
||||
* @brief 停止控制
|
||||
* @details 控制时间管理器线程停止运行接口
|
||||
*/
|
||||
void OnAbort();
|
||||
void Abort();
|
||||
|
||||
/**
|
||||
* @brief 暂停控制
|
||||
* @details 控制时间管理器线程暂停运行接口
|
||||
*/
|
||||
void OnPause();
|
||||
void Pause();
|
||||
|
||||
/**
|
||||
* @brief 继续控制
|
||||
* @details 控制时间管理器线程继续运行接口
|
||||
*/
|
||||
void OnContinue();
|
||||
void Continue();
|
||||
|
||||
/**
|
||||
* @brief 初始化时间管理器
|
||||
@ -103,22 +84,21 @@ public slots:
|
||||
* @return false: 初始化失败
|
||||
* @details 时间管理器的初始化接口函数
|
||||
*/
|
||||
virtual void OnInitialize() override;
|
||||
virtual bool Initialize() override;
|
||||
|
||||
/**
|
||||
* @brief 仿真运行前最后处理
|
||||
* @note 时间管理器在开始执行前的准备工作
|
||||
*/
|
||||
virtual void OnPrepareForExecute() override;
|
||||
virtual bool PrepareForExecute() override;
|
||||
|
||||
/**
|
||||
* @brief 仿真控制
|
||||
* @param objectId: 对象ID
|
||||
* @param cmd: 仿真控制命令
|
||||
*/
|
||||
void OnSimControl(quint32 objectId, SimControlCmd cmd);
|
||||
void SimControl(uint32_t objectId, SimControlCmd cmd);
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief 获取运行状态
|
||||
* @return RunStatus: 枚举类,时间管理器线程运行状态
|
||||
|
@ -11,21 +11,12 @@
|
||||
#pragma once
|
||||
#include "XNBaseFrameObject_p.h"
|
||||
#include "XNThread.h"
|
||||
#include <chrono>
|
||||
|
||||
/**
|
||||
* @brief 时间管理器类私有结构体
|
||||
*/
|
||||
class XNTimeManagerPrivate : public XNBaseFrameObjectPrivate
|
||||
{
|
||||
public:
|
||||
Q_DECLARE_PUBLIC(XNTimeManager)
|
||||
|
||||
explicit XNTimeManagerPrivate(XNTimeManager *q) : XNBaseFrameObjectPrivate(q)
|
||||
{
|
||||
_eRunStatus = RunStatus::NotStart;
|
||||
}
|
||||
|
||||
private:
|
||||
struct XNTimeManagerPrivate : public XNBaseFrameObjectPrivate {
|
||||
/*
|
||||
* @brief 仿真运行状态
|
||||
*/
|
||||
@ -33,11 +24,11 @@ private:
|
||||
/**
|
||||
* @brief 仿真开始时间
|
||||
*/
|
||||
QDateTime _SimStartTime;
|
||||
std::chrono::system_clock::time_point _SimStartTime;
|
||||
/**
|
||||
* @brief 当前仿真时间
|
||||
*/
|
||||
QDateTime _SimTime;
|
||||
std::chrono::system_clock::time_point _SimTime;
|
||||
/**
|
||||
* @brief 时间管理器线程智能指针
|
||||
*/
|
||||
|
3
XNCore/.vscode/settings.json
vendored
3
XNCore/.vscode/settings.json
vendored
@ -78,6 +78,7 @@
|
||||
"qlibrary": "cpp",
|
||||
"csignal": "cpp",
|
||||
"any": "cpp",
|
||||
"unordered_set": "cpp"
|
||||
"unordered_set": "cpp",
|
||||
"fstream": "cpp"
|
||||
}
|
||||
}
|
@ -41,6 +41,7 @@ add_library(XNCore SHARED
|
||||
XNTimeManager.cpp
|
||||
XNThread.h
|
||||
XNThread.cpp
|
||||
XNThread_p.h
|
||||
XNThreadManager.h
|
||||
XNThreadManager_p.h
|
||||
XNThreadManager.cpp
|
||||
@ -54,7 +55,6 @@ add_library(XNCore SHARED
|
||||
XNScenarioManager_p.h
|
||||
XNScenarioManager.cpp
|
||||
XNDDSManager.h
|
||||
XNDDSManager_p.h
|
||||
XNDDSManager.cpp
|
||||
XNServiceManager.h
|
||||
XNServiceManager_p.h
|
||||
|
@ -1,8 +1,7 @@
|
||||
#include "XNBaseFrameObject.h"
|
||||
#include "XNBaseFrameObject_p.h"
|
||||
|
||||
XNBaseFrameObject::XNBaseFrameObject(QObject *parent)
|
||||
: XNObject(*new XNBaseFrameObjectPrivate(this), parent)
|
||||
XNBaseFrameObject::XNBaseFrameObject() : XNObject(new XNBaseFrameObjectPrivate())
|
||||
{
|
||||
}
|
||||
|
||||
@ -10,13 +9,24 @@ XNBaseFrameObject::~XNBaseFrameObject()
|
||||
{
|
||||
}
|
||||
|
||||
XNBaseFrameObject::XNBaseFrameObject(XNBaseFrameObjectPrivate &dd, QObject *parent)
|
||||
: XNObject(dd, parent)
|
||||
XNBaseFrameObject::XNBaseFrameObject(PrivateType *p) : XNObject(p)
|
||||
{
|
||||
}
|
||||
|
||||
XNFrameObjectStatus XNBaseFrameObject::GetFrameObjectStatus()
|
||||
{
|
||||
Q_D(XNBaseFrameObject);
|
||||
T_D();
|
||||
return d->_status;
|
||||
}
|
||||
|
||||
XNFrameworkPtr XNBaseFrameObject::GetFramework()
|
||||
{
|
||||
T_D();
|
||||
return d->_framework;
|
||||
}
|
||||
|
||||
void XNBaseFrameObject::SetFramework(XNFrameworkPtr framework)
|
||||
{
|
||||
T_D();
|
||||
d->_framework = framework;
|
||||
}
|
||||
|
@ -12,34 +12,29 @@
|
||||
|
||||
#include "XNObject.h"
|
||||
|
||||
class XNBaseFrameObjectPrivate;
|
||||
struct XNBaseFrameObjectPrivate;
|
||||
|
||||
/**
|
||||
* @brief 框架对象基类
|
||||
*/
|
||||
class XNCORE_EXPORT XNBaseFrameObject : public XNObject
|
||||
{
|
||||
/**
|
||||
* @brief 宏定义,用于支持Qt的元对象系统
|
||||
*/
|
||||
Q_OBJECT
|
||||
|
||||
/**
|
||||
* @brief 宏定义,用于禁用拷贝构造函数
|
||||
*/
|
||||
Q_DISABLE_COPY(XNBaseFrameObject)
|
||||
XN_METATYPE(XNBaseFrameObject, XNObject)
|
||||
|
||||
/**
|
||||
* @brief 宏定义,用于声明私有数据成员
|
||||
*/
|
||||
Q_DECLARE_PRIVATE(XNBaseFrameObject);
|
||||
XN_DECLARE_PRIVATE(XNBaseFrameObject)
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief 构造函数
|
||||
* @param parent 父对象
|
||||
*/
|
||||
XNBaseFrameObject(QObject *parent = nullptr);
|
||||
XNBaseFrameObject();
|
||||
|
||||
/**
|
||||
* @brief 析构函数
|
||||
@ -52,44 +47,34 @@ protected:
|
||||
* @param dd 私有数据成员
|
||||
* @param parent 父对象
|
||||
*/
|
||||
XNBaseFrameObject(XNBaseFrameObjectPrivate &dd, QObject *parent = nullptr);
|
||||
|
||||
signals:
|
||||
/**
|
||||
* @brief 初始化
|
||||
*/
|
||||
void Initialize();
|
||||
|
||||
/**
|
||||
* @brief 初始化失败
|
||||
*/
|
||||
void InitializeFailed();
|
||||
|
||||
/**
|
||||
* @brief 准备执行
|
||||
*/
|
||||
void PrepareForExecute();
|
||||
|
||||
/**
|
||||
* @brief 准备执行失败
|
||||
*/
|
||||
void PrepareForExecuteFailed();
|
||||
|
||||
public slots:
|
||||
/**
|
||||
* @brief 初始化
|
||||
*/
|
||||
virtual void OnInitialize() = 0;
|
||||
|
||||
/**
|
||||
* @brief 准备执行
|
||||
*/
|
||||
virtual void OnPrepareForExecute() = 0;
|
||||
XNBaseFrameObject(PrivateType *p);
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief 初始化
|
||||
*/
|
||||
virtual bool Initialize() = 0;
|
||||
|
||||
/**
|
||||
* @brief 准备执行
|
||||
*/
|
||||
virtual bool PrepareForExecute() = 0;
|
||||
|
||||
/**
|
||||
* @brief 获取框架对象状态
|
||||
* @return 框架对象状态
|
||||
*/
|
||||
XNFrameObjectStatus GetFrameObjectStatus();
|
||||
|
||||
/**
|
||||
* @brief 获取框架对象
|
||||
* @return 框架对象
|
||||
*/
|
||||
XNFrameworkPtr GetFramework();
|
||||
|
||||
/**
|
||||
* @brief 设置框架对象
|
||||
* @param framework 框架对象
|
||||
*/
|
||||
void SetFramework(XNFrameworkPtr framework);
|
||||
};
|
||||
|
@ -16,22 +16,13 @@
|
||||
/**
|
||||
* @brief 框架对象基类的私有数据成员
|
||||
*/
|
||||
class XNBaseFrameObjectPrivate : public XNObjectPrivate
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief 构造函数
|
||||
* @param q 框架对象基类指针
|
||||
*/
|
||||
explicit XNBaseFrameObjectPrivate(XNBaseFrameObject *q) : XNObjectPrivate(q) {}
|
||||
|
||||
/**
|
||||
* @brief 宏定义,用于声明公有数据成员
|
||||
*/
|
||||
Q_DECLARE_PUBLIC(XNBaseFrameObject)
|
||||
|
||||
struct XNBaseFrameObjectPrivate : public XNObjectPrivate {
|
||||
/**
|
||||
* @brief 框架对象状态
|
||||
*/
|
||||
XNFrameObjectStatus _status = XNFrameObjectStatus::NotReady;
|
||||
/**
|
||||
* @brief 框架对象
|
||||
*/
|
||||
XNFrameworkPtr _framework;
|
||||
};
|
||||
|
10
XNCore/XNCore_Function.cpp
Normal file
10
XNCore/XNCore_Function.cpp
Normal file
@ -0,0 +1,10 @@
|
||||
#include "XNCore_global.h"
|
||||
|
||||
XNTimePoint parseISOTime(const std::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;
|
||||
}
|
@ -1,14 +1,13 @@
|
||||
#ifndef XNCORE_GLOBAL_H
|
||||
#define XNCORE_GLOBAL_H
|
||||
|
||||
#include <QtCore/qglobal.h>
|
||||
#pragma once
|
||||
|
||||
#if defined(XNCORE_LIBRARY)
|
||||
# define XNCORE_EXPORT Q_DECL_EXPORT
|
||||
# define XNCORE_EXPORT __attribute__((visibility("default")))
|
||||
#else
|
||||
# define XNCORE_EXPORT Q_DECL_IMPORT
|
||||
# define XNCORE_EXPORT __attribute__((visibility("default")))
|
||||
#endif
|
||||
|
||||
#define FORCEINLINE __attribute__((always_inline))
|
||||
|
||||
#ifdef __linux__
|
||||
# include <pthread.h>
|
||||
# include <sched.h>
|
||||
@ -20,8 +19,34 @@
|
||||
# include <memory>
|
||||
# include <errno.h>
|
||||
# include <unistd.h>
|
||||
# include <limits.h>
|
||||
# include <functional>
|
||||
# include <map>
|
||||
# include <unordered_map>
|
||||
# include <vector>
|
||||
# include <set>
|
||||
# include <any>
|
||||
# include <string>
|
||||
# include <thread>
|
||||
# include <mutex>
|
||||
# include <condition_variable>
|
||||
# include <queue>
|
||||
# include <tinyxml2.h>
|
||||
# include <chrono>
|
||||
# include <iomanip>
|
||||
# include <sstream>
|
||||
# include <dlfcn.h>
|
||||
# include <filesystem>
|
||||
#endif
|
||||
|
||||
#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/Subscriber.hpp>
|
||||
#include <fastdds/dds/topic/TypeSupport.hpp>
|
||||
#include <fastdds/dds/subscriber/DataReaderListener.hpp>
|
||||
#define FAST_DDS_MACRO eprosima::fastdds::dds
|
||||
|
||||
/**
|
||||
@ -40,6 +65,9 @@ using XNCallBack = std::function<void()>;
|
||||
//DDS回调函数类型别名
|
||||
using XNDDSCallBack = std::function<void(void *)>;
|
||||
|
||||
//事件回调函数类型别名
|
||||
using XNEventCallback = std::function<void(const std::any &)>;
|
||||
|
||||
/**
|
||||
* @brief 纳秒睡眠相关时间结构体
|
||||
* @details 用于线程睡眠时间控制
|
||||
@ -54,6 +82,17 @@ struct PERIOD_INFO {
|
||||
*/
|
||||
long period_ns;
|
||||
};
|
||||
/**
|
||||
* @brief 系统时间点类型别名
|
||||
*/
|
||||
using XNTimePoint = std::chrono::system_clock::time_point;
|
||||
|
||||
/**
|
||||
* @brief 将ISO格式的时间字符串转换为系统时间点
|
||||
* @param timeStr ISO格式的时间字符串 (YYYY-MM-DDTHH:mm:ss)
|
||||
* @return 系统时间点
|
||||
*/
|
||||
XNTimePoint parseISOTime(const std::string &timeStr);
|
||||
|
||||
/**
|
||||
* @brief 系统运行状态枚举类
|
||||
@ -155,10 +194,63 @@ enum class XNFrameObjectStatus {
|
||||
Unknown
|
||||
};
|
||||
|
||||
#define XN_DLL_INITIALIZE(ClassName) \
|
||||
extern "C" void Initial##ClassName() \
|
||||
{ \
|
||||
qRegisterMetaType<ClassName>(#ClassName); \
|
||||
template <class ToType, class FromType>
|
||||
FORCEINLINE ToType XNStaticCastHelper(const FromType &from)
|
||||
{
|
||||
return std::static_pointer_cast<typename ToType::element_type>(from);
|
||||
}
|
||||
|
||||
#endif // XNCORE_GLOBAL_H
|
||||
template <class ToType, class FromType>
|
||||
FORCEINLINE ToType XNCastHelper(const FromType &from)
|
||||
{
|
||||
return std::dynamic_pointer_cast<typename ToType::element_type>(from);
|
||||
}
|
||||
|
||||
#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>;
|
||||
|
||||
#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()
|
||||
|
||||
struct XNNullClass {
|
||||
};
|
||||
|
||||
#define XN_METATYPE_P(cls) \
|
||||
public: \
|
||||
using ThisType = cls; \
|
||||
using SuperType = XNNullClass;
|
||||
|
||||
#define XN_METATYPE(cls, sup) \
|
||||
public: \
|
||||
using ThisType = cls; \
|
||||
using SuperType = sup;
|
||||
|
193
XNCore/XNDDSInterface.h
Executable file → Normal file
193
XNCore/XNDDSInterface.h
Executable file → Normal file
@ -45,44 +45,6 @@ public:
|
||||
XNDDSInterface() = default;
|
||||
virtual ~XNDDSInterface() = default;
|
||||
|
||||
template <typename T>
|
||||
void getByteArray(eprosima::fastcdr::optional<T> data, uint8_t *buffer, size_t bufferSize)
|
||||
{
|
||||
if (bufferSize < getTypeSize<T>())
|
||||
return;
|
||||
|
||||
if constexpr (std::is_arithmetic_v<T>) {
|
||||
if (data) {
|
||||
std::memcpy(buffer, &data.value(), sizeof(T));
|
||||
} else {
|
||||
T zero = 0;
|
||||
std::memcpy(buffer, &zero, sizeof(T));
|
||||
}
|
||||
} else if constexpr (is_std_array_v<T>) {
|
||||
if (data) {
|
||||
getByteArrayFromStdArray(data.value(), buffer, bufferSize);
|
||||
} else {
|
||||
T zero = {};
|
||||
getByteArrayFromStdArray(zero, buffer, bufferSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, std::size_t N>
|
||||
void getByteArrayFromStdArray(std::array<T, N> data, uint8_t *buffer, size_t bufferSize)
|
||||
{
|
||||
if (bufferSize < getTypeSize<T>() * N)
|
||||
return;
|
||||
|
||||
for (std::size_t i = 0; i < N; ++i) {
|
||||
if constexpr (std::is_arithmetic_v<T>) {
|
||||
std::memcpy(buffer + i * getTypeSize<T>(), &data[i], getTypeSize<T>());
|
||||
} else {
|
||||
getByteArrayFromStdArray(data[i], buffer + i * getTypeSize<T>(), getTypeSize<T>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void getUDPPackage(uint8_t *buffer, size_t bufferSize)
|
||||
{
|
||||
if (bufferSize < MAX_UDP_PACKET_SIZE)
|
||||
@ -112,42 +74,6 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::string getString(eprosima::fastcdr::optional<T> data)
|
||||
{
|
||||
if constexpr (std::is_arithmetic_v<T>) {
|
||||
if (data) {
|
||||
return std::to_string(data.value());
|
||||
} else {
|
||||
return std::to_string(0);
|
||||
}
|
||||
} else if constexpr (std::is_same_v<T, std::string>) {
|
||||
if (data) {
|
||||
return getStringFromStdArray(data.value());
|
||||
} else {
|
||||
T zero = {};
|
||||
return getStringFromStdArray(zero);
|
||||
}
|
||||
}
|
||||
return std::string();
|
||||
}
|
||||
|
||||
template <typename T, std::size_t N>
|
||||
std::string getStringFromStdArray(std::array<T, N> data)
|
||||
{
|
||||
std::stringstream ss;
|
||||
for (std::size_t i = 0; i < N; ++i) {
|
||||
if (i > 0)
|
||||
ss << ",";
|
||||
if constexpr (std::is_arithmetic_v<T>) {
|
||||
ss << data[i];
|
||||
} else {
|
||||
ss << getStringFromStdArray(data[i]);
|
||||
}
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string getData(const std::string &varName)
|
||||
{
|
||||
int index1 = -1;
|
||||
@ -221,6 +147,81 @@ public:
|
||||
return list2[index2];
|
||||
}
|
||||
|
||||
protected:
|
||||
template <typename T>
|
||||
void getByteArray(eprosima::fastcdr::optional<T> data, uint8_t *buffer, size_t bufferSize)
|
||||
{
|
||||
if (bufferSize < getTypeSize<T>())
|
||||
return;
|
||||
|
||||
if constexpr (std::is_arithmetic_v<T>) {
|
||||
if (data) {
|
||||
std::memcpy(buffer, &data.value(), sizeof(T));
|
||||
} else {
|
||||
T zero = 0;
|
||||
std::memcpy(buffer, &zero, sizeof(T));
|
||||
}
|
||||
} else if constexpr (is_std_array_v<T>) {
|
||||
if (data) {
|
||||
getByteArrayFromStdArray(data.value(), buffer, bufferSize);
|
||||
} else {
|
||||
T zero = {};
|
||||
getByteArrayFromStdArray(zero, buffer, bufferSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, std::size_t N>
|
||||
void getByteArrayFromStdArray(std::array<T, N> data, uint8_t *buffer, size_t bufferSize)
|
||||
{
|
||||
if (bufferSize < getTypeSize<T>() * N)
|
||||
return;
|
||||
|
||||
for (std::size_t i = 0; i < N; ++i) {
|
||||
if constexpr (std::is_arithmetic_v<T>) {
|
||||
std::memcpy(buffer + i * getTypeSize<T>(), &data[i], getTypeSize<T>());
|
||||
} else {
|
||||
getByteArrayFromStdArray(data[i], buffer + i * getTypeSize<T>(), getTypeSize<T>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::string getString(eprosima::fastcdr::optional<T> data)
|
||||
{
|
||||
if constexpr (std::is_arithmetic_v<T>) {
|
||||
if (data) {
|
||||
return std::to_string(data.value());
|
||||
} else {
|
||||
return std::to_string(0);
|
||||
}
|
||||
} else if constexpr (std::is_same_v<T, std::string>) {
|
||||
if (data) {
|
||||
return getStringFromStdArray(data.value());
|
||||
} else {
|
||||
T zero = {};
|
||||
return getStringFromStdArray(zero);
|
||||
}
|
||||
}
|
||||
return std::string();
|
||||
}
|
||||
|
||||
template <typename T, std::size_t N>
|
||||
std::string getStringFromStdArray(std::array<T, N> data)
|
||||
{
|
||||
std::stringstream ss;
|
||||
for (std::size_t i = 0; i < N; ++i) {
|
||||
if (i > 0)
|
||||
ss << ",";
|
||||
if constexpr (std::is_arithmetic_v<T>) {
|
||||
ss << data[i];
|
||||
} else {
|
||||
ss << getStringFromStdArray(data[i]);
|
||||
}
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
protected:
|
||||
struct ByteArrayFunc {
|
||||
std::function<void(uint8_t *, size_t)> func;
|
||||
@ -239,3 +240,47 @@ protected:
|
||||
getByteArrayFunction.push_back( \
|
||||
{[this](uint8_t *buffer, size_t size) { getByteArray(data.NAME(), buffer, size); }, \
|
||||
getTypeSize<decltype(data.NAME())>()})
|
||||
|
||||
#define ASSIGN_VALUE_GET(NAME) \
|
||||
if (data.NAME()) { \
|
||||
auto temp = data.NAME().value(); \
|
||||
if constexpr (std::is_arithmetic_v<decltype(temp)>) { \
|
||||
model_data->NAME = temp; \
|
||||
} else if constexpr (std::is_std_array_v<decltype(temp)>) { \
|
||||
size_t arraySize = std::tuple_size<decltype(temp)>::value; \
|
||||
for (size_t i = 0; i < arraySize; ++i) { \
|
||||
if constexpr (std::is_arithmetic_v<decltype(temp[i])>) { \
|
||||
model_data->NAME[i] = temp[i]; \
|
||||
} else if constexpr (std::is_std_array_v<decltype(temp[i])>) { \
|
||||
size_t arraySize2 = std::tuple_size<decltype(temp[i])>::value; \
|
||||
for (size_t j = 0; j < arraySize2; ++j) { \
|
||||
model_data->NAME[i][j] = temp[i][j]; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
#define ASSIGN_VALUE_SET(NAME) \
|
||||
if constexpr (std::is_arithmetic_v<decltype(data.NAME())::type>) { \
|
||||
data.NAME(model_data->NAME); \
|
||||
} else if constexpr (std::is_std_array_v<decltype(data.NAME())::type>) { \
|
||||
using thisType = typename decltype(data.NAME())::type; \
|
||||
thisType temp; \
|
||||
size_t arraySize1 = std::tuple_size<thisType>::value; \
|
||||
using subType = thisType::value_type; \
|
||||
if constexpr (std::is_arithmetic_v<subType>) { \
|
||||
for (size_t i = 0; i < arraySize1; ++i) { \
|
||||
temp[i] = model_data->NAME[i]; \
|
||||
} \
|
||||
} else if constexpr (std::is_std_array_v<subType>) { \
|
||||
size_t arraySize2 = std::tuple_size<subType>::value; \
|
||||
std::array<subType, arraySize1> temp; \
|
||||
for (size_t i = 0; i < arraySize1; ++i) { \
|
||||
for (size_t j = 0; j < arraySize2; ++j) { \
|
||||
temp[i][j] = model_data->NAME[i][j]; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
data.NAME(temp); \
|
||||
}
|
||||
|
@ -1,45 +1,45 @@
|
||||
#include "XNDDSManager.h"
|
||||
#include "XNDDSManager_p.h"
|
||||
|
||||
XNDDSManager::XNDDSManager(QObject *parent)
|
||||
: XNBaseFrameObject(*new XNDDSManagerPrivate(this), parent)
|
||||
XNDDSManager::XNDDSManager() : XNBaseFrameObject(new XNDDSManagerPrivate())
|
||||
{
|
||||
setUniqueId(8);
|
||||
setObjectName("XNDDSManager");
|
||||
SetUniqueId(8);
|
||||
SetObjectName("XNDDSManager");
|
||||
}
|
||||
|
||||
XNDDSManager::~XNDDSManager()
|
||||
{
|
||||
}
|
||||
|
||||
XNDDSManager::XNDDSManager(XNDDSManagerPrivate &dd, QObject *parent) : XNBaseFrameObject(dd, parent)
|
||||
XNDDSManager::XNDDSManager(PrivateType *p) : XNBaseFrameObject(p)
|
||||
{
|
||||
}
|
||||
|
||||
void XNDDSManager::OnInitialize()
|
||||
bool XNDDSManager::Initialize()
|
||||
{
|
||||
Q_D(XNDDSManager);
|
||||
LOG_INFO("XNDDSManager Initialize Success!");
|
||||
T_D();
|
||||
d->_status = XNFrameObjectStatus::Initialized;
|
||||
emit Initialize();
|
||||
d->participant_ = nullptr;
|
||||
d->topics_.clear();
|
||||
LOG_INFO("XNDDSManager Initialize Success!");
|
||||
return true;
|
||||
}
|
||||
|
||||
void XNDDSManager::OnPrepareForExecute()
|
||||
bool XNDDSManager::PrepareForExecute()
|
||||
{
|
||||
Q_D(XNDDSManager);
|
||||
T_D();
|
||||
d->_status = XNFrameObjectStatus::Ready;
|
||||
LOG_INFO("XNDDSManager is prepared!");
|
||||
emit PrepareForExecute();
|
||||
return true;
|
||||
}
|
||||
|
||||
void XNDDSManager::SetDomainID(quint32 domainID)
|
||||
void XNDDSManager::SetDomainID(uint32_t domainID)
|
||||
{
|
||||
Q_D(XNDDSManager);
|
||||
T_D();
|
||||
FAST_DDS_MACRO::DomainParticipantQos participantQos;
|
||||
participantQos.name("XNDDSManager");
|
||||
participant_ = FAST_DDS_MACRO::DomainParticipantFactory::get_instance()->create_participant(
|
||||
d->participant_ = FAST_DDS_MACRO::DomainParticipantFactory::get_instance()->create_participant(
|
||||
domainID, participantQos);
|
||||
if (participant_ == nullptr) {
|
||||
if (d->participant_ == nullptr) {
|
||||
LOG_ERROR("0x2130 Create DomainParticipant Failed!");
|
||||
}
|
||||
}
|
||||
|
@ -1,14 +1,6 @@
|
||||
#pragma once
|
||||
#include "XNBaseFrameObject.h"
|
||||
|
||||
#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/Subscriber.hpp>
|
||||
#include <fastdds/dds/topic/TypeSupport.hpp>
|
||||
#include <fastdds/dds/subscriber/DataReaderListener.hpp>
|
||||
#include "XNBaseFrameObject_p.h"
|
||||
|
||||
struct PublisherInfo {
|
||||
FAST_DDS_MACRO::Publisher *publisher;
|
||||
@ -22,8 +14,8 @@ struct SubscriberInfo {
|
||||
|
||||
struct TopicInfo {
|
||||
FAST_DDS_MACRO::Topic *topic;
|
||||
QMap<quint32, PublisherInfo> publishers_;
|
||||
QMap<quint32, SubscriberInfo> subscribers_;
|
||||
std::map<uint32_t, PublisherInfo> publishers_;
|
||||
std::map<uint32_t, SubscriberInfo> subscribers_;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
@ -46,50 +38,54 @@ private:
|
||||
std::function<void(const T &)> callback_;
|
||||
};
|
||||
|
||||
class XNDDSManagerPrivate;
|
||||
struct XNDDSManagerPrivate : public XNBaseFrameObjectPrivate {
|
||||
FAST_DDS_MACRO::DomainParticipant *participant_;
|
||||
std::map<std::string, TopicInfo> topics_;
|
||||
std::mutex mutex_;
|
||||
};
|
||||
|
||||
class XNDDSManager : public XNBaseFrameObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DECLARE_PRIVATE(XNDDSManager)
|
||||
Q_DISABLE_COPY(XNDDSManager)
|
||||
XN_METATYPE(XNDDSManager, XNBaseFrameObject)
|
||||
XN_DECLARE_PRIVATE(XNDDSManager)
|
||||
public:
|
||||
explicit XNDDSManager(QObject *parent = nullptr);
|
||||
XNDDSManager();
|
||||
~XNDDSManager();
|
||||
|
||||
protected:
|
||||
XNDDSManager(XNDDSManagerPrivate &dd, QObject *parent = nullptr);
|
||||
XNDDSManager(PrivateType *p);
|
||||
|
||||
public slots:
|
||||
virtual void OnInitialize() override;
|
||||
public:
|
||||
virtual bool Initialize() override;
|
||||
|
||||
virtual void OnPrepareForExecute() override;
|
||||
virtual bool PrepareForExecute() override;
|
||||
|
||||
void SetDomainID(quint32 domainID);
|
||||
void SetDomainID(uint32_t domainID);
|
||||
|
||||
public:
|
||||
template <typename T>
|
||||
FAST_DDS_MACRO::DataWriter *RegisterPublisher(const QString &topicName, quint32 publisherID)
|
||||
FAST_DDS_MACRO::DataWriter *RegisterPublisher(const std::string &topicName,
|
||||
uint32_t publisherID)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
if (!topics_.contains(topicName)) {
|
||||
topics_[topicName] = TopicInfo();
|
||||
TopicInfo &tmp = topics_[topicName];
|
||||
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];
|
||||
FAST_DDS_MACRO::TypeSupport typeSupport(new T());
|
||||
typeSupport.register_type(participant_);
|
||||
tmp.topic =
|
||||
participant_->create_topic(topicName.toStdString(), typeSupport.get_type_name(),
|
||||
typeSupport.register_type(d->participant_);
|
||||
tmp.topic = d->participant_->create_topic(topicName, typeSupport.get_type_name(),
|
||||
FAST_DDS_MACRO::TOPIC_QOS_DEFAULT);
|
||||
if (tmp.topic == nullptr) {
|
||||
LOG_ERROR("0x2130 Create Topic %1 Failed!", topicName);
|
||||
topics_.remove(topicName);
|
||||
d->topics_.erase(topicName);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
TopicInfo &tmp = topics_[topicName];
|
||||
TopicInfo &tmp = d->topics_[topicName];
|
||||
tmp.publishers_[publisherID] = PublisherInfo();
|
||||
tmp.publishers_[publisherID].publisher =
|
||||
participant_->create_publisher(FAST_DDS_MACRO::PUBLISHER_QOS_DEFAULT, nullptr);
|
||||
d->participant_->create_publisher(FAST_DDS_MACRO::PUBLISHER_QOS_DEFAULT, nullptr);
|
||||
if (tmp.publishers_[publisherID].publisher == nullptr) {
|
||||
LOG_ERROR("0x2131 Create Publisher %1 for Topic %2 Failed!", publisherID, topicName);
|
||||
return nullptr;
|
||||
@ -119,29 +115,28 @@ public:
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void RegisterSubscriber(const QString &topicName, quint32 subscriberID,
|
||||
void RegisterSubscriber(const std::string &topicName, uint32_t subscriberID,
|
||||
std::function<void(const typename T::type &)> fun)
|
||||
{
|
||||
Q_D(XNDDSManager);
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
if (!topics_.contains(topicName)) {
|
||||
topics_[topicName] = TopicInfo();
|
||||
TopicInfo &tmp = topics_[topicName];
|
||||
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];
|
||||
FAST_DDS_MACRO::TypeSupport typeSupport(new T());
|
||||
typeSupport.register_type(participant_);
|
||||
tmp.topic =
|
||||
participant_->create_topic(topicName.toStdString(), typeSupport.get_type_name(),
|
||||
typeSupport.register_type(d->participant_);
|
||||
tmp.topic = d->participant_->create_topic(topicName, typeSupport.get_type_name(),
|
||||
FAST_DDS_MACRO::TOPIC_QOS_DEFAULT);
|
||||
if (tmp.topic == nullptr) {
|
||||
LOG_ERROR("0x2130 Create Topic %1 Failed!", topicName);
|
||||
topics_.remove(topicName);
|
||||
d->topics_.erase(topicName);
|
||||
return;
|
||||
}
|
||||
}
|
||||
TopicInfo &tmp = topics_[topicName];
|
||||
TopicInfo &tmp = d->topics_[topicName];
|
||||
tmp.subscribers_[subscriberID] = SubscriberInfo();
|
||||
tmp.subscribers_[subscriberID].subscriber =
|
||||
participant_->create_subscriber(FAST_DDS_MACRO::SUBSCRIBER_QOS_DEFAULT, nullptr);
|
||||
d->participant_->create_subscriber(FAST_DDS_MACRO::SUBSCRIBER_QOS_DEFAULT, nullptr);
|
||||
if (tmp.subscribers_[subscriberID].subscriber == nullptr) {
|
||||
LOG_ERROR("0x2135 Create Subscriber %1 for Topic %2 Failed!", subscriberID, topicName);
|
||||
}
|
||||
@ -157,9 +152,4 @@ public:
|
||||
}
|
||||
LOG_INFO("0x2137 Create Subscriber %1 for Topic %2 Success!", subscriberID, topicName);
|
||||
}
|
||||
|
||||
private:
|
||||
FAST_DDS_MACRO::DomainParticipant *participant_;
|
||||
QMap<QString, TopicInfo> topics_;
|
||||
std::mutex mutex_;
|
||||
};
|
||||
|
@ -1,15 +0,0 @@
|
||||
#pragma once
|
||||
#include "XNBaseFrameObject_p.h"
|
||||
|
||||
#include <mutex>
|
||||
#include <fastdds/dds/domain/DomainParticipant.hpp>
|
||||
|
||||
struct TopicInfo;
|
||||
|
||||
class XNDDSManagerPrivate : public XNBaseFrameObjectPrivate
|
||||
{
|
||||
public:
|
||||
Q_DECLARE_PUBLIC(XNDDSManager)
|
||||
|
||||
explicit XNDDSManagerPrivate(XNDDSManager *q) : XNBaseFrameObjectPrivate(q) {}
|
||||
};
|
@ -1,76 +1,47 @@
|
||||
#include "XNEventManager.h"
|
||||
#include "XNEventManager_p.h"
|
||||
#include "XNFramework.h"
|
||||
#include <thread>
|
||||
#include <algorithm>
|
||||
|
||||
// 构造函数
|
||||
XNEventManager::XNEventManager(QObject *parent)
|
||||
: XNBaseFrameObject(*new XNEventManagerPrivate(this), parent)
|
||||
XNEventManager::XNEventManager() : XNBaseFrameObject(new XNEventManagerPrivate())
|
||||
{
|
||||
// 设置唯一标识符
|
||||
setUniqueId(7);
|
||||
SetUniqueId(7);
|
||||
// 设置对象名称
|
||||
setObjectName("XNEventManager");
|
||||
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(XNEventManagerPrivate &dd, QObject *parent)
|
||||
: XNBaseFrameObject(dd, parent)
|
||||
XNEventManager::XNEventManager(PrivateType *p) : XNBaseFrameObject(p)
|
||||
{
|
||||
}
|
||||
|
||||
// 添加一个用于异步执行的任务类
|
||||
class EventTask : public QRunnable
|
||||
{
|
||||
public:
|
||||
EventTask(const QString &name, const QVariant &data,
|
||||
std::function<void(const QVariant &)> callback, XNEventManager *manager)
|
||||
: eventName(name), eventData(data), eventCallback(callback), eventManager(manager)
|
||||
{
|
||||
setAutoDelete(true);
|
||||
}
|
||||
|
||||
void run() override
|
||||
{
|
||||
try {
|
||||
eventCallback(eventData);
|
||||
if (eventManager) {
|
||||
QMetaObject::invokeMethod(eventManager, "EventProcessed", Qt::QueuedConnection,
|
||||
Q_ARG(QString, eventName), Q_ARG(bool, true));
|
||||
}
|
||||
} catch (const std::exception &e) {
|
||||
LOG_ERROR(
|
||||
QString("Async event handler exception for %1: %2").arg(eventName).arg(e.what()));
|
||||
if (eventManager) {
|
||||
QMetaObject::invokeMethod(eventManager, "EventProcessed", Qt::QueuedConnection,
|
||||
Q_ARG(QString, eventName), Q_ARG(bool, false));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
QString eventName;
|
||||
QVariant eventData;
|
||||
std::function<void(const QVariant &)> eventCallback;
|
||||
XNEventManager *eventManager;
|
||||
};
|
||||
|
||||
// 修改注册事件处理器的实现
|
||||
int XNEventManager::RegisterEventHandler(const QString &eventName,
|
||||
std::function<void(const QVariant &)> callback,
|
||||
quint32 objectId, bool async, XNEvent::Priority priority)
|
||||
int XNEventManager::RegisterEventHandler(const std::string &eventName, XNEventCallback callback,
|
||||
uint32_t objectId, bool async, XNEvent::Priority priority)
|
||||
{
|
||||
Q_D(XNEventManager);
|
||||
if (eventName.isEmpty() || !callback) {
|
||||
T_D();
|
||||
if (eventName.empty() || !callback) {
|
||||
LOG_WARNING("Invalid event name or callback!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
QMutexLocker locker(&d->eventMutex);
|
||||
std::lock_guard<std::mutex> locker(d->eventMutex);
|
||||
|
||||
// 生成新的本地ID
|
||||
d->localIdCounter = (d->localIdCounter + 1) & 0xFFFF;
|
||||
@ -88,94 +59,94 @@ int XNEventManager::RegisterEventHandler(const QString &eventName,
|
||||
int handlerId = handlerInfo.GetHandlerId();
|
||||
|
||||
// 添加处理器信息到事件列表
|
||||
d->eventHandlers[eventName].append(handlerInfo);
|
||||
d->eventHandlers[eventName].push_back(handlerInfo);
|
||||
// 添加反向映射
|
||||
d->handlerToEvent[handlerId] = eventName;
|
||||
|
||||
LOG_INFO(
|
||||
QString("Registered %1 event handler for event: %2, handler ID: %3 (object: %4, local: %5)")
|
||||
.arg(async ? "async" : "sync")
|
||||
.arg(eventName)
|
||||
.arg(handlerId)
|
||||
.arg(objectId)
|
||||
.arg(d->localIdCounter));
|
||||
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 QString &eventName, int handlerId)
|
||||
bool XNEventManager::RemoveEventHandler(const std::string &eventName, int handlerId)
|
||||
{
|
||||
Q_D(XNEventManager);
|
||||
QMutexLocker locker(&d->eventMutex);
|
||||
T_D();
|
||||
std::lock_guard<std::mutex> locker(d->eventMutex);
|
||||
|
||||
// 如果指定了事件名称,先验证事件是否存在
|
||||
if (!eventName.isEmpty()) {
|
||||
if (!d->eventHandlers.contains(eventName)) {
|
||||
LOG_WARNING(QString("Event %1 not found!").arg(eventName));
|
||||
if (!eventName.empty()) {
|
||||
auto it = d->eventHandlers.find(eventName);
|
||||
if (it == d->eventHandlers.end()) {
|
||||
LOG_WARNING("Event " + eventName + " not found!");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 查找并移除指定的处理器
|
||||
auto &handlers = d->eventHandlers[eventName];
|
||||
for (auto it = handlers.begin(); it != handlers.end(); ++it) {
|
||||
if (it->GetHandlerId() == handlerId) {
|
||||
handlers.erase(it);
|
||||
d->handlerToEvent.remove(handlerId);
|
||||
LOG_INFO(
|
||||
QString("Removed handler ID %1 from event: %2").arg(handlerId).arg(eventName));
|
||||
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.isEmpty()) {
|
||||
d->eventHandlers.remove(eventName);
|
||||
if (handlers.empty()) {
|
||||
d->eventHandlers.erase(it);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
LOG_WARNING(QString("Handler ID %1 not found in event: %2").arg(handlerId).arg(eventName));
|
||||
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()) {
|
||||
QString eventToRemove = eventIt.value();
|
||||
std::string eventToRemove = eventIt->second;
|
||||
auto &handlers = d->eventHandlers[eventToRemove];
|
||||
|
||||
for (auto it = handlers.begin(); it != handlers.end(); ++it) {
|
||||
if (it->GetHandlerId() == handlerId) {
|
||||
handlers.erase(it);
|
||||
d->handlerToEvent.remove(handlerId);
|
||||
LOG_INFO(QString("Removed handler ID %1 from event: %2")
|
||||
.arg(handlerId)
|
||||
.arg(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.isEmpty()) {
|
||||
d->eventHandlers.remove(eventToRemove);
|
||||
if (handlers.empty()) {
|
||||
d->eventHandlers.erase(eventToRemove);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LOG_WARNING(QString("Handler ID %1 not found!").arg(handlerId));
|
||||
LOG_WARNING("Handler ID " + std::to_string(handlerId) + " not found!");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 修改触发事件的实现
|
||||
void XNEventManager::TriggerEvent(const QString &eventName, const QVariant &eventData,
|
||||
void XNEventManager::TriggerEvent(const std::string &eventName, const std::any &eventData,
|
||||
bool forceAsync, XNEvent::Priority priority)
|
||||
{
|
||||
Q_D(XNEventManager);
|
||||
|
||||
QList<EventHandlerInfo> handlers;
|
||||
T_D();
|
||||
std::list<EventHandlerInfo> handlers;
|
||||
{
|
||||
QMutexLocker locker(&d->eventMutex);
|
||||
if (!d->eventHandlers.contains(eventName)) {
|
||||
//LOG_WARNING(QString("No handlers registered for event: %1").arg(eventName));
|
||||
std::lock_guard<std::mutex> locker(d->eventMutex);
|
||||
auto it = d->eventHandlers.find(eventName);
|
||||
if (it == d->eventHandlers.end()) {
|
||||
return;
|
||||
}
|
||||
handlers = d->eventHandlers[eventName];
|
||||
handlers = it->second;
|
||||
}
|
||||
|
||||
for (const auto &handler : handlers) {
|
||||
@ -186,54 +157,85 @@ void XNEventManager::TriggerEvent(const QString &eventName, const QVariant &even
|
||||
d->rtManager.addTask(task);
|
||||
} else {
|
||||
// 普通异步任务使用线程池
|
||||
d->normalThreadPool.start(
|
||||
new EventTask(eventName, eventData, handler.callback, this));
|
||||
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);
|
||||
emit EventProcessed(eventName, true);
|
||||
EventProcessed(eventName, true);
|
||||
} catch (const std::exception &e) {
|
||||
LOG_ERROR(QString("Exception in handler %1 for event %2: %3")
|
||||
.arg(handler.GetHandlerId())
|
||||
.arg(eventName)
|
||||
.arg(e.what()));
|
||||
emit EventProcessed(eventName, false);
|
||||
LOG_ERROR("Exception in handler " + std::to_string(handler.GetHandlerId())
|
||||
+ " for event " + eventName + ": " + e.what());
|
||||
EventProcessed(eventName, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//LOG_INFO(QString("Triggered event: %1 with %2 handlers").arg(eventName).arg(handlers.size()));
|
||||
}
|
||||
|
||||
void XNEventManager::SetMaxThreadCount(int count)
|
||||
{
|
||||
Q_D(XNEventManager);
|
||||
d->threadPool.setMaxThreadCount(count);
|
||||
LOG_INFO(QString("Set thread pool max thread count to %1").arg(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
|
||||
{
|
||||
Q_D(const XNEventManager);
|
||||
return d->threadPool.maxThreadCount();
|
||||
T_D();
|
||||
std::lock_guard<std::mutex> lock(d->taskMutex);
|
||||
return d->workerThreads.size();
|
||||
}
|
||||
|
||||
void XNEventManager::WaitForAsyncEvents()
|
||||
{
|
||||
Q_D(XNEventManager);
|
||||
d->threadPool.waitForDone();
|
||||
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");
|
||||
}
|
||||
|
||||
// 初始化事件管理器
|
||||
void XNEventManager::OnInitialize()
|
||||
bool XNEventManager::Initialize()
|
||||
{
|
||||
Q_D(XNEventManager);
|
||||
|
||||
T_D();
|
||||
// 配置普通线程池
|
||||
d->threadPool.setMaxThreadCount(QThread::idealThreadCount());
|
||||
SetMaxThreadCount(std::thread::hardware_concurrency());
|
||||
|
||||
// 配置实时线程池
|
||||
SetRTThreadPoolConfig(2, // 最大线程数
|
||||
@ -242,32 +244,30 @@ void XNEventManager::OnInitialize()
|
||||
|
||||
LOG_INFO("XNEventManager Initialize Success!");
|
||||
d->_status = XNFrameObjectStatus::Initialized;
|
||||
emit Initialize();
|
||||
return true;
|
||||
}
|
||||
|
||||
// 准备执行
|
||||
void XNEventManager::OnPrepareForExecute()
|
||||
bool XNEventManager::PrepareForExecute()
|
||||
{
|
||||
Q_D(XNEventManager);
|
||||
// 设置状态为就绪
|
||||
T_D();
|
||||
d->_status = XNFrameObjectStatus::Ready;
|
||||
LOG_INFO("XNEventManager is prepared!");
|
||||
// 发送准备完成信号
|
||||
emit PrepareForExecute();
|
||||
return true;
|
||||
}
|
||||
|
||||
void XNEventManager::SetRTThreadPoolConfig(int maxThreads, int minPriority, int maxPriority)
|
||||
{
|
||||
Q_D(XNEventManager);
|
||||
T_D();
|
||||
d->rtManager.stop();
|
||||
|
||||
XNFramework *framework = qobject_cast<XNFramework *>(parent());
|
||||
if (framework == nullptr) {
|
||||
XNFrameworkPtr framework = GetFramework();
|
||||
if (!framework) {
|
||||
LOG_WARNING("XNFramework is nullptr!");
|
||||
return;
|
||||
}
|
||||
|
||||
quint32 cpuAffinity = framework->GetCpuAffinity();
|
||||
uint32_t cpuAffinity = framework->GetCpuAffinity();
|
||||
|
||||
// 找到最后一个可用的CPU
|
||||
int lastCpu = -1;
|
||||
@ -281,8 +281,15 @@ void XNEventManager::SetRTThreadPoolConfig(int maxThreads, int minPriority, int
|
||||
LOG_WARNING("No available CPU found in affinity mask, using default CPU 1");
|
||||
lastCpu = 1;
|
||||
} else {
|
||||
LOG_INFO(QString("RT thread bound to CPU %1").arg(lastCpu));
|
||||
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"));
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
#include "XNBaseFrameObject.h"
|
||||
#include <QVariant>
|
||||
|
||||
// 事件优先级定义
|
||||
namespace XNEvent
|
||||
{
|
||||
@ -11,19 +11,18 @@ enum class Priority {
|
||||
Low = 3 // 低优先级
|
||||
};
|
||||
}
|
||||
|
||||
// 前向声明私有类
|
||||
class XNEventManagerPrivate;
|
||||
struct XNEventManagerPrivate;
|
||||
|
||||
// 事件管理器类,继承自XNBaseFrameObject
|
||||
class XNEventManager : public XNBaseFrameObject
|
||||
{
|
||||
Q_OBJECT // 启用Qt的元对象系统
|
||||
Q_DECLARE_PRIVATE(XNEventManager) // 声明私有实现类
|
||||
Q_DISABLE_COPY(XNEventManager) // 禁用拷贝构造和赋值操作
|
||||
|
||||
XN_METATYPE(XNEventManager, XNBaseFrameObject)
|
||||
XN_DECLARE_PRIVATE(XNEventManager)
|
||||
public:
|
||||
// 构造函数,创建事件管理器实例
|
||||
explicit XNEventManager(QObject *parent = nullptr);
|
||||
XNEventManager();
|
||||
// 析构函数
|
||||
~XNEventManager();
|
||||
|
||||
@ -34,21 +33,20 @@ class XNEventManager : public XNBaseFrameObject
|
||||
// @param async: 是否异步处理该事件
|
||||
// @param priority: 事件优先级
|
||||
// @return: 返回处理器ID,失败返回-1
|
||||
int RegisterEventHandler(const QString &eventName,
|
||||
std::function<void(const QVariant &)> callback, quint32 objectId,
|
||||
bool async = false,
|
||||
int RegisterEventHandler(const std::string &eventName, XNEventCallback callback,
|
||||
uint32_t objectId, bool async = false,
|
||||
XNEvent::Priority priority = XNEvent::Priority::Normal);
|
||||
// 移除事件处理器
|
||||
// @param eventName: 事件名称
|
||||
// @param handlerId: 处理器ID
|
||||
// @return: 移除是否成功
|
||||
bool RemoveEventHandler(const QString &eventName, int handlerId);
|
||||
bool RemoveEventHandler(const std::string &eventName, int handlerId);
|
||||
// 触发指定事件
|
||||
// @param eventName: 要触发的事件名称
|
||||
// @param eventData: 事件携带的数据
|
||||
// @param forceAsync: 强制异步处理
|
||||
// @param priority: 事件优先级
|
||||
void TriggerEvent(const QString &eventName, const QVariant &eventData = QVariant(),
|
||||
void TriggerEvent(const std::string &eventName, const std::any &eventData = std::any(),
|
||||
bool forceAsync = false,
|
||||
XNEvent::Priority priority = XNEvent::Priority::Normal);
|
||||
|
||||
@ -64,17 +62,16 @@ class XNEventManager : public XNBaseFrameObject
|
||||
// 设置实时线程池参数
|
||||
void SetRTThreadPoolConfig(int maxThreads, int minPriority, int maxPriority);
|
||||
|
||||
// 事件处理完成回调
|
||||
void EventProcessed(const std::string &eventName, bool success);
|
||||
|
||||
protected:
|
||||
// 保护构造函数,用于继承实现
|
||||
XNEventManager(XNEventManagerPrivate &dd, QObject *parent = nullptr);
|
||||
XNEventManager(PrivateType *p);
|
||||
|
||||
public slots:
|
||||
public:
|
||||
// 初始化事件管理器
|
||||
virtual void OnInitialize() override;
|
||||
virtual bool Initialize() override;
|
||||
// 准备执行
|
||||
virtual void OnPrepareForExecute() override;
|
||||
|
||||
signals:
|
||||
// 事件处理完成信号
|
||||
void EventProcessed(const QString &eventName, bool success);
|
||||
virtual bool PrepareForExecute() override;
|
||||
};
|
@ -1,9 +1,6 @@
|
||||
#pragma once
|
||||
#include "XNBaseFrameObject_p.h"
|
||||
#include "XNEventManager.h"
|
||||
#include <QMap>
|
||||
#include <QMutex>
|
||||
#include <QThreadPool>
|
||||
#include <functional>
|
||||
#include <sys/types.h>
|
||||
#include <bits/pthreadtypes.h>
|
||||
@ -12,78 +9,130 @@
|
||||
#include <queue>
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
#include <string>
|
||||
#include <any>
|
||||
#include <map>
|
||||
#include <list>
|
||||
|
||||
// 事件处理器信息结构
|
||||
struct EventHandlerInfo {
|
||||
std::function<void(const QVariant &)> callback; // 回调函数
|
||||
quint32 objectId; // 对象ID
|
||||
int localId; // 本地ID
|
||||
std::function<void(const std::any &)> callback; // 回调函数
|
||||
uint32_t objectId; // 对象ID
|
||||
uint32_t localId; // 本地ID
|
||||
bool isAsync; // 是否异步处理
|
||||
XNEvent::Priority priority; // 事件优先级
|
||||
int threadPriority; // 线程优先级
|
||||
uint32_t threadPriority; // 线程优先级
|
||||
|
||||
// 获取全局处理器ID
|
||||
int GetHandlerId() const { return (objectId << 16) | (localId & 0xFFFF); }
|
||||
uint32_t GetHandlerId() const { return (objectId << 16) | (localId & 0xFFFF); }
|
||||
|
||||
// 从全局处理器ID中提取对象ID
|
||||
static quint32 GetObjectId(int handlerId) { return handlerId >> 16; }
|
||||
static uint32_t GetObjectId(uint32_t handlerId) { return handlerId >> 16; }
|
||||
|
||||
// 从全局处理器ID中提取本地ID
|
||||
static int GetLocalId(int handlerId) { return handlerId & 0xFFFF; }
|
||||
static uint32_t GetLocalId(uint32_t handlerId) { return handlerId & 0xFFFF; }
|
||||
};
|
||||
|
||||
// 事件任务基类
|
||||
class BaseEventTask : public QRunnable
|
||||
class BaseEventTask
|
||||
{
|
||||
public:
|
||||
BaseEventTask(const QString &name, const QVariant &data,
|
||||
std::function<void(const QVariant &)> callback, XNEventManager *manager)
|
||||
/**
|
||||
* @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)
|
||||
{
|
||||
setAutoDelete(true);
|
||||
}
|
||||
virtual ~BaseEventTask() = default;
|
||||
|
||||
/**
|
||||
* @brief 执行任务
|
||||
*/
|
||||
virtual void execute() = 0;
|
||||
|
||||
protected:
|
||||
QString eventName;
|
||||
QVariant eventData;
|
||||
std::function<void(const QVariant &)> eventCallback;
|
||||
std::string eventName;
|
||||
std::any eventData;
|
||||
std::function<void(const std::any &)> eventCallback;
|
||||
XNEventManager *eventManager;
|
||||
};
|
||||
|
||||
// 实时事件任务
|
||||
class RTEventTask
|
||||
// 异步事件任务
|
||||
class AsyncEventTask : public BaseEventTask
|
||||
{
|
||||
public:
|
||||
RTEventTask(const QString &name, const QVariant &data,
|
||||
std::function<void(const QVariant &)> callback, XNEventManager *manager)
|
||||
: eventName(name), eventData(data), eventCallback(callback), eventManager(manager)
|
||||
/**
|
||||
* @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)
|
||||
{
|
||||
}
|
||||
|
||||
void execute()
|
||||
/**
|
||||
* @brief 执行任务
|
||||
*/
|
||||
void execute() override
|
||||
{
|
||||
try {
|
||||
eventCallback(eventData);
|
||||
if (eventManager) {
|
||||
QMetaObject::invokeMethod(eventManager, "EventProcessed", Qt::QueuedConnection,
|
||||
Q_ARG(QString, eventName), Q_ARG(bool, true));
|
||||
eventManager->EventProcessed(eventName, true);
|
||||
}
|
||||
} catch (const std::exception &e) {
|
||||
LOG_ERROR(
|
||||
QString("RT event handler exception for %1: %2").arg(eventName).arg(e.what()));
|
||||
LOG_ERROR("Async event handler exception for " + eventName + ": " + e.what());
|
||||
if (eventManager) {
|
||||
QMetaObject::invokeMethod(eventManager, "EventProcessed", Qt::QueuedConnection,
|
||||
Q_ARG(QString, eventName), Q_ARG(bool, false));
|
||||
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)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
QString eventName;
|
||||
QVariant eventData;
|
||||
std::function<void(const QVariant &)> eventCallback;
|
||||
XNEventManager *eventManager;
|
||||
/**
|
||||
* @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);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 实时线程管理器
|
||||
@ -167,35 +216,27 @@ private:
|
||||
};
|
||||
|
||||
// 事件管理器的私有实现类
|
||||
class XNEventManagerPrivate : public XNBaseFrameObjectPrivate
|
||||
{
|
||||
public:
|
||||
// 声明公共接口类
|
||||
Q_DECLARE_PUBLIC(XNEventManager)
|
||||
|
||||
// 构造函数,初始化私有实现
|
||||
explicit XNEventManagerPrivate(XNEventManager *q) : XNBaseFrameObjectPrivate(q) {}
|
||||
|
||||
struct XNEventManagerPrivate : public XNBaseFrameObjectPrivate {
|
||||
// 存储事件及其对应的处理器信息列表
|
||||
// key: 事件名称
|
||||
// value: 该事件对应的所有处理器信息列表
|
||||
QMap<QString, QList<EventHandlerInfo>> eventHandlers;
|
||||
std::map<std::string, std::list<EventHandlerInfo>> eventHandlers;
|
||||
|
||||
// 处理器ID到事件名称的反向映射,用于快速查找
|
||||
QMap<int, QString> handlerToEvent;
|
||||
std::map<int, std::string> handlerToEvent;
|
||||
|
||||
// 本地ID计数器
|
||||
int localIdCounter = 0;
|
||||
|
||||
// 互斥锁,用于保护事件处理器表的线程安全访问
|
||||
QMutex eventMutex;
|
||||
std::mutex eventMutex;
|
||||
|
||||
// 线程池,用于异步执行事件处理器
|
||||
QThreadPool threadPool;
|
||||
|
||||
// 实时线程池
|
||||
QThreadPool rtThreadPool;
|
||||
// 线程池相关
|
||||
std::vector<std::thread> workerThreads;
|
||||
std::queue<BaseEventTask *> taskQueue;
|
||||
std::mutex taskMutex;
|
||||
std::condition_variable taskCond;
|
||||
bool running = true;
|
||||
|
||||
RTThreadManager rtManager;
|
||||
QThreadPool normalThreadPool; // 用于非实时任务
|
||||
};
|
||||
|
@ -9,130 +9,28 @@
|
||||
#include "XNServiceManager.h"
|
||||
#include "XNEventManager.h"
|
||||
|
||||
XNFramework::XNFramework(QObject *parent) : XNObject(*new XNFrameworkPrivate(this), parent)
|
||||
XNFramework::XNFramework() : XNObject(new XNFrameworkPrivate())
|
||||
{
|
||||
setObjectName("XNFramework");
|
||||
setUniqueId(1);
|
||||
XNTimeManager *timeManager = new XNTimeManager(this);
|
||||
XNThreadManager *threadManager = new XNThreadManager(this);
|
||||
XNScenarioManager *scenarioManager = new XNScenarioManager(this);
|
||||
XNDDSManager *ddsManager = new XNDDSManager(this);
|
||||
XNModelManager *modelManager = new XNModelManager(this);
|
||||
XNServiceManager *serviceManager = new XNServiceManager(this);
|
||||
XNEventManager *eventManager = new XNEventManager(this);
|
||||
|
||||
//链接各组件初始化信号槽,依次链接,回告完成
|
||||
connect(this, &XNFramework::Initialize, eventManager, &XNEventManager::OnInitialize);
|
||||
connect(eventManager, &XNEventManager::Initialize, timeManager, &XNTimeManager::OnInitialize);
|
||||
connect(timeManager, &XNTimeManager::Initialize, ddsManager, &XNDDSManager::OnInitialize);
|
||||
connect(ddsManager, &XNDDSManager::Initialize, serviceManager, &XNServiceManager::OnInitialize);
|
||||
connect(serviceManager, &XNServiceManager::Initialize, threadManager,
|
||||
&XNThreadManager::OnInitialize);
|
||||
connect(threadManager, &XNThreadManager::Initialize, modelManager,
|
||||
&XNModelManager::OnInitialize);
|
||||
connect(modelManager, &XNModelManager::Initialize, scenarioManager,
|
||||
&XNScenarioManager::OnInitialize);
|
||||
connect(modelManager, &XNModelManager::InitializeSuccess, this,
|
||||
&XNFramework::OnInitializeSuccess);
|
||||
|
||||
//连接各组件初始化失败信号到框架的槽
|
||||
connect(eventManager, &XNEventManager::InitializeFailed, this,
|
||||
&XNFramework::OnInitializeFailed);
|
||||
connect(timeManager, &XNTimeManager::InitializeFailed, this, &XNFramework::OnInitializeFailed);
|
||||
connect(ddsManager, &XNDDSManager::InitializeFailed, this, &XNFramework::OnInitializeFailed);
|
||||
connect(serviceManager, &XNServiceManager::InitializeFailed, this,
|
||||
&XNFramework::OnInitializeFailed);
|
||||
connect(threadManager, &XNThreadManager::InitializeFailed, this,
|
||||
&XNFramework::OnInitializeFailed);
|
||||
connect(modelManager, &XNModelManager::InitializeFailed, this,
|
||||
&XNFramework::OnInitializeFailed);
|
||||
connect(scenarioManager, &XNScenarioManager::InitializeFailed, this,
|
||||
&XNFramework::OnInitializeFailed);
|
||||
|
||||
//连接解析配置文件信号到框架的槽
|
||||
connect(scenarioManager, &XNScenarioManager::AnalyzeScenarioXmlFailed, this,
|
||||
&XNFramework::OnAnalyzeScenarioXmlFailed);
|
||||
connect(scenarioManager, &XNScenarioManager::AnalyzeScenarioXmlSuccess, this,
|
||||
&XNFramework::OnAnalyzeScenarioXmlSuccess);
|
||||
|
||||
//链接各组件准备执行信号槽
|
||||
connect(this, &XNFramework::PrepareForExecute, eventManager,
|
||||
&XNEventManager::OnPrepareForExecute);
|
||||
connect(eventManager, &XNEventManager::PrepareForExecute, timeManager,
|
||||
&XNTimeManager::OnPrepareForExecute);
|
||||
connect(timeManager, &XNTimeManager::PrepareForExecute, ddsManager,
|
||||
&XNDDSManager::OnPrepareForExecute);
|
||||
connect(ddsManager, &XNDDSManager::PrepareForExecute, serviceManager,
|
||||
&XNServiceManager::OnPrepareForExecute);
|
||||
connect(serviceManager, &XNServiceManager::PrepareForExecute, threadManager,
|
||||
&XNThreadManager::OnPrepareForExecute);
|
||||
connect(threadManager, &XNThreadManager::PrepareForExecute, modelManager,
|
||||
&XNModelManager::OnPrepareForExecute);
|
||||
connect(modelManager, &XNModelManager::PrepareForExecute, scenarioManager,
|
||||
&XNScenarioManager::OnPrepareForExecute);
|
||||
connect(modelManager, &XNModelManager::PrepareForExecuteSuccess, this,
|
||||
&XNFramework::OnPrepareForExecuteSuccess);
|
||||
|
||||
//连接准备执行失败的槽
|
||||
connect(eventManager, &XNEventManager::PrepareForExecuteFailed, this,
|
||||
&XNFramework::OnPrepareForExecuteFailed);
|
||||
connect(timeManager, &XNTimeManager::PrepareForExecuteFailed, this,
|
||||
&XNFramework::OnPrepareForExecuteFailed);
|
||||
connect(ddsManager, &XNDDSManager::PrepareForExecuteFailed, this,
|
||||
&XNFramework::OnPrepareForExecuteFailed);
|
||||
connect(serviceManager, &XNServiceManager::PrepareForExecuteFailed, this,
|
||||
&XNFramework::OnPrepareForExecuteFailed);
|
||||
connect(threadManager, &XNThreadManager::PrepareForExecuteFailed, this,
|
||||
&XNFramework::OnPrepareForExecuteFailed);
|
||||
connect(modelManager, &XNModelManager::PrepareForExecuteFailed, this,
|
||||
&XNFramework::OnPrepareForExecuteFailed);
|
||||
connect(scenarioManager, &XNScenarioManager::PrepareForExecuteFailed, this,
|
||||
&XNFramework::OnPrepareForExecuteFailed);
|
||||
|
||||
//threadManager的设置开始时间信号触发timeManager的设置开始时间槽
|
||||
connect(threadManager, &XNThreadManager::SetStartTime, timeManager,
|
||||
&XNTimeManager::OnSetStartTime);
|
||||
//framework的仿真控制信号触发timeManager的仿真控制槽
|
||||
connect(this, &XNFramework::SimControl, timeManager, &XNTimeManager::OnSimControl);
|
||||
//timeManager的仿真控制信号触发threadManager的仿真控制槽
|
||||
connect(timeManager, &XNTimeManager::SimControl, threadManager, &XNThreadManager::OnSimControl);
|
||||
//scenarioManager的分析场景XML信号触发framework的分析场景XML槽
|
||||
connect(this, &XNFramework::AnalyzeScenarioXml, scenarioManager,
|
||||
&XNScenarioManager::AnalysisScenarioXml);
|
||||
//scenarioManager的添加线程池信号触发threadManager的添加线程池槽
|
||||
connect(scenarioManager, &XNScenarioManager::AddThreadPool, threadManager,
|
||||
&XNThreadManager::OnAddThreadPool);
|
||||
//scenarioManager的加载模型信号触发modelManager的加载模型槽
|
||||
connect(scenarioManager, &XNScenarioManager::LoadModel, modelManager,
|
||||
&XNModelManager::OnLoadModel);
|
||||
//scenarioManager的加载服务信号触发serviceManager的加载服务槽
|
||||
connect(scenarioManager, &XNScenarioManager::LoadService, serviceManager,
|
||||
&XNServiceManager::OnLoadService);
|
||||
//scenarioManager的设置工作路径信号触发framework的设置工作路径槽
|
||||
connect(scenarioManager, &XNScenarioManager::SetWorkPath, this, &XNFramework::SetWorkPath);
|
||||
//scenarioManager的设置模型路径信号触发framework的设置模型路径槽
|
||||
connect(scenarioManager, &XNScenarioManager::SetModelPath, this, &XNFramework::SetModelPath);
|
||||
//scenarioManager的设置服务路径信号触发framework的设置服务路径槽
|
||||
connect(scenarioManager, &XNScenarioManager::SetServicePath, this,
|
||||
&XNFramework::SetServicePath);
|
||||
//scenarioManager的设置CPU亲和性信号触发framework的设置CPU亲和性槽
|
||||
connect(scenarioManager, &XNScenarioManager::SetCpuAffinity, this,
|
||||
&XNFramework::SetCpuAffinity);
|
||||
//scenarioManager的设置基频信号触发threadManager的设置基频槽
|
||||
connect(scenarioManager, &XNScenarioManager::SetBaseFreq, threadManager,
|
||||
&XNThreadManager::OnSetBaseFreq);
|
||||
//scenarioManager的设置基频信号触发modelManager的设置基频槽
|
||||
connect(scenarioManager, &XNScenarioManager::SetBaseFreq, modelManager,
|
||||
&XNModelManager::OnSetBaseFreq);
|
||||
//modelManager的注册函数信号触发threadManager的注册函数槽
|
||||
connect(modelManager, &XNModelManager::RegisterFunction, threadManager,
|
||||
&XNThreadManager::OnRegisterFunction);
|
||||
//scenarioManager的设置DDS域ID信号触发ddsManager的设置DDS域ID槽
|
||||
connect(scenarioManager, &XNScenarioManager::SetDomainID, ddsManager,
|
||||
&XNDDSManager::SetDomainID);
|
||||
SetObjectName("XNFramework");
|
||||
SetUniqueId(1);
|
||||
T_D();
|
||||
d->timeManager = std::make_shared<XNTimeManager>();
|
||||
d->threadManager = std::make_shared<XNThreadManager>();
|
||||
d->scenarioManager = std::make_shared<XNScenarioManager>();
|
||||
d->ddsManager = std::make_shared<XNDDSManager>();
|
||||
d->modelManager = std::make_shared<XNModelManager>();
|
||||
d->serviceManager = std::make_shared<XNServiceManager>();
|
||||
d->eventManager = std::make_shared<XNEventManager>();
|
||||
d->ddsManager->SetFramework(XN_THISPTR);
|
||||
d->timeManager->SetFramework(XN_THISPTR);
|
||||
d->threadManager->SetFramework(XN_THISPTR);
|
||||
d->scenarioManager->SetFramework(XN_THISPTR);
|
||||
d->modelManager->SetFramework(XN_THISPTR);
|
||||
d->serviceManager->SetFramework(XN_THISPTR);
|
||||
d->eventManager->SetFramework(XN_THISPTR);
|
||||
}
|
||||
|
||||
XNFramework::XNFramework(XNFrameworkPrivate &dd, QObject *parent) : XNObject(dd, parent)
|
||||
XNFramework::XNFramework(PrivateType *p) : XNObject(p)
|
||||
{
|
||||
}
|
||||
|
||||
@ -140,114 +38,196 @@ XNFramework::~XNFramework()
|
||||
{
|
||||
}
|
||||
|
||||
QString XNFramework::GetWorkPath()
|
||||
std::string XNFramework::GetWorkPath()
|
||||
{
|
||||
Q_D(XNFramework);
|
||||
T_D();
|
||||
return d->workPath;
|
||||
}
|
||||
|
||||
void XNFramework::SetWorkPath(const QString &workPath)
|
||||
void XNFramework::SetWorkPath(const std::string &workPath)
|
||||
{
|
||||
Q_D(XNFramework);
|
||||
T_D();
|
||||
d->workPath = workPath;
|
||||
}
|
||||
|
||||
QString XNFramework::GetModelPath()
|
||||
std::string XNFramework::GetModelPath()
|
||||
{
|
||||
Q_D(XNFramework);
|
||||
T_D();
|
||||
return d->modelPath;
|
||||
}
|
||||
|
||||
void XNFramework::SetModelPath(const QString &modelPath)
|
||||
void XNFramework::SetModelPath(const std::string &modelPath)
|
||||
{
|
||||
Q_D(XNFramework);
|
||||
T_D();
|
||||
d->modelPath = modelPath;
|
||||
}
|
||||
|
||||
QString XNFramework::GetServicePath()
|
||||
std::string XNFramework::GetServicePath()
|
||||
{
|
||||
Q_D(XNFramework);
|
||||
T_D();
|
||||
return d->servicePath;
|
||||
}
|
||||
|
||||
void XNFramework::SetServicePath(const QString &servicePath)
|
||||
void XNFramework::SetServicePath(const std::string &servicePath)
|
||||
{
|
||||
Q_D(XNFramework);
|
||||
T_D();
|
||||
d->servicePath = servicePath;
|
||||
}
|
||||
|
||||
quint32 XNFramework::GetCpuAffinity()
|
||||
uint32_t XNFramework::GetCpuAffinity()
|
||||
{
|
||||
Q_D(XNFramework);
|
||||
T_D();
|
||||
return d->uCpuAffinity;
|
||||
}
|
||||
|
||||
void XNFramework::SetCpuAffinity(quint32 cpuAffinity)
|
||||
void XNFramework::SetCpuAffinity(uint32_t cpuAffinity)
|
||||
{
|
||||
Q_D(XNFramework);
|
||||
T_D();
|
||||
d->uCpuAffinity = cpuAffinity;
|
||||
}
|
||||
|
||||
void XNFramework::OnInitialize()
|
||||
void XNFramework::Initialize()
|
||||
{
|
||||
Q_D(XNFramework);
|
||||
T_D();
|
||||
LOG_INFO("XNFramework Initialize ...");
|
||||
emit Initialize();
|
||||
bool ret = d->eventManager->Initialize();
|
||||
if (!ret) {
|
||||
LOG_ERROR("XNFramework Initialize Failed!");
|
||||
return;
|
||||
}
|
||||
ret = d->timeManager->Initialize();
|
||||
if (!ret) {
|
||||
LOG_ERROR("XNFramework Initialize Failed!");
|
||||
return;
|
||||
}
|
||||
ret = d->ddsManager->Initialize();
|
||||
if (!ret) {
|
||||
LOG_ERROR("XNFramework Initialize Failed!");
|
||||
return;
|
||||
}
|
||||
ret = d->serviceManager->Initialize();
|
||||
if (!ret) {
|
||||
LOG_ERROR("XNFramework Initialize Failed!");
|
||||
return;
|
||||
}
|
||||
ret = d->threadManager->Initialize();
|
||||
if (!ret) {
|
||||
LOG_ERROR("XNFramework Initialize Failed!");
|
||||
return;
|
||||
}
|
||||
ret = d->modelManager->Initialize();
|
||||
if (!ret) {
|
||||
LOG_ERROR("XNFramework Initialize Failed!");
|
||||
return;
|
||||
}
|
||||
ret = d->scenarioManager->Initialize();
|
||||
if (!ret) {
|
||||
LOG_ERROR("XNFramework Initialize Failed!");
|
||||
return;
|
||||
}
|
||||
LOG_INFO("XNFramework Initialize Success!");
|
||||
LOG_INFO("XNFramework Analyze Scenario Xml ...");
|
||||
ret = d->scenarioManager->AnalysisScenarioXml(d->scenarioXml);
|
||||
if (!ret) {
|
||||
LOG_ERROR("XNFramework Analyze Scenario Xml Failed!");
|
||||
return;
|
||||
}
|
||||
LOG_INFO("XNFramework Analyze Scenario Xml Success!");
|
||||
}
|
||||
|
||||
void XNFramework::OnPrepareForExecute()
|
||||
void XNFramework::PrepareForExecute()
|
||||
{
|
||||
Q_D(XNFramework);
|
||||
emit PrepareForExecute();
|
||||
T_D();
|
||||
|
||||
bool ret = d->eventManager->PrepareForExecute();
|
||||
if (!ret) {
|
||||
LOG_ERROR("XNFramework PrepareForExecute Failed!");
|
||||
return;
|
||||
}
|
||||
ret = d->timeManager->PrepareForExecute();
|
||||
if (!ret) {
|
||||
LOG_ERROR("XNFramework PrepareForExecute Failed!");
|
||||
return;
|
||||
}
|
||||
ret = d->ddsManager->PrepareForExecute();
|
||||
if (!ret) {
|
||||
LOG_ERROR("XNFramework PrepareForExecute Failed!");
|
||||
return;
|
||||
}
|
||||
ret = d->serviceManager->PrepareForExecute();
|
||||
if (!ret) {
|
||||
LOG_ERROR("XNFramework PrepareForExecute Failed!");
|
||||
return;
|
||||
}
|
||||
ret = d->threadManager->PrepareForExecute();
|
||||
if (!ret) {
|
||||
LOG_ERROR("XNFramework PrepareForExecute Failed!");
|
||||
return;
|
||||
}
|
||||
ret = d->modelManager->PrepareForExecute();
|
||||
if (!ret) {
|
||||
LOG_ERROR("XNFramework PrepareForExecute Failed!");
|
||||
return;
|
||||
}
|
||||
ret = d->scenarioManager->PrepareForExecute();
|
||||
if (!ret) {
|
||||
LOG_ERROR("XNFramework PrepareForExecute Failed!");
|
||||
return;
|
||||
}
|
||||
LOG_INFO("XNCore is prepared for execute! Simulation will start soon...");
|
||||
}
|
||||
|
||||
void XNFramework::SetScenarioXml(const QString &scenarioXml)
|
||||
void XNFramework::SetScenarioXml(const std::string &scenarioXml)
|
||||
{
|
||||
Q_D(XNFramework);
|
||||
T_D();
|
||||
d->scenarioXml = scenarioXml;
|
||||
}
|
||||
|
||||
void XNFramework::OnInitializeSuccess()
|
||||
void XNFramework::SimControl(uint32_t objectId, SimControlCmd cmd)
|
||||
{
|
||||
Q_D(XNFramework);
|
||||
LOG_INFO("XNFramework Initialize Success!");
|
||||
LOG_INFO("XNFramework Analyze Scenario Xml ...");
|
||||
emit AnalyzeScenarioXml(d->scenarioXml);
|
||||
T_D();
|
||||
d->timeManager->SimControl(objectId, cmd);
|
||||
d->threadManager->SimControl(objectId, cmd);
|
||||
}
|
||||
|
||||
void XNFramework::OnInitializeFailed()
|
||||
XNTimeManagerPtr XNFramework::GetTimeManager()
|
||||
{
|
||||
LOG_INFO("XNFramework Initialize Failed!");
|
||||
emit InitializeSuccess(false);
|
||||
T_D();
|
||||
return d->timeManager;
|
||||
}
|
||||
|
||||
void XNFramework::OnAnalyzeScenarioXmlSuccess()
|
||||
XNThreadManagerPtr XNFramework::GetThreadManager()
|
||||
{
|
||||
LOG_INFO("XNFramework Analyze Scenario Xml Success!");
|
||||
emit InitializeSuccess(true);
|
||||
T_D();
|
||||
return d->threadManager;
|
||||
}
|
||||
|
||||
void XNFramework::OnAnalyzeScenarioXmlFailed()
|
||||
XNScenarioManagerPtr XNFramework::GetScenarioManager()
|
||||
{
|
||||
LOG_INFO("XNFramework Analyze Scenario Xml Failed!");
|
||||
emit InitializeSuccess(false);
|
||||
T_D();
|
||||
return d->scenarioManager;
|
||||
}
|
||||
|
||||
void XNFramework::OnPrepareForExecuteSuccess()
|
||||
XNDDSManagerPtr XNFramework::GetDDSManager()
|
||||
{
|
||||
Q_D(XNFramework);
|
||||
LOG_INFO("XNCore is prepared for execute! Simulation will start soon...");
|
||||
emit PrepareForExecuteSuccess(true);
|
||||
T_D();
|
||||
return d->ddsManager;
|
||||
}
|
||||
|
||||
void XNFramework::OnPrepareForExecuteFailed()
|
||||
XNEventManagerPtr XNFramework::GetEventManager()
|
||||
{
|
||||
Q_D(XNFramework);
|
||||
LOG_INFO("XNCore is failed to prepared for execute!");
|
||||
emit PrepareForExecuteSuccess(false);
|
||||
T_D();
|
||||
return d->eventManager;
|
||||
}
|
||||
|
||||
void XNFramework::OnSimControl(quint32 objectId, SimControlCmd cmd)
|
||||
XNModelManagerPtr XNFramework::GetModelManager()
|
||||
{
|
||||
emit SimControl(objectId, cmd);
|
||||
T_D();
|
||||
return d->modelManager;
|
||||
}
|
||||
|
||||
XNServiceManagerPtr XNFramework::GetServiceManager()
|
||||
{
|
||||
T_D();
|
||||
return d->serviceManager;
|
||||
}
|
||||
|
@ -12,195 +12,164 @@
|
||||
|
||||
#include "XNObject.h"
|
||||
|
||||
class XNFrameworkPrivate;
|
||||
struct XNFrameworkPrivate;
|
||||
|
||||
/**
|
||||
* @brief 框架类
|
||||
*/
|
||||
class XNCORE_EXPORT XNFramework : public XNObject
|
||||
{
|
||||
/**
|
||||
* @brief 宏定义,用于支持Qt的元对象系统
|
||||
*/
|
||||
Q_OBJECT
|
||||
|
||||
/**
|
||||
* @brief 宏定义,用于禁用拷贝构造函数
|
||||
*/
|
||||
Q_DISABLE_COPY(XNFramework)
|
||||
XN_METATYPE(XNFramework, XNObject)
|
||||
|
||||
/**
|
||||
* @brief 宏定义,用于声明私有数据成员
|
||||
*/
|
||||
Q_DECLARE_PRIVATE(XNFramework);
|
||||
|
||||
/**
|
||||
* @brief 宏定义,用于声明属性workPath
|
||||
*/
|
||||
Q_PROPERTY(QString workPath READ GetWorkPath WRITE SetWorkPath)
|
||||
|
||||
/**
|
||||
* @brief 宏定义,用于声明属性modelPath
|
||||
*/
|
||||
Q_PROPERTY(QString modelPath READ GetModelPath WRITE SetModelPath)
|
||||
|
||||
/**
|
||||
* @brief 宏定义,用于声明属性cpuAffinity
|
||||
*/
|
||||
Q_PROPERTY(quint32 cpuAffinity READ GetCpuAffinity WRITE SetCpuAffinity)
|
||||
|
||||
XN_DECLARE_PRIVATE(XNFramework)
|
||||
public:
|
||||
/**
|
||||
* @brief 构造函数
|
||||
* @param parent 父对象
|
||||
*/
|
||||
explicit XNFramework(QObject *parent = nullptr);
|
||||
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 场景管理器
|
||||
*/
|
||||
XNScenarioManagerPtr GetScenarioManager();
|
||||
|
||||
/**
|
||||
* @brief 获取服务管理器
|
||||
* @return 服务管理器
|
||||
*/
|
||||
XNServiceManagerPtr GetServiceManager();
|
||||
|
||||
/**
|
||||
* @brief 获取线程管理器
|
||||
* @return 线程管理器
|
||||
*/
|
||||
XNThreadManagerPtr GetThreadManager();
|
||||
|
||||
/**
|
||||
* @brief 获取时间管理器
|
||||
* @return 时间管理器
|
||||
*/
|
||||
XNTimeManagerPtr GetTimeManager();
|
||||
|
||||
/**
|
||||
* @brief 获取工作路径
|
||||
* @return 工作路径
|
||||
*/
|
||||
QString GetWorkPath();
|
||||
std::string GetWorkPath();
|
||||
|
||||
/**
|
||||
* @brief 设置工作路径
|
||||
* @param workPath 工作路径
|
||||
*/
|
||||
void SetWorkPath(const std::string &workPath);
|
||||
|
||||
/**
|
||||
* @brief 获取模型库路径
|
||||
* @return 模型库路径
|
||||
*/
|
||||
QString GetModelPath();
|
||||
std::string GetModelPath();
|
||||
|
||||
/**
|
||||
* @brief 设置模型库路径
|
||||
* @param modelPath 模型库路径
|
||||
*/
|
||||
void SetModelPath(const std::string &modelPath);
|
||||
|
||||
/**
|
||||
* @brief 获取服务库路径
|
||||
* @return 服务库路径
|
||||
*/
|
||||
QString GetServicePath();
|
||||
std::string GetServicePath();
|
||||
|
||||
/**
|
||||
* @brief 设置服务库路径
|
||||
* @param servicePath 服务库路径
|
||||
*/
|
||||
void SetServicePath(const std::string &servicePath);
|
||||
|
||||
/**
|
||||
* @brief 获取CPU亲和性
|
||||
* @return CPU亲和性
|
||||
*/
|
||||
quint32 GetCpuAffinity();
|
||||
uint32_t GetCpuAffinity();
|
||||
|
||||
/**
|
||||
* @brief 设置CPU亲和性
|
||||
* @param cpuAffinity CPU亲和性
|
||||
*/
|
||||
void SetCpuAffinity(uint32_t cpuAffinity);
|
||||
|
||||
/**
|
||||
* @brief 设置场景XML
|
||||
* @param scenarioXml 场景XML
|
||||
*/
|
||||
void SetScenarioXml(const QString &scenarioXml);
|
||||
|
||||
signals:
|
||||
/**
|
||||
* @brief 初始化
|
||||
*/
|
||||
void Initialize();
|
||||
|
||||
/**
|
||||
* @brief 初始化成功
|
||||
*/
|
||||
void InitializeSuccess(bool isSuccess);
|
||||
void SetScenarioXml(const std::string &scenarioXml);
|
||||
|
||||
/**
|
||||
* @brief 准备执行
|
||||
*/
|
||||
void PrepareForExecute();
|
||||
|
||||
/**
|
||||
* @brief 准备执行成功
|
||||
*/
|
||||
void PrepareForExecuteSuccess(bool isSuccess);
|
||||
|
||||
/**
|
||||
* @brief 分析场景XML
|
||||
* @param scenarioXml 场景XML
|
||||
*/
|
||||
void AnalyzeScenarioXml(const QString &scenarioXml);
|
||||
void AnalyzeScenarioXml(const std::string &scenarioXml);
|
||||
|
||||
/**
|
||||
* @brief 仿真控制
|
||||
* @param objectId 对象ID
|
||||
* @param cmd 命令
|
||||
*/
|
||||
void SimControl(quint32 objectId, SimControlCmd cmd);
|
||||
|
||||
public slots:
|
||||
/**
|
||||
* @brief 设置工作路径
|
||||
* @param workPath 工作路径
|
||||
*/
|
||||
void SetWorkPath(const QString &workPath);
|
||||
|
||||
/**
|
||||
* @brief 设置模型库路径
|
||||
* @param modelPath 模型库路径
|
||||
*/
|
||||
void SetModelPath(const QString &modelPath);
|
||||
|
||||
/**
|
||||
* @brief 设置服务库路径
|
||||
* @param servicePath 服务库路径
|
||||
*/
|
||||
void SetServicePath(const QString &servicePath);
|
||||
|
||||
/**
|
||||
* @brief 设置CPU亲和性
|
||||
* @param cpuAffinity CPU亲和性
|
||||
*/
|
||||
void SetCpuAffinity(quint32 cpuAffinity);
|
||||
void SimControl(uint32_t objectId, SimControlCmd cmd);
|
||||
|
||||
/**
|
||||
* @brief 初始化
|
||||
*/
|
||||
void OnInitialize();
|
||||
|
||||
/**
|
||||
* @brief 初始化成功
|
||||
*/
|
||||
void OnInitializeSuccess();
|
||||
|
||||
/**
|
||||
* @brief 初始化失败
|
||||
*/
|
||||
void OnInitializeFailed();
|
||||
|
||||
/**
|
||||
* @brief 解析配置文件成功
|
||||
*/
|
||||
void OnAnalyzeScenarioXmlSuccess();
|
||||
|
||||
/**
|
||||
* @brief 解析配置文件失败
|
||||
*/
|
||||
void OnAnalyzeScenarioXmlFailed();
|
||||
|
||||
/**
|
||||
* @brief 准备执行
|
||||
*/
|
||||
void OnPrepareForExecute();
|
||||
|
||||
/**
|
||||
* @brief 准备执行成功
|
||||
*/
|
||||
void OnPrepareForExecuteSuccess();
|
||||
|
||||
/**
|
||||
* @brief 准备执行失败
|
||||
*/
|
||||
void OnPrepareForExecuteFailed();
|
||||
void Initialize();
|
||||
|
||||
/**
|
||||
* @brief 仿真控制
|
||||
* @param cmd 命令
|
||||
*/
|
||||
void OnSimControl(quint32 objectId, SimControlCmd cmd);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief 构造函数
|
||||
* @param dd 私有数据成员
|
||||
* @param parent 父对象
|
||||
*/
|
||||
XNFramework(XNFrameworkPrivate &dd, QObject *parent = nullptr);
|
||||
void OnSimControl(uint32_t objectId, SimControlCmd cmd);
|
||||
};
|
||||
|
@ -16,43 +16,65 @@
|
||||
/**
|
||||
* @brief 框架类的私有数据成员
|
||||
*/
|
||||
class XNFrameworkPrivate : public XNObjectPrivate
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief 构造函数
|
||||
* @param q 框架类指针
|
||||
*/
|
||||
explicit XNFrameworkPrivate(XNFramework *q) : XNObjectPrivate(q) {}
|
||||
struct XNFrameworkPrivate : public XNObjectPrivate {
|
||||
|
||||
/**
|
||||
* @brief 宏定义,用于声明公有数据成员
|
||||
* @brief DDS管理器
|
||||
*/
|
||||
Q_DECLARE_PUBLIC(XNFramework)
|
||||
XNDDSManagerPtr ddsManager;
|
||||
|
||||
/**
|
||||
* @brief 事件管理器
|
||||
*/
|
||||
XNEventManagerPtr eventManager;
|
||||
|
||||
/**
|
||||
* @brief 模型管理器
|
||||
*/
|
||||
XNModelManagerPtr modelManager;
|
||||
|
||||
/**
|
||||
* @brief 场景管理器
|
||||
*/
|
||||
XNScenarioManagerPtr scenarioManager;
|
||||
|
||||
/**
|
||||
* @brief 服务管理器
|
||||
*/
|
||||
XNServiceManagerPtr serviceManager;
|
||||
|
||||
/**
|
||||
* @brief 线程管理器
|
||||
*/
|
||||
XNThreadManagerPtr threadManager;
|
||||
|
||||
/**
|
||||
* @brief 时间管理器
|
||||
*/
|
||||
XNTimeManagerPtr timeManager;
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief 工作路径
|
||||
*/
|
||||
QString workPath;
|
||||
std::string workPath;
|
||||
|
||||
/**
|
||||
* @brief 模型路径
|
||||
*/
|
||||
QString modelPath;
|
||||
std::string modelPath;
|
||||
|
||||
/**
|
||||
* @brief 服务路径
|
||||
*/
|
||||
QString servicePath;
|
||||
std::string servicePath;
|
||||
|
||||
/**
|
||||
* @brief CPU亲和性
|
||||
*/
|
||||
quint32 uCpuAffinity;
|
||||
uint32_t uCpuAffinity;
|
||||
|
||||
/**
|
||||
* @brief 场景XML
|
||||
*/
|
||||
QString scenarioXml;
|
||||
std::string scenarioXml;
|
||||
};
|
||||
|
@ -4,39 +4,51 @@ XNLogger::XNLogger()
|
||||
: consoleOutputEnabled{true, true, true, true}, fileOutputEnabled{true, true, true, true}
|
||||
{
|
||||
// 获取当前工作目录
|
||||
QString currentDir = QDir::currentPath();
|
||||
QString logDirPath = currentDir + "/log";
|
||||
std::filesystem::path currentDir = std::filesystem::current_path();
|
||||
std::filesystem::path logDirPath = currentDir / "log";
|
||||
|
||||
// 创建 log 文件夹
|
||||
QDir logDir;
|
||||
if (!logDir.exists(logDirPath)) {
|
||||
logDir.mkpath(logDirPath);
|
||||
if (!std::filesystem::exists(logDirPath)) {
|
||||
std::filesystem::create_directories(logDirPath);
|
||||
}
|
||||
|
||||
// 创建以当前日期和时间命名的日志文件
|
||||
QString logFileName =
|
||||
QString("log_%1.log").arg(QDateTime::currentDateTime().toString("yyyyMMdd_HHmmss"));
|
||||
logFile.setFileName(logDirPath + "/" + logFileName);
|
||||
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";
|
||||
|
||||
logFile.open(QIODevice::Append | QIODevice::Text);
|
||||
logFilePath = (logDirPath / logFileName).string();
|
||||
logFile.open(logFilePath, std::ios::app);
|
||||
}
|
||||
|
||||
XNLogger::~XNLogger()
|
||||
{
|
||||
if (logFile.isOpen()) {
|
||||
if (logFile.is_open()) {
|
||||
logFile.close();
|
||||
}
|
||||
}
|
||||
|
||||
void XNLogger::log(LogLevel level, const QString &message)
|
||||
std::string XNLogger::getCurrentTimeString() const
|
||||
{
|
||||
QMutexLocker locker(&mutex);
|
||||
QString logMessage = QString("[%1] [%2] %3")
|
||||
.arg(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss.zzz"))
|
||||
.arg(logLevelToString(level))
|
||||
.arg(message);
|
||||
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;
|
||||
|
||||
QString coloredMessage;
|
||||
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) {
|
||||
@ -61,19 +73,18 @@ void XNLogger::log(LogLevel level, const QString &message)
|
||||
if (consoleOutputEnabled[level]) {
|
||||
if (level == Time) {
|
||||
// 如果是时间日志,则不换行,回退到该行开始
|
||||
QTextStream(stdout) << coloredMessage << "\r";
|
||||
std::cout << coloredMessage << "\r" << std::flush;
|
||||
} else {
|
||||
QTextStream(stdout) << coloredMessage << "\n";
|
||||
std::cout << coloredMessage << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
// 文件输出
|
||||
if (fileOutputEnabled[level] && logFile.isOpen()) {
|
||||
QTextStream fileStream(&logFile);
|
||||
if (fileOutputEnabled[level] && logFile.is_open()) {
|
||||
if (level == Time) {
|
||||
fileStream << logMessage << "\r";
|
||||
logFile << logMessage << "\r" << std::flush;
|
||||
} else {
|
||||
fileStream << logMessage << "\n";
|
||||
logFile << logMessage << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -88,7 +99,7 @@ void XNLogger::enableFileOutput(LogLevel level, bool enable)
|
||||
fileOutputEnabled[level] = enable;
|
||||
}
|
||||
|
||||
QString XNLogger::logLevelToString(LogLevel level) const
|
||||
std::string XNLogger::logLevelToString(LogLevel level) const
|
||||
{
|
||||
switch (level) {
|
||||
case Debug:
|
||||
|
@ -9,13 +9,15 @@
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
#include <QString>
|
||||
#include <QMutex>
|
||||
#include <QFile>
|
||||
#include <QTextStream>
|
||||
#include <QDateTime>
|
||||
#include <QDir>
|
||||
#include <string>
|
||||
#include <mutex>
|
||||
#include <fstream>
|
||||
#include <chrono>
|
||||
#include <filesystem>
|
||||
#include <type_traits>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
|
||||
/**
|
||||
* @brief 日志类
|
||||
@ -34,7 +36,6 @@ public:
|
||||
*/
|
||||
static XNLogger &instance()
|
||||
{
|
||||
// 懒汉式单例,C++11 及以上版本的标准保证了局部静态变量的初始化是线程安全的
|
||||
static XNLogger instance;
|
||||
return instance;
|
||||
}
|
||||
@ -44,7 +45,7 @@ public:
|
||||
* @param level 日志等级
|
||||
* @param message 日志消息
|
||||
*/
|
||||
void log(LogLevel level, const QString &message);
|
||||
void log(LogLevel level, const std::string &message);
|
||||
|
||||
/**
|
||||
* @brief 启用控制台输出
|
||||
@ -64,7 +65,7 @@ private:
|
||||
/**
|
||||
* @brief 构造函数
|
||||
*/
|
||||
XNLogger(); // 默认构造函数
|
||||
XNLogger();
|
||||
|
||||
/**
|
||||
* @brief 析构函数
|
||||
@ -74,17 +75,17 @@ private:
|
||||
/**
|
||||
* @brief 禁止拷贝构造
|
||||
*/
|
||||
XNLogger(const XNLogger &) = delete; // 禁止拷贝构造
|
||||
XNLogger(const XNLogger &) = delete;
|
||||
|
||||
/**
|
||||
* @brief 禁止赋值
|
||||
*/
|
||||
XNLogger &operator=(const XNLogger &) = delete; // 禁止赋值
|
||||
XNLogger &operator=(const XNLogger &) = delete;
|
||||
|
||||
/**
|
||||
* @brief 日志文件路径
|
||||
*/
|
||||
QString logFilePath;
|
||||
std::string logFilePath;
|
||||
|
||||
/**
|
||||
* @brief 控制台输出控制
|
||||
@ -99,44 +100,50 @@ private:
|
||||
/**
|
||||
* @brief 日志文件
|
||||
*/
|
||||
QFile logFile;
|
||||
std::ofstream logFile;
|
||||
|
||||
/**
|
||||
* @brief 互斥锁
|
||||
*/
|
||||
QMutex mutex;
|
||||
std::mutex mutex;
|
||||
|
||||
/**
|
||||
* @brief 日志等级转换为字符串
|
||||
* @param level 日志等级
|
||||
* @return 日志等级字符串
|
||||
*/
|
||||
QString logLevelToString(LogLevel level) const;
|
||||
std::string logLevelToString(LogLevel level) const;
|
||||
|
||||
/**
|
||||
* @brief 获取当前时间字符串
|
||||
* @return 格式化的时间字符串
|
||||
*/
|
||||
std::string getCurrentTimeString() const;
|
||||
|
||||
/**
|
||||
* @brief 控制台输出字体恢复颜色常量
|
||||
*/
|
||||
const QString COLOR_RESET = "\033[0m";
|
||||
const std::string COLOR_RESET = "\033[0m";
|
||||
|
||||
/**
|
||||
* @brief 调试颜色常量
|
||||
*/
|
||||
const QString COLOR_DEBUG = "\033[34m"; // 蓝色
|
||||
const std::string COLOR_DEBUG = "\033[34m"; // 蓝色
|
||||
|
||||
/**
|
||||
* @brief 信息颜色常量
|
||||
*/
|
||||
const QString COLOR_INFO = "\033[32m"; // 绿色
|
||||
const std::string COLOR_INFO = "\033[32m"; // 绿色
|
||||
|
||||
/**
|
||||
* @brief 警告颜色常量
|
||||
*/
|
||||
const QString COLOR_WARNING = "\033[33m"; // 黄色
|
||||
const std::string COLOR_WARNING = "\033[33m"; // 黄色
|
||||
|
||||
/**
|
||||
* @brief 错误颜色常量
|
||||
*/
|
||||
const QString COLOR_ERROR = "\033[31m"; // 红色
|
||||
const std::string COLOR_ERROR = "\033[31m"; // 红色
|
||||
};
|
||||
|
||||
/**
|
||||
@ -154,9 +161,9 @@ public:
|
||||
*/
|
||||
template <typename... Args>
|
||||
inline static typename std::enable_if<(sizeof...(Args) > 0), void>::type
|
||||
log(XNLogger::LogLevel level, const QString &message, Args... args)
|
||||
log(XNLogger::LogLevel level, const std::string &message, Args... args)
|
||||
{
|
||||
QString formattedMessage = formatMessage(message, args...);
|
||||
std::string formattedMessage = formatMessage(message, args...);
|
||||
XNLogger::instance().log(level, formattedMessage);
|
||||
}
|
||||
|
||||
@ -165,7 +172,7 @@ public:
|
||||
* @param level 日志等级
|
||||
* @param message 日志消息
|
||||
*/
|
||||
inline static void log(XNLogger::LogLevel level, const QString &message)
|
||||
inline static void log(XNLogger::LogLevel level, const std::string &message)
|
||||
{
|
||||
XNLogger::instance().log(level, message);
|
||||
}
|
||||
@ -173,27 +180,44 @@ public:
|
||||
private:
|
||||
// 辅助函数,用于格式化消息
|
||||
template <typename T>
|
||||
static QString convertToString(const T &arg)
|
||||
static std::string convertToString(const T &arg)
|
||||
{
|
||||
if constexpr (std::is_arithmetic<T>::value) {
|
||||
return QString::number(arg); // 处理数值类型
|
||||
return std::to_string(arg); // 处理数值类型
|
||||
} else {
|
||||
return arg;
|
||||
return std::string(arg);
|
||||
}
|
||||
}
|
||||
|
||||
// 递归变参函数,用于处理多个参数
|
||||
template <typename T, typename... Args>
|
||||
static QString formatMessage(const QString &message, T arg, Args... args)
|
||||
static std::string formatMessage(const std::string &message, T arg, Args... args)
|
||||
{
|
||||
return formatMessage(message.arg(convertToString(arg)), args...); // 递归调用
|
||||
// 查找下一个参数占位符
|
||||
std::string result = message;
|
||||
size_t paramIndex = 0;
|
||||
size_t pos = 0;
|
||||
|
||||
// 找到当前参数对应的占位符
|
||||
while (true) {
|
||||
std::string placeholder = "%" + std::to_string(paramIndex + 1);
|
||||
pos = result.find(placeholder);
|
||||
if (pos != std::string::npos) {
|
||||
// 替换占位符,使用placeholder的长度
|
||||
result.replace(pos, placeholder.length(), convertToString(arg));
|
||||
break;
|
||||
}
|
||||
paramIndex++;
|
||||
if (paramIndex > 100) { // 防止无限循环
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return formatMessage(result, args...);
|
||||
}
|
||||
|
||||
// 基础情况
|
||||
static QString formatMessage(const QString &message)
|
||||
{
|
||||
return message; // 处理没有参数的情况
|
||||
}
|
||||
static std::string formatMessage(const std::string &message) { return message; }
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -11,17 +11,15 @@
|
||||
#include "XNModelManager.h"
|
||||
#include "XNModelManager_p.h"
|
||||
#include "XNModelObject.h"
|
||||
#include <QLibrary>
|
||||
#include <QMetaObject>
|
||||
#include <QPointer>
|
||||
#include "XNFramework.h"
|
||||
#include "XNThreadManager.h"
|
||||
|
||||
// 构造函数
|
||||
XNModelManager::XNModelManager(QObject *parent)
|
||||
: XNBaseFrameObject(*new XNModelManagerPrivate(this), parent)
|
||||
XNModelManager::XNModelManager() : XNBaseFrameObject(new XNModelManagerPrivate())
|
||||
{
|
||||
setUniqueId(6);
|
||||
setObjectName("XNModelManager");
|
||||
Q_D(XNModelManager);
|
||||
SetUniqueId(6);
|
||||
SetObjectName("XNModelManager");
|
||||
T_D();
|
||||
d->ModelIDAssigned.resize(10000, false);
|
||||
}
|
||||
|
||||
@ -30,103 +28,93 @@ XNModelManager::~XNModelManager()
|
||||
{
|
||||
}
|
||||
|
||||
XNModelManager::XNModelManager(XNModelManagerPrivate &dd, QObject *parent)
|
||||
: XNBaseFrameObject(dd, parent)
|
||||
XNModelManager::XNModelManager(PrivateType *p) : XNBaseFrameObject(p)
|
||||
{
|
||||
Q_D(XNModelManager);
|
||||
T_D();
|
||||
d->ModelIDAssigned.resize(10000, false);
|
||||
}
|
||||
|
||||
// 运行前最后准备
|
||||
void XNModelManager::OnPrepareForExecute()
|
||||
bool XNModelManager::PrepareForExecute()
|
||||
{
|
||||
Q_D(XNModelManager);
|
||||
emit PrepareForExecute();
|
||||
T_D();
|
||||
d->_status = XNFrameObjectStatus::Ready;
|
||||
LOG_INFO("XNModelManager is prepared!");
|
||||
emit PrepareForExecuteSuccess();
|
||||
return true;
|
||||
}
|
||||
|
||||
void XNModelManager::OnInitialize()
|
||||
bool XNModelManager::Initialize()
|
||||
{
|
||||
Q_D(XNModelManager);
|
||||
T_D();
|
||||
LOG_INFO("XNModelManager Initialize Success!");
|
||||
d->_status = XNFrameObjectStatus::Initialized;
|
||||
emit InitializeSuccess();
|
||||
return true;
|
||||
}
|
||||
|
||||
void XNModelManager::OnLoadModel(const QString &modelPath, const QString &className)
|
||||
void XNModelManager::LoadModel(const std::string &modelPath, const std::string &className,
|
||||
uint32_t initialType, uint32_t threadID)
|
||||
{
|
||||
Q_D(XNModelManager);
|
||||
QLibrary lib(modelPath);
|
||||
if (lib.load()) {
|
||||
typedef void (*InitialModelFunc)();
|
||||
QString initialModelName = "Initial" + className;
|
||||
InitialModelFunc initialModel =
|
||||
(InitialModelFunc)lib.resolve(initialModelName.toUtf8().constData());
|
||||
T_D();
|
||||
void *handle = dlopen(modelPath.c_str(), RTLD_LAZY);
|
||||
if (handle) {
|
||||
typedef XNModelObjectPtr (*InitialModelFunc)();
|
||||
std::string initialModelName = "Initial" + className;
|
||||
InitialModelFunc initialModel = (InitialModelFunc)dlsym(handle, initialModelName.c_str());
|
||||
if (initialModel) {
|
||||
initialModel();
|
||||
QMetaType metaType = QMetaType::fromName(className.toUtf8().constData());
|
||||
if (metaType.isValid()) {
|
||||
QObject *obj = static_cast<QObject *>(metaType.create());
|
||||
if (obj) {
|
||||
XNModelObject *model = qobject_cast<XNModelObject *>(obj);
|
||||
XNModelObjectPtr model = initialModel();
|
||||
if (model) {
|
||||
quint32 modelID = RegisterModel();
|
||||
uint32_t modelID = RegisterModel();
|
||||
if (modelID == 0) {
|
||||
LOG_WARNING("0x2174 Assign Model ID Failed, Model ID is used up!");
|
||||
delete obj;
|
||||
dlclose(handle);
|
||||
return;
|
||||
}
|
||||
model->setParent(this);
|
||||
model->setObjectName(className);
|
||||
model->setUniqueId(modelID);
|
||||
model->SetBaseFreq(d->dBaseFreq);
|
||||
QString configFilePath =
|
||||
QFileInfo(modelPath).absolutePath() + "/" + className + ".mcfg";
|
||||
model->SetXmlPath(configFilePath);
|
||||
connect(model, &XNModelObject::RegisterFunction, this,
|
||||
&XNModelManager::OnRegisterFunction);
|
||||
connect(this, &XNModelManager::PrepareForExecute, model,
|
||||
&XNModelObject::OnPrepareForExecute);
|
||||
model->OnInitialize();
|
||||
} else {
|
||||
LOG_WARNING("0x2175 Model %1 Instantiation Failed, Not a subclass of "
|
||||
"XNModelObject!",
|
||||
className);
|
||||
delete obj;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
LOG_WARNING("0x2176 Model %1 Instantiation Failed, Not a subclass of QObject!",
|
||||
className);
|
||||
delete obj;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
LOG_WARNING("0x2173 Model %1 Not found in dynamic link library %2!", className,
|
||||
modelPath);
|
||||
}
|
||||
} else {
|
||||
LOG_WARNING("0x2177 InitialModel function not found in dynamic link library %2!",
|
||||
modelPath);
|
||||
}
|
||||
} else {
|
||||
LOG_WARNING("0x2172 Model %1 Dynamic link library loading failed! Error: %2", className,
|
||||
lib.errorString());
|
||||
}
|
||||
}
|
||||
model->SetUniqueId(modelID);
|
||||
model->SetObjectName(className);
|
||||
model->SetFramework(GetFramework());
|
||||
|
||||
void XNModelManager::OnSetBaseFreq(const double &dBaseFreq)
|
||||
{
|
||||
Q_D(XNModelManager);
|
||||
d->dBaseFreq = dBaseFreq;
|
||||
// 使用std::filesystem处理路径
|
||||
std::filesystem::path configPath =
|
||||
std::filesystem::path(modelPath).parent_path() / (className + ".mcfg");
|
||||
model->SetXmlPath(configPath.string());
|
||||
|
||||
// 注册模型到管理器
|
||||
d->ModelMap[modelID] = model;
|
||||
|
||||
// 初始化模型
|
||||
model->Initialize(initialType, threadID);
|
||||
|
||||
// 注册到线程管理器
|
||||
if (threadID != 0) {
|
||||
auto framework = GetFramework();
|
||||
if (framework) {
|
||||
framework->GetThreadManager()->RegisterFunction(
|
||||
modelID, std::bind(&XNModelObject::StepUpdate, model.get()), threadID,
|
||||
0, 0, 0);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
LOG_WARNING("0x2173 Model %s Not found in dynamic link library %s!",
|
||||
className.c_str(), modelPath.c_str());
|
||||
dlclose(handle);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
LOG_WARNING("0x2177 InitialModel function not found in dynamic link library %s!",
|
||||
modelPath.c_str());
|
||||
dlclose(handle);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
LOG_WARNING("0x2172 Model %s Dynamic link library loading failed! Error: %s",
|
||||
className.c_str(), dlerror());
|
||||
}
|
||||
}
|
||||
|
||||
// 模型注册
|
||||
quint32 XNModelManager::RegisterModel()
|
||||
uint32_t XNModelManager::RegisterModel()
|
||||
{
|
||||
Q_D(XNModelManager);
|
||||
T_D();
|
||||
// 从10000~19999的编号中分配ID
|
||||
for (int i = 0; i < 10000; i++) {
|
||||
if (d->ModelIDAssigned[i])
|
||||
@ -140,26 +128,29 @@ quint32 XNModelManager::RegisterModel()
|
||||
}
|
||||
|
||||
// 获取模型指针
|
||||
XNModelObject *XNModelManager::GetModel(quint32 modelID)
|
||||
XNModelObjectPtr XNModelManager::GetModel(uint32_t modelID)
|
||||
{
|
||||
Q_D(XNModelManager);
|
||||
T_D();
|
||||
if (d->ModelIDAssigned[modelID - 10000]) {
|
||||
QList<XNModelObject *> modelList = findChildren<XNModelObject *>();
|
||||
for (auto &model : modelList) {
|
||||
if (model->getUniqueId() == modelID)
|
||||
return model;
|
||||
auto model = d->ModelMap.find(modelID);
|
||||
if (model != d->ModelMap.end()) {
|
||||
return model->second;
|
||||
}
|
||||
return nullptr;
|
||||
} else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void XNModelManager::OnRegisterFunction(quint32 id, XNCallBack fun, quint32 freqGroup,
|
||||
quint32 RunPos, quint32 RunPriorty)
|
||||
void XNModelManager::RegisterFunction(uint32_t id, XNCallBack fun, uint32_t threadID,
|
||||
uint32_t freqGroup, uint32_t RunPos, uint32_t RunPriorty)
|
||||
{
|
||||
Q_D(XNModelManager);
|
||||
T_D();
|
||||
if (d->ModelIDAssigned[id - 10000]) {
|
||||
emit RegisterFunction(id, fun, freqGroup, RunPos, RunPriorty);
|
||||
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!",
|
||||
|
@ -12,7 +12,9 @@
|
||||
#include "XNBaseFrameObject.h"
|
||||
|
||||
class XNModelObject;
|
||||
class XNModelManagerPrivate;
|
||||
XNCLASS_PTR_DECLARE(XNModelObject)
|
||||
|
||||
struct XNModelManagerPrivate;
|
||||
|
||||
/**
|
||||
* @brief 模型管理器类
|
||||
@ -20,18 +22,14 @@ class XNModelManagerPrivate;
|
||||
*/
|
||||
class XNModelManager : public XNBaseFrameObject
|
||||
{
|
||||
/**
|
||||
* @brief 使用禁止复制类宏定义自身禁止复制
|
||||
*/
|
||||
Q_OBJECT
|
||||
Q_DECLARE_PRIVATE(XNModelManager)
|
||||
Q_DISABLE_COPY(XNModelManager)
|
||||
XN_METATYPE(XNModelManager, XNBaseFrameObject)
|
||||
XN_DECLARE_PRIVATE(XNModelManager)
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief 模型管理器类默认构造函数
|
||||
*/
|
||||
explicit XNModelManager(QObject *parent = nullptr);
|
||||
XNModelManager();
|
||||
|
||||
/**
|
||||
* @brief 模型管理器类默认析构函数
|
||||
@ -44,20 +42,20 @@ protected:
|
||||
* @param p:私有结构体指针
|
||||
* @details 子类构造时调用此构造函数,传入子类的私有结构体指针
|
||||
*/
|
||||
XNModelManager(XNModelManagerPrivate &dd, QObject *parent = nullptr);
|
||||
XNModelManager(PrivateType *p);
|
||||
|
||||
public slots:
|
||||
public:
|
||||
/**
|
||||
* @brief 系统开始运行前的最后准备工作
|
||||
* @details 系统运行前模型管理器做最后处理的接口
|
||||
*/
|
||||
virtual void OnPrepareForExecute() override;
|
||||
virtual bool PrepareForExecute() override;
|
||||
|
||||
/**
|
||||
* @brief 初始化模型管理器
|
||||
* @details 模型管理器的初始化接口
|
||||
*/
|
||||
virtual void OnInitialize() override;
|
||||
virtual bool Initialize() override;
|
||||
|
||||
/**
|
||||
* @brief 加载模型
|
||||
@ -65,31 +63,23 @@ public slots:
|
||||
* @param className: QString类型,模型类名
|
||||
* @details 加载模型
|
||||
*/
|
||||
void OnLoadModel(const QString &modelPath, const QString &className);
|
||||
void LoadModel(const std::string &modelPath, const std::string &className, uint32_t initialType,
|
||||
uint32_t threadID);
|
||||
|
||||
/**
|
||||
* @brief 设置仿真系统运行基频
|
||||
* @param dBaseFreq: double类型,频率值,单位Hz
|
||||
* @details 仿真系统所有线程以此基频的 1 或 1/2 或 1/4 或 1/8 或 1/16 或 1/32 倍运行
|
||||
*/
|
||||
void OnSetBaseFreq(const double &dBaseFreq);
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief 注册模型信息
|
||||
* @return UINT32: 模型的全局唯一ID
|
||||
* @details 模型通过此接口注册自身,并获取自身全局唯一ID
|
||||
*/
|
||||
quint32 RegisterModel();
|
||||
uint32_t RegisterModel();
|
||||
|
||||
/**
|
||||
* @brief 获取模型指针
|
||||
* @param modelID: UINT32类型,模型全局唯一ID
|
||||
* @return XNModelObjectPtr: 模型基类指针
|
||||
*/
|
||||
XNModelObject *GetModel(quint32 modelID);
|
||||
XNModelObjectPtr GetModel(uint32_t modelID);
|
||||
|
||||
public slots:
|
||||
/**
|
||||
* @brief 注册模型函数
|
||||
* @param ModelID: UINT32类型,模型全局唯一ID
|
||||
@ -98,22 +88,6 @@ public slots:
|
||||
* @param RunPos: UINT32类型,提交的函数运行节点号,<2^(freqGroup)
|
||||
* @param RunPriorty: UINT32类型,提交的函数运行优先级,99~0,优先级数值越大,优先级越高
|
||||
*/
|
||||
void OnRegisterFunction(quint32 id, XNCallBack fun, quint32 freqGroup, quint32 RunPos,
|
||||
quint32 RunPriorty);
|
||||
|
||||
signals:
|
||||
/**
|
||||
* @brief 注册函数信号
|
||||
* @param id: 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(quint32 id, XNCallBack fun, quint32 freqGroup, quint32 RunPos,
|
||||
quint32 RunPriorty);
|
||||
|
||||
void InitializeSuccess();
|
||||
|
||||
void PrepareForExecuteSuccess();
|
||||
void RegisterFunction(uint32_t id, XNCallBack fun, uint32_t threadID, uint32_t freqGroup,
|
||||
uint32_t RunPos, uint32_t RunPriorty);
|
||||
};
|
@ -1,25 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include "XNBaseFrameObject_p.h"
|
||||
#include <QVector>
|
||||
#include <QHash>
|
||||
|
||||
class XNModelManagerPrivate : public XNBaseFrameObjectPrivate
|
||||
{
|
||||
public:
|
||||
Q_DECLARE_PUBLIC(XNModelManager)
|
||||
|
||||
explicit XNModelManagerPrivate(XNModelManager *q) : XNBaseFrameObjectPrivate(q) {}
|
||||
|
||||
struct XNModelManagerPrivate : public XNBaseFrameObjectPrivate {
|
||||
XNFrameworkPtr framework;
|
||||
/**
|
||||
* @brief 模型ID库
|
||||
* @details 所有模型已用ID的存储库
|
||||
*/
|
||||
QVector<bool> ModelIDAssigned;
|
||||
|
||||
std::vector<bool> ModelIDAssigned;
|
||||
/**
|
||||
* @brief 仿真系统运行基频
|
||||
* @details 仿真系统所有线程以此基频的 1 或 1/2 或 1/4 或 1/8 或 1/16 或 1/32 倍运行
|
||||
* @brief 模型ID与模型指针的映射表
|
||||
* @details 所有模型ID与模型指针的映射表
|
||||
*/
|
||||
double dBaseFreq;
|
||||
std::map<uint32_t, XNModelObjectPtr> ModelMap;
|
||||
};
|
||||
|
@ -15,10 +15,9 @@
|
||||
#include "XNModelManager.h"
|
||||
#include "XNDDSManager.h"
|
||||
#include "XNIDL/XNSimStatusPubSubTypes.hpp"
|
||||
#include <QMetaMethod>
|
||||
|
||||
// 默认构造函数
|
||||
XNModelObject::XNModelObject(QObject *parent) : XNObject(*new XNModelObjectPrivate(this), parent)
|
||||
XNModelObject::XNModelObject() : XNObject(new XNModelObjectPrivate())
|
||||
{
|
||||
}
|
||||
|
||||
@ -27,184 +26,209 @@ XNModelObject::~XNModelObject()
|
||||
{
|
||||
}
|
||||
|
||||
XNModelObject::XNModelObject(XNModelObjectPrivate &dd, QObject *parent) : XNObject(dd, parent)
|
||||
XNModelObject::XNModelObject(PrivateType *p) : XNObject(p)
|
||||
{
|
||||
}
|
||||
|
||||
// 获取模型描述
|
||||
const QString &XNModelObject::GetDescription()
|
||||
const std::string &XNModelObject::GetDescription()
|
||||
{
|
||||
Q_D(XNModelObject);
|
||||
T_D();
|
||||
return d->_sDescription;
|
||||
}
|
||||
|
||||
// 设置模型描述
|
||||
void XNModelObject::SetDescription(const QString &sDescription)
|
||||
void XNModelObject::SetDescription(const std::string &sDescription)
|
||||
{
|
||||
Q_D(XNModelObject);
|
||||
T_D();
|
||||
d->_sDescription = sDescription;
|
||||
}
|
||||
|
||||
// 获取作者
|
||||
const QString &XNModelObject::GetAuthor()
|
||||
const std::string &XNModelObject::GetAuthor()
|
||||
{
|
||||
Q_D(XNModelObject);
|
||||
T_D();
|
||||
return d->_sAuthor;
|
||||
}
|
||||
|
||||
// 设置作者
|
||||
void XNModelObject::SetAuthor(const QString &sAuthor)
|
||||
void XNModelObject::SetAuthor(const std::string &sAuthor)
|
||||
{
|
||||
Q_D(XNModelObject);
|
||||
T_D();
|
||||
d->_sAuthor = sAuthor;
|
||||
}
|
||||
|
||||
// 获取模型配置文件路径
|
||||
const QString &XNModelObject::GetXmlPath()
|
||||
const std::string &XNModelObject::GetXmlPath()
|
||||
{
|
||||
Q_D(XNModelObject);
|
||||
T_D();
|
||||
return d->_sXmlPath;
|
||||
}
|
||||
|
||||
// 设置模型配置文件路径
|
||||
void XNModelObject::SetXmlPath(const QString &sXmlPath)
|
||||
void XNModelObject::SetXmlPath(const std::string &sXmlPath)
|
||||
{
|
||||
Q_D(XNModelObject);
|
||||
T_D();
|
||||
d->_sXmlPath = sXmlPath;
|
||||
}
|
||||
|
||||
// 获取模型创建时间
|
||||
const QDateTime &XNModelObject::GetCreateTime()
|
||||
const XNTimePoint &XNModelObject::GetCreateTime()
|
||||
{
|
||||
Q_D(XNModelObject);
|
||||
T_D();
|
||||
return d->_cCreatTime;
|
||||
}
|
||||
|
||||
// 设置模型创建时间
|
||||
void XNModelObject::SetCreateTime(const QDateTime &cTime)
|
||||
void XNModelObject::SetCreateTime(const XNTimePoint &cTime)
|
||||
{
|
||||
Q_D(XNModelObject);
|
||||
T_D();
|
||||
d->_cCreatTime = cTime;
|
||||
}
|
||||
|
||||
// 获取模型修改时间
|
||||
const QDateTime &XNModelObject::GetChangeTime()
|
||||
const XNTimePoint &XNModelObject::GetChangeTime()
|
||||
{
|
||||
Q_D(XNModelObject);
|
||||
T_D();
|
||||
return d->_cChangeTime;
|
||||
}
|
||||
|
||||
// 设置模型修改时间
|
||||
void XNModelObject::SetChangeTime(const QDateTime &cTime)
|
||||
void XNModelObject::SetChangeTime(const XNTimePoint &cTime)
|
||||
{
|
||||
Q_D(XNModelObject);
|
||||
T_D();
|
||||
d->_cChangeTime = cTime;
|
||||
}
|
||||
|
||||
// 获取模型版本号
|
||||
const QString &XNModelObject::GetVersion()
|
||||
const std::string &XNModelObject::GetVersion()
|
||||
{
|
||||
Q_D(XNModelObject);
|
||||
T_D();
|
||||
return d->_sVersion;
|
||||
}
|
||||
|
||||
// 设置模型版本号
|
||||
void XNModelObject::SetVersion(const QString &sVersion)
|
||||
void XNModelObject::SetVersion(const std::string &sVersion)
|
||||
{
|
||||
Q_D(XNModelObject);
|
||||
T_D();
|
||||
d->_sVersion = sVersion;
|
||||
}
|
||||
|
||||
void XNModelObject::SetBaseFreq(const double &dBaseFreq)
|
||||
{
|
||||
Q_D(XNModelObject);
|
||||
d->_setFreq = dBaseFreq;
|
||||
}
|
||||
|
||||
// 初始化函数
|
||||
void XNModelObject::OnInitialize()
|
||||
void XNModelObject::Initialize(uint32_t initialType, uint32_t threadID)
|
||||
{
|
||||
// 先尝试调取动态库
|
||||
Q_D(XNModelObject);
|
||||
T_D();
|
||||
if (initialType == 0) {
|
||||
// 读取配置文件,设置循环执行函数
|
||||
QFile file(GetXmlPath());
|
||||
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
std::ifstream file(GetXmlPath());
|
||||
if (!file.is_open()) {
|
||||
LOG_WARNING("0x2161 Failed to open the model configuration file: %1!", GetXmlPath());
|
||||
return;
|
||||
}
|
||||
QDomDocument doc;
|
||||
doc.setContent(&file);
|
||||
QDomElement rootNode = doc.documentElement();
|
||||
// 读取配置文件的模型参数
|
||||
QString modelName = rootNode.firstChildElement("Name").text();
|
||||
if (modelName != objectName()) {
|
||||
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!",
|
||||
objectName(), modelName);
|
||||
tinyxml2::XMLDocument doc;
|
||||
doc.LoadFile(GetXmlPath().c_str());
|
||||
tinyxml2::XMLElement *rootNode = doc.FirstChildElement("Model");
|
||||
if (!rootNode) {
|
||||
LOG_WARNING("0x2161 Failed to parse model configuration file: %1!", GetXmlPath());
|
||||
return;
|
||||
}
|
||||
d->_sDescription = rootNode.firstChildElement("Description").text();
|
||||
d->_sAuthor = rootNode.firstChildElement("Author").text();
|
||||
d->_sVersion = rootNode.firstChildElement("Version").text();
|
||||
d->_cCreatTime =
|
||||
QDateTime::fromString(rootNode.firstChildElement("CreateTime").text(), Qt::ISODate);
|
||||
d->_cChangeTime =
|
||||
QDateTime::fromString(rootNode.firstChildElement("ChangeTime").text(), Qt::ISODate);
|
||||
QString funcNode = rootNode.firstChildElement("Node").text();
|
||||
d->_runPriority = rootNode.firstChildElement("Priority").text().toInt();
|
||||
// 检查运行节点是否是 "x-x" 形式
|
||||
quint32 tmp = funcNode.indexOf('-');
|
||||
if (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!",
|
||||
objectName());
|
||||
// 读取配置文件的模型参数
|
||||
const char *modelName = rootNode->FirstChildElement("Name")->GetText();
|
||||
if (!modelName || std::string(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 ? modelName : "null");
|
||||
return;
|
||||
}
|
||||
d->_runFreq = funcNode.left(tmp).toInt();
|
||||
d->_setFreq = d->_setFreq / pow(2.0, d->_runFreq);
|
||||
d->_runNode = funcNode.right(funcNode.length() - tmp - 1).toInt();
|
||||
d->_sDescription = rootNode->FirstChildElement("Description")->GetText();
|
||||
d->_sAuthor = rootNode->FirstChildElement("Author")->GetText();
|
||||
d->_sVersion = rootNode->FirstChildElement("Version")->GetText();
|
||||
|
||||
// 使用标准C++时间处理
|
||||
std::string createTimeStr = rootNode->FirstChildElement("CreateTime")->GetText();
|
||||
std::string changeTimeStr = rootNode->FirstChildElement("ChangeTime")->GetText();
|
||||
d->_cCreatTime = parseISOTime(createTimeStr);
|
||||
d->_cChangeTime = parseISOTime(changeTimeStr);
|
||||
|
||||
std::string funcNode = rootNode->FirstChildElement("Node")->GetText();
|
||||
d->_runPriority = std::stoi(rootNode->FirstChildElement("Priority")->GetText());
|
||||
|
||||
// 检查运行节点是否是 "x-x" 形式
|
||||
size_t 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 = std::stoi(funcNode.substr(0, tmp));
|
||||
d->_setFreq = d->_setFreq / std::pow(2.0, d->_runFreq);
|
||||
d->_runNode = std::stoi(funcNode.substr(tmp + 1));
|
||||
|
||||
// 注册周期性函数
|
||||
emit RegisterFunction(getUniqueId(), std::bind(&XNModelObject::StepUpdate, this), d->_runFreq,
|
||||
d->_runNode, d->_runPriority);
|
||||
auto framework = GetFramework();
|
||||
if (framework) {
|
||||
auto threadManager = framework->GetThreadManager();
|
||||
if (threadManager) {
|
||||
threadManager->RegisterFunction(
|
||||
GetUniqueId(), std::bind(&XNModelObject::StepUpdate, this), threadID,
|
||||
d->_runFreq, d->_runNode, d->_runPriority);
|
||||
}
|
||||
}
|
||||
|
||||
// 加载动态库
|
||||
QString mathlib = rootNode.firstChildElement("MathLib").text();
|
||||
if (mathlib.size() != 0) {
|
||||
d->_sLibPath = QFileInfo(GetXmlPath()).absolutePath() + "/" + mathlib;
|
||||
d->_dynamicLib = new QLibrary(d->_sLibPath);
|
||||
if (d->_dynamicLib->load()) { // 动态库加载成功
|
||||
const char *mathlib = rootNode->FirstChildElement("MathLib")->GetText();
|
||||
if (mathlib && strlen(mathlib) > 0) {
|
||||
// 使用标准C++文件路径处理
|
||||
std::filesystem::path xmlPath(GetXmlPath());
|
||||
d->_sLibPath = xmlPath.parent_path().string() + "/" + mathlib;
|
||||
|
||||
// 使用标准C++动态库加载
|
||||
d->_dynamicLib = dlopen(d->_sLibPath.c_str(), RTLD_LAZY);
|
||||
if (d->_dynamicLib) { // 动态库加载成功
|
||||
LOG_INFO("0x2163 Model %1 loaded algorithm dynamic library %2 successfully!",
|
||||
objectName(), d->_sLibPath);
|
||||
GetObjectName(), d->_sLibPath);
|
||||
} else {
|
||||
LOG_WARNING(
|
||||
"0x2160 Model %1 failed to find algorithm dynamic library %2, will not call "
|
||||
"algorithm!",
|
||||
objectName(), d->_sLibPath);
|
||||
delete d->_dynamicLib;
|
||||
GetObjectName(), d->_sLibPath);
|
||||
d->_dynamicLib = nullptr;
|
||||
}
|
||||
}
|
||||
// TODO 指令列表
|
||||
QDomElement nodeCmds = rootNode.firstChildElement("CommandList");
|
||||
for (QDomElement nodeCmd = nodeCmds.firstChildElement("Command"); !nodeCmd.isNull();
|
||||
nodeCmd = nodeCmd.nextSiblingElement("Command")) {
|
||||
QString cmdName = nodeCmd.attribute("Name");
|
||||
QString cmdDescription = nodeCmd.attribute("Description");
|
||||
QString cmdCall = nodeCmd.attribute("Call");
|
||||
|
||||
// 处理指令列表
|
||||
tinyxml2::XMLElement *nodeCmds = rootNode->FirstChildElement("CommandList");
|
||||
if (nodeCmds) {
|
||||
for (tinyxml2::XMLElement *nodeCmd = nodeCmds->FirstChildElement("Command");
|
||||
nodeCmd != nullptr; nodeCmd = nodeCmd->NextSiblingElement("Command")) {
|
||||
const char *cmdName = nodeCmd->Attribute("Name");
|
||||
const char *cmdDescription = nodeCmd->Attribute("Description");
|
||||
const char *cmdCall = nodeCmd->Attribute("Call");
|
||||
// TODO: 处理命令列表
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 单步执行函数
|
||||
void XNModelObject::StepUpdate()
|
||||
{
|
||||
Q_D(XNModelObject);
|
||||
quint32 setFreq = d->_setFreq < 1.0 ? 1 : (quint32)d->_setFreq;
|
||||
if (d->_dataWriters.contains("XNSim::XNSimStatus::XNModelStatus")
|
||||
T_D();
|
||||
uint32_t setFreq = d->_setFreq < 1.0 ? 1 : (uint32_t)d->_setFreq;
|
||||
if (d->_dataWriters.find("XNSim::XNSimStatus::XNModelStatus") != d->_dataWriters.end()
|
||||
&& d->_dataWriters["XNSim::XNSimStatus::XNModelStatus"] != nullptr && d->_runCnt > 0
|
||||
&& d->_runCnt % setFreq == 0) {
|
||||
XNSim::XNSimStatus::XNModelStatus modelStatus;
|
||||
modelStatus.XNModelName(objectName().toStdString());
|
||||
modelStatus.XNModelID(getUniqueId());
|
||||
modelStatus.XNModelName(GetObjectName());
|
||||
modelStatus.XNModelID(GetUniqueId());
|
||||
modelStatus.XNModelSt(1);
|
||||
modelStatus.XNModelThID(pthread_self());
|
||||
modelStatus.XNModelThID(d->_threadID);
|
||||
modelStatus.XNModelNode(d->_runNode);
|
||||
modelStatus.XNModelPro(d->_runPriority);
|
||||
modelStatus.XNModelRunCnt(d->_runCnt);
|
||||
@ -216,15 +240,15 @@ void XNModelObject::StepUpdate()
|
||||
modelStatus.XNMdlSetFreq(d->_setFreq);
|
||||
d->_dataWriters["XNSim::XNSimStatus::XNModelStatus"]->write(&modelStatus);
|
||||
d->_lastRunTime = now;
|
||||
LOG_DEBUG("Model: %1 Write DDS!", objectName());
|
||||
LOG_DEBUG("Model: %1 Write DDS!", GetObjectName());
|
||||
}
|
||||
d->_runCnt++;
|
||||
}
|
||||
|
||||
// 运行前最后准备函数
|
||||
void XNModelObject::OnPrepareForExecute()
|
||||
void XNModelObject::PrepareForExecute()
|
||||
{
|
||||
Q_D(XNModelObject);
|
||||
T_D();
|
||||
d->_runCnt = 0;
|
||||
// 注册DDS
|
||||
RegisterDDSParticipant();
|
||||
@ -233,49 +257,53 @@ void XNModelObject::OnPrepareForExecute()
|
||||
|
||||
void XNModelObject::RegisterDDSParticipant()
|
||||
{
|
||||
Q_D(XNModelObject);
|
||||
XNModelManager *modelManager = qobject_cast<XNModelManager *>(parent());
|
||||
if (modelManager == nullptr)
|
||||
T_D();
|
||||
auto framework = GetFramework();
|
||||
if (framework == nullptr) {
|
||||
LOG_WARNING("Failed to get Framework!");
|
||||
return;
|
||||
XNDDSManager *ddsManager = modelManager->parent()->findChild<XNDDSManager *>();
|
||||
if (ddsManager == nullptr)
|
||||
}
|
||||
auto ddsManager = framework->GetDDSManager();
|
||||
if (ddsManager == nullptr) {
|
||||
LOG_WARNING("Failed to get DDSManager!");
|
||||
return;
|
||||
quint32 MyID = getUniqueId();
|
||||
}
|
||||
uint32_t MyID = GetUniqueId();
|
||||
XN_PUBLISHTOPIC(XNSim::XNSimStatus::XNModelStatus);
|
||||
}
|
||||
|
||||
int XNModelObject::RegisterEventHandler(const QString &eventName,
|
||||
std::function<void(const QVariant &)> callback, bool async,
|
||||
int XNModelObject::RegisterEventHandler(const std::string &eventName,
|
||||
std::function<void(const std::any &)> callback, bool async,
|
||||
XNEvent::Priority priority)
|
||||
{
|
||||
// 获取事件管理器
|
||||
XNModelManager *modelManager = qobject_cast<XNModelManager *>(parent());
|
||||
if (modelManager == nullptr) {
|
||||
LOG_WARNING("Failed to get ModelManager!");
|
||||
auto framework = GetFramework();
|
||||
if (framework == nullptr) {
|
||||
LOG_WARNING("Failed to get Framework!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
XNEventManager *eventManager = modelManager->parent()->findChild<XNEventManager *>();
|
||||
XNEventManagerPtr eventManager = framework->GetEventManager();
|
||||
if (eventManager == nullptr) {
|
||||
LOG_WARNING("Failed to get EventManager!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 注册事件处理器
|
||||
return eventManager->RegisterEventHandler(eventName, callback, getUniqueId(), async, priority);
|
||||
return eventManager->RegisterEventHandler(eventName, callback, GetUniqueId(), async, priority);
|
||||
}
|
||||
|
||||
void XNModelObject::TriggerEvent(const QString &eventName, const QVariant &eventData,
|
||||
void XNModelObject::TriggerEvent(const std::string &eventName, const std::any &eventData,
|
||||
bool forceAsync, XNEvent::Priority priority)
|
||||
{
|
||||
// 获取事件管理器
|
||||
XNModelManager *modelManager = qobject_cast<XNModelManager *>(parent());
|
||||
if (modelManager == nullptr) {
|
||||
LOG_WARNING("Failed to get ModelManager!");
|
||||
auto framework = GetFramework();
|
||||
if (framework == nullptr) {
|
||||
LOG_WARNING("Failed to get Framework!");
|
||||
return;
|
||||
}
|
||||
|
||||
XNEventManager *eventManager = modelManager->parent()->findChild<XNEventManager *>();
|
||||
XNEventManagerPtr eventManager = framework->GetEventManager();
|
||||
if (eventManager == nullptr) {
|
||||
LOG_WARNING("Failed to get EventManager!");
|
||||
return;
|
||||
|
@ -12,7 +12,7 @@
|
||||
#include "XNObject.h"
|
||||
#include "XNEventManager.h"
|
||||
|
||||
class XNModelObjectPrivate;
|
||||
struct XNModelObjectPrivate;
|
||||
|
||||
/**
|
||||
* @brief 模型基类
|
||||
@ -20,22 +20,14 @@ class XNModelObjectPrivate;
|
||||
*/
|
||||
class XNModelObject : public XNObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY(XNModelObject)
|
||||
Q_DECLARE_PRIVATE(XNModelObject)
|
||||
|
||||
Q_PROPERTY(QString description READ GetDescription WRITE SetDescription)
|
||||
Q_PROPERTY(QString author READ GetAuthor WRITE SetAuthor)
|
||||
Q_PROPERTY(QString xmlPath READ GetXmlPath WRITE SetXmlPath)
|
||||
Q_PROPERTY(QDateTime createTime READ GetCreateTime WRITE SetCreateTime)
|
||||
Q_PROPERTY(QDateTime changeTime READ GetChangeTime WRITE SetChangeTime)
|
||||
Q_PROPERTY(QString version READ GetVersion WRITE SetVersion)
|
||||
XN_METATYPE(XNModelObject, XNObject)
|
||||
XN_DECLARE_PRIVATE(XNModelObject)
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief 模型基类默认构造函数
|
||||
*/
|
||||
XNModelObject(QObject *parent = nullptr);
|
||||
XNModelObject();
|
||||
|
||||
/**
|
||||
* @brief 模型基类默认析构函数
|
||||
@ -45,89 +37,89 @@ public:
|
||||
protected:
|
||||
/**
|
||||
* @brief 模型基类带参构造函数
|
||||
* @param dd:XNModelObjectPrivate类型,私有结构体指针
|
||||
* @param parent:QObject类型,父对象指针
|
||||
* @param p:XNModelObjectPrivate类型,私有结构体指针
|
||||
* @details 子类构造时调用此构造函数,传入子类的私有结构体指针
|
||||
*/
|
||||
XNModelObject(XNModelObjectPrivate &dd, QObject *parent = nullptr);
|
||||
XNModelObject(PrivateType *p);
|
||||
|
||||
public:
|
||||
void SetFramework(XNFrameworkPtr framework);
|
||||
|
||||
protected:
|
||||
XNFrameworkPtr GetFramework() const;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief 获取模型描述
|
||||
* @return const QString&:模型描述
|
||||
*/
|
||||
const QString &GetDescription();
|
||||
const std::string &GetDescription();
|
||||
|
||||
/**
|
||||
* @brief 设置模型描述
|
||||
* @param sDescription:QString类型,模型描述
|
||||
*/
|
||||
void SetDescription(const QString &sDescription);
|
||||
void SetDescription(const std::string &sDescription);
|
||||
|
||||
/**
|
||||
* @brief 获取作者
|
||||
* @return const QString&: 作者
|
||||
*/
|
||||
const QString &GetAuthor();
|
||||
const std::string &GetAuthor();
|
||||
|
||||
/**
|
||||
* @brief 设置作者
|
||||
* @param sAuthor: QString类型,作者
|
||||
*/
|
||||
void SetAuthor(const QString &sAuthor);
|
||||
void SetAuthor(const std::string &sAuthor);
|
||||
|
||||
/**
|
||||
* @brief 获取模型配置文件路径
|
||||
* @return const QString&: 模型配置文件路径
|
||||
*/
|
||||
const QString &GetXmlPath();
|
||||
const std::string &GetXmlPath();
|
||||
|
||||
/**
|
||||
* @brief 设置模型配置文件路径
|
||||
* @param sXmlPath:QString类型,模型配置文件路径
|
||||
*/
|
||||
void SetXmlPath(const QString &sXmlPath);
|
||||
void SetXmlPath(const std::string &sXmlPath);
|
||||
|
||||
/**
|
||||
* @brief 获取模型创建时间
|
||||
* @return const QDateTime&:模型创建时间
|
||||
* @return const XNTimePoint&:模型创建时间
|
||||
*/
|
||||
const QDateTime &GetCreateTime();
|
||||
const XNTimePoint &GetCreateTime();
|
||||
|
||||
/**
|
||||
* @brief 设置模型创建时间
|
||||
* @param cTime: QDateTime类型,模型创建时间
|
||||
* @param cTime: XNTimePoint类型,模型创建时间
|
||||
*/
|
||||
void SetCreateTime(const QDateTime &cTime);
|
||||
void SetCreateTime(const XNTimePoint &cTime);
|
||||
|
||||
/**
|
||||
* @brief 获取模型修改时间
|
||||
* @return const QDateTime&:模型修改时间
|
||||
* @return const XNTimePoint&:模型修改时间
|
||||
*/
|
||||
const QDateTime &GetChangeTime();
|
||||
const XNTimePoint &GetChangeTime();
|
||||
|
||||
/**
|
||||
* @brief 设置模型修改时间
|
||||
* @param cTime: QDateTime类型,模型修改时间
|
||||
* @param cTime: XNTimePoint类型,模型修改时间
|
||||
*/
|
||||
void SetChangeTime(const QDateTime &cTime);
|
||||
void SetChangeTime(const XNTimePoint &cTime);
|
||||
|
||||
/**
|
||||
* @brief 获取模型版本号
|
||||
* @return const XNString&: 模型版本号
|
||||
*/
|
||||
const QString &GetVersion();
|
||||
/**
|
||||
* @brief 设置模型版本号
|
||||
* @param sVersion: QString类型,模型版本号
|
||||
*/
|
||||
void SetVersion(const QString &sVersion);
|
||||
const std::string &GetVersion();
|
||||
|
||||
/**
|
||||
* @brief 设置仿真系统运行基频
|
||||
* @param dBaseFreq: double类型,频率值,单位Hz
|
||||
* @brief 设置模型版本号
|
||||
* @param sVersion: std::string类型,模型版本号
|
||||
*/
|
||||
void SetBaseFreq(const double &dBaseFreq);
|
||||
void SetVersion(const std::string &sVersion);
|
||||
|
||||
/**
|
||||
* @brief 单步执行函数
|
||||
@ -142,8 +134,8 @@ public:
|
||||
* @param async: 是否异步处理
|
||||
* @return: 返回处理器ID,失败返回-1
|
||||
*/
|
||||
int RegisterEventHandler(const QString &eventName,
|
||||
std::function<void(const QVariant &)> callback, bool async = false,
|
||||
int RegisterEventHandler(const std::string &eventName, XNEventCallback callback,
|
||||
bool async = false,
|
||||
XNEvent::Priority priority = XNEvent::Priority::Normal);
|
||||
|
||||
/**
|
||||
@ -152,7 +144,7 @@ public:
|
||||
* @param eventData: 事件携带的数据
|
||||
* @param forceAsync: 强制异步处理
|
||||
*/
|
||||
void TriggerEvent(const QString &eventName, const QVariant &eventData = QVariant(),
|
||||
void TriggerEvent(const std::string &eventName, const std::any &eventData = std::any(),
|
||||
bool forceAsync = false,
|
||||
XNEvent::Priority priority = XNEvent::Priority::Normal);
|
||||
|
||||
@ -162,8 +154,7 @@ public:
|
||||
* @param callback: 事件处理回调函数
|
||||
* @return: 返回处理器ID,失败返回-1
|
||||
*/
|
||||
int RegisterRTEventHandler(const QString &eventName,
|
||||
std::function<void(const QVariant &)> callback)
|
||||
int RegisterRTEventHandler(const std::string &eventName, XNEventCallback callback)
|
||||
{
|
||||
return RegisterEventHandler(eventName, callback, true, XNEvent::Priority::RealTime);
|
||||
}
|
||||
@ -173,37 +164,23 @@ public:
|
||||
* @param eventName: 要触发的事件名称
|
||||
* @param eventData: 事件携带的数据
|
||||
*/
|
||||
void TriggerRTEvent(const QString &eventName, const QVariant &eventData = QVariant())
|
||||
void TriggerRTEvent(const std::string &eventName, const std::any &eventData = std::any())
|
||||
{
|
||||
TriggerEvent(eventName, eventData, true, XNEvent::Priority::RealTime);
|
||||
}
|
||||
|
||||
signals:
|
||||
/**
|
||||
* @brief 注册周期性执行的函数
|
||||
* @param id: quint32类型,模型ID
|
||||
* @param fun: QFunctionPointer类型,需要提交的函数的包装
|
||||
* @param freqGroup:UINT32类型,提交的函数运行频率组,0为基频,1为半频,2为1/4频,3为1/8频,4为1/16频,5为1/32频
|
||||
* @param RunPos: UINT32类型,提交的函数运行节点号,<2^(freqGroup)
|
||||
* @param RunPriorty:INT32类型,提交的函数运行优先级,99~0,优先级数值越大,优先级越高
|
||||
* @details 向线程管理器添加要周期性执行的函数
|
||||
*/
|
||||
void RegisterFunction(quint32 id, XNCallBack fun, quint32 freqGroup, quint32 RunPos,
|
||||
quint32 RunPriorty);
|
||||
|
||||
public slots:
|
||||
/**
|
||||
* @brief 初始化函数
|
||||
* @details
|
||||
* 模型的初始化函数接口,子类继承时要调用父类初始化接口,或在此函数中使用AddMyFunction方法注册需要被线程调用的函数
|
||||
*/
|
||||
virtual void OnInitialize();
|
||||
virtual void Initialize(uint32_t initialType, uint32_t threadID);
|
||||
|
||||
/**
|
||||
* @brief 仿真系统运行前做最后处理
|
||||
* @details 系统运行前模型做最后处理的接口
|
||||
*/
|
||||
virtual void OnPrepareForExecute();
|
||||
virtual void PrepareForExecute();
|
||||
|
||||
public:
|
||||
virtual void RegisterDDSParticipant();
|
||||
@ -218,11 +195,11 @@ public:
|
||||
{ \
|
||||
XNModelObject::RegisterDDSParticipant(); \
|
||||
Q_D(class); \
|
||||
XNModelManager *modelManager = qobject_cast<XNModelManager *>(parent()); \
|
||||
if (modelManager == nullptr) \
|
||||
auto framework = GetFramework(); \
|
||||
if (!framework) \
|
||||
return; \
|
||||
XNDDSManager *ddsManager = modelManager->parent()->findChild<XNDDSManager *>(); \
|
||||
if (ddsManager == nullptr) \
|
||||
XNDDSManagerPtr ddsManager = framework->GetDDSManager(); \
|
||||
if (!ddsManager) \
|
||||
return; \
|
||||
quint32 MyID = getUniqueId();
|
||||
|
||||
@ -234,3 +211,10 @@ public:
|
||||
#topic, MyID, std::bind(fun, this, std::placeholders::_1));
|
||||
|
||||
#define XN_REGISTER_PARTICIPANT_END(class) }
|
||||
|
||||
#define XN_MODEL_INITIALIZE(ClassName) \
|
||||
extern "C" XNModelObjectPtr Initial##ClassName() \
|
||||
{ \
|
||||
ClassNamePtr obj = std::make_shared<ClassName>(); \
|
||||
return obj; \
|
||||
}
|
||||
|
@ -10,62 +10,49 @@
|
||||
*/
|
||||
#pragma once
|
||||
#include "XNObject_p.h"
|
||||
#include <QLibrary>
|
||||
#include <QFunctionPointer>
|
||||
#include <QHash>
|
||||
#include <fastdds/dds/publisher/DataWriter.hpp>
|
||||
|
||||
/**
|
||||
* @brief 模型基类私有结构体
|
||||
*/
|
||||
class XNModelObjectPrivate : public XNObjectPrivate
|
||||
{
|
||||
public:
|
||||
Q_DECLARE_PUBLIC(XNModelObject)
|
||||
|
||||
/**
|
||||
* @brief 构造函数
|
||||
* @param q 模型基类指针
|
||||
*/
|
||||
explicit XNModelObjectPrivate(XNModelObject *q) : XNObjectPrivate(q) {}
|
||||
|
||||
struct XNModelObjectPrivate : public XNObjectPrivate {
|
||||
XNFrameworkPtr _framework;
|
||||
/**
|
||||
* @brief 模型描述
|
||||
*/
|
||||
QString _sDescription;
|
||||
std::string _sDescription;
|
||||
/**
|
||||
* @brief 模型作者
|
||||
*/
|
||||
QString _sAuthor;
|
||||
std::string _sAuthor;
|
||||
/**
|
||||
* @brief 模型配置文件路径
|
||||
*/
|
||||
QString _sXmlPath;
|
||||
std::string _sXmlPath;
|
||||
/**
|
||||
* @brief 数据包模型动态库路径
|
||||
*/
|
||||
QString _sLibPath;
|
||||
std::string _sLibPath;
|
||||
/**
|
||||
* @brief 模型创建时间
|
||||
*/
|
||||
QDateTime _cCreatTime;
|
||||
XNTimePoint _cCreatTime;
|
||||
/**
|
||||
* @brief 模型修改时间
|
||||
*/
|
||||
QDateTime _cChangeTime;
|
||||
XNTimePoint _cChangeTime;
|
||||
/**
|
||||
* @brief 模型版本号
|
||||
*/
|
||||
QString _sVersion;
|
||||
std::string _sVersion;
|
||||
/**
|
||||
* @brief 数据包模型动态库句柄
|
||||
*/
|
||||
QLibrary *_dynamicLib = nullptr;
|
||||
void *_dynamicLib = nullptr;
|
||||
|
||||
/**
|
||||
* @brief 发布者信息
|
||||
*/
|
||||
QHash<QString, FAST_DDS_MACRO::DataWriter *> _dataWriters;
|
||||
std::unordered_map<std::string, FAST_DDS_MACRO::DataWriter *> _dataWriters;
|
||||
|
||||
/**
|
||||
* @brief 模型运行时间
|
||||
@ -75,25 +62,30 @@ public:
|
||||
/**
|
||||
* @brief 模型运行次数
|
||||
*/
|
||||
quint64 _runCnt;
|
||||
uint64_t _runCnt;
|
||||
|
||||
/**
|
||||
* @brief 模型运行频率
|
||||
*/
|
||||
quint32 _runFreq;
|
||||
uint32_t _runFreq;
|
||||
|
||||
/**
|
||||
* @brief 模型运行节点
|
||||
*/
|
||||
quint32 _runNode;
|
||||
uint32_t _runNode;
|
||||
|
||||
/**
|
||||
* @brief 模型运行优先级
|
||||
*/
|
||||
quint32 _runPriority;
|
||||
uint32_t _runPriority;
|
||||
|
||||
/**
|
||||
* @brief 模型设置频率
|
||||
*/
|
||||
double _setFreq;
|
||||
|
||||
/**
|
||||
* @brief 模型线程ID
|
||||
*/
|
||||
uint32_t _threadID;
|
||||
};
|
||||
|
@ -1,28 +1,45 @@
|
||||
#include "XNObject.h"
|
||||
#include "XNObject_p.h"
|
||||
|
||||
XNObject::XNObject(QObject *parent) : QObject(parent), d_ptr(new XNObjectPrivate(this))
|
||||
XNObject::XNObject() : _Private_Ptr(new XNObjectPrivate())
|
||||
{
|
||||
_Private_Ptr->_Public_Ptr = this;
|
||||
}
|
||||
|
||||
XNObject::XNObject(XNObjectPrivate &dd, QObject *parent) : QObject(parent), d_ptr(&dd)
|
||||
XNObject::XNObject(PrivateType *p) : _Private_Ptr(p)
|
||||
{
|
||||
_Private_Ptr->_Public_Ptr = this;
|
||||
}
|
||||
|
||||
XNObject::~XNObject()
|
||||
{
|
||||
Q_D(XNObject);
|
||||
delete d;
|
||||
if (_Private_Ptr) {
|
||||
delete _Private_Ptr;
|
||||
}
|
||||
_Private_Ptr = nullptr;
|
||||
}
|
||||
|
||||
quint32 XNObject::getUniqueId()
|
||||
XNObjectPrivate::~XNObjectPrivate()
|
||||
{
|
||||
Q_D(XNObject);
|
||||
return d->uUniqueID;
|
||||
_Public_Ptr = nullptr;
|
||||
}
|
||||
|
||||
void XNObject::setUniqueId(const quint32 &uniqueId)
|
||||
uint32_t XNObject::GetUniqueId()
|
||||
{
|
||||
Q_D(XNObject);
|
||||
d->uUniqueID = uniqueId;
|
||||
return _Private_Ptr->uUniqueID;
|
||||
}
|
||||
|
||||
void XNObject::SetUniqueId(const uint32_t &uniqueId)
|
||||
{
|
||||
_Private_Ptr->uUniqueID = uniqueId;
|
||||
}
|
||||
|
||||
const std::string &XNObject::GetObjectName()
|
||||
{
|
||||
return _Private_Ptr->sObjectName;
|
||||
}
|
||||
|
||||
void XNObject::SetObjectName(const std::string &name)
|
||||
{
|
||||
_Private_Ptr->sObjectName = name;
|
||||
}
|
||||
|
@ -10,75 +10,83 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <QVariant>
|
||||
#include <QtXml/QDomDocument>
|
||||
|
||||
#include "XNCore_global.h"
|
||||
#include "XNLogger.h"
|
||||
|
||||
class XNObjectPrivate;
|
||||
struct XNObjectPrivate;
|
||||
|
||||
/**
|
||||
* @brief 基础对象类
|
||||
*/
|
||||
class XNCORE_EXPORT XNObject : public QObject
|
||||
class XNCORE_EXPORT XNObject : public std::enable_shared_from_this<XNObject>
|
||||
{
|
||||
XN_METATYPE_P(XNObject)
|
||||
XN_NOCOPYABLE(XNObject)
|
||||
protected:
|
||||
using PrivateType = XNObjectPrivate;
|
||||
/**
|
||||
* @brief 宏定义,用于支持Qt的元对象系统
|
||||
* @brief 私有数据成员
|
||||
*/
|
||||
Q_OBJECT
|
||||
|
||||
/**
|
||||
* @brief 宏定义,用于禁用拷贝构造函数
|
||||
*/
|
||||
Q_DISABLE_COPY(XNObject)
|
||||
|
||||
/**
|
||||
* @brief 宏定义,用于声明私有数据成员
|
||||
*/
|
||||
Q_DECLARE_PRIVATE(XNObject)
|
||||
|
||||
/**
|
||||
* @brief 宏定义,用于声明属性uniqueId
|
||||
*/
|
||||
Q_PROPERTY(quint32 UniqueId READ getUniqueId WRITE setUniqueId)
|
||||
PrivateType *_Private_Ptr;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief 构造函数
|
||||
* @param parent 父对象
|
||||
*/
|
||||
explicit XNObject(QObject *parent = nullptr);
|
||||
XNObject();
|
||||
|
||||
/**
|
||||
* @brief 析构函数
|
||||
*/
|
||||
virtual ~XNObject();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief 构造函数
|
||||
* @param p 私有数据成员
|
||||
*/
|
||||
XNObject(PrivateType *p);
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief 获取唯一ID
|
||||
* @return 唯一ID
|
||||
*/
|
||||
quint32 getUniqueId();
|
||||
uint32_t GetUniqueId();
|
||||
|
||||
/**
|
||||
* @brief 设置唯一ID
|
||||
* @param uniqueId 唯一ID
|
||||
*/
|
||||
void setUniqueId(const quint32 &uniqueId);
|
||||
void SetUniqueId(const uint32_t &uniqueId);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief 构造函数
|
||||
* @param dd 私有数据成员
|
||||
* @param parent 父对象
|
||||
* @brief 获取对象名称
|
||||
* @return 对象名称
|
||||
*/
|
||||
XNObject(XNObjectPrivate &dd, QObject *parent = nullptr);
|
||||
const std::string &GetObjectName();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief 私有数据成员
|
||||
* @brief 设置对象名称
|
||||
* @param name 对象名称
|
||||
*/
|
||||
XNObjectPrivate *d_ptr;
|
||||
void SetObjectName(const std::string &name);
|
||||
};
|
||||
|
||||
class XNFramework;
|
||||
class XNDDSManager;
|
||||
class XNEventManager;
|
||||
class XNModelManager;
|
||||
class XNScenarioManager;
|
||||
class XNServiceManager;
|
||||
class XNThreadManager;
|
||||
class XNTimeManager;
|
||||
|
||||
XNCLASS_PTR_DECLARE(XNFramework)
|
||||
XNCLASS_PTR_DECLARE(XNDDSManager)
|
||||
XNCLASS_PTR_DECLARE(XNEventManager)
|
||||
XNCLASS_PTR_DECLARE(XNModelManager)
|
||||
XNCLASS_PTR_DECLARE(XNScenarioManager)
|
||||
XNCLASS_PTR_DECLARE(XNServiceManager)
|
||||
XNCLASS_PTR_DECLARE(XNThreadManager)
|
||||
XNCLASS_PTR_DECLARE(XNTimeManager)
|
@ -15,28 +15,20 @@
|
||||
/**
|
||||
* @brief 基础对象类的私有数据成员
|
||||
*/
|
||||
class XNObjectPrivate
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief 宏定义,用于声明公有数据成员
|
||||
*/
|
||||
Q_DECLARE_PUBLIC(XNObject)
|
||||
|
||||
/**
|
||||
* @brief 构造函数
|
||||
* @param q 基础对象类指针
|
||||
*/
|
||||
explicit XNObjectPrivate(XNObject *q) : q_ptr(q) {}
|
||||
|
||||
struct XNObjectPrivate {
|
||||
virtual ~XNObjectPrivate();
|
||||
/**
|
||||
* @brief 基础对象类指针
|
||||
*/
|
||||
XNObject *q_ptr;
|
||||
XNObject *_Public_Ptr;
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief 唯一ID
|
||||
*/
|
||||
quint32 uUniqueID;
|
||||
uint32_t uUniqueID;
|
||||
|
||||
/**
|
||||
* @brief 对象名称
|
||||
*/
|
||||
std::string sObjectName;
|
||||
};
|
||||
|
@ -11,180 +11,192 @@
|
||||
#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(QObject *parent)
|
||||
: XNBaseFrameObject(*new XNScenarioManagerPrivate(this), parent)
|
||||
XNScenarioManager::XNScenarioManager() : XNBaseFrameObject(new XNScenarioManagerPrivate())
|
||||
{
|
||||
setUniqueId(5);
|
||||
setObjectName("XNScenarioManager");
|
||||
SetUniqueId(5);
|
||||
SetObjectName("XNScenarioManager");
|
||||
}
|
||||
|
||||
XNScenarioManager::~XNScenarioManager()
|
||||
{
|
||||
}
|
||||
|
||||
XNScenarioManager::XNScenarioManager(XNScenarioManagerPrivate &dd, QObject *parent)
|
||||
: XNBaseFrameObject(dd, parent)
|
||||
XNScenarioManager::XNScenarioManager(PrivateType *p) : XNBaseFrameObject(p)
|
||||
{
|
||||
}
|
||||
|
||||
// 获取运行环境名称
|
||||
const QString &XNScenarioManager::GetSimName()
|
||||
const std::string &XNScenarioManager::GetSimName()
|
||||
{
|
||||
Q_D(const XNScenarioManager);
|
||||
T_D();
|
||||
return d->_ScenarioName;
|
||||
}
|
||||
|
||||
// 设置运行环境名称
|
||||
void XNScenarioManager::SetSimName(QString &simName)
|
||||
void XNScenarioManager::SetSimName(const std::string &simName)
|
||||
{
|
||||
Q_D(XNScenarioManager);
|
||||
T_D();
|
||||
d->_ScenarioName = simName;
|
||||
}
|
||||
|
||||
// 获取运行环境开始时间
|
||||
const QDateTime &XNScenarioManager::GetSimStartTime()
|
||||
{
|
||||
Q_D(XNScenarioManager);
|
||||
return d->_SimStartTime;
|
||||
}
|
||||
|
||||
// 设置运行环境开始时间
|
||||
void XNScenarioManager::SetSimStartTime(QDateTime &startTime)
|
||||
{
|
||||
Q_D(XNScenarioManager);
|
||||
d->_SimStartTime = startTime;
|
||||
}
|
||||
|
||||
// 初始化
|
||||
void XNScenarioManager::OnInitialize()
|
||||
bool XNScenarioManager::Initialize()
|
||||
{
|
||||
Q_D(XNScenarioManager);
|
||||
T_D();
|
||||
LOG_INFO("XNScenarioManager Initialize Success!");
|
||||
d->_status = XNFrameObjectStatus::Initialized;
|
||||
emit Initialize();
|
||||
return true;
|
||||
}
|
||||
|
||||
void XNScenarioManager::OnPrepareForExecute()
|
||||
bool XNScenarioManager::PrepareForExecute()
|
||||
{
|
||||
Q_D(XNScenarioManager);
|
||||
T_D();
|
||||
d->_status = XNFrameObjectStatus::Ready;
|
||||
LOG_INFO("XNScenarioManager is prepared!");
|
||||
emit PrepareForExecute();
|
||||
return true;
|
||||
}
|
||||
|
||||
// 辅助函数:分割字符串
|
||||
std::vector<std::string> split(const std::string &str, const std::string &delim)
|
||||
{
|
||||
std::vector<std::string> tokens;
|
||||
size_t prev = 0, pos = 0;
|
||||
do {
|
||||
pos = str.find(delim, prev);
|
||||
if (pos == std::string::npos)
|
||||
pos = str.length();
|
||||
std::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;
|
||||
}
|
||||
|
||||
// 辅助函数:获取文件名(不含扩展名)
|
||||
std::string getFileNameWithoutExt(const std::string &path)
|
||||
{
|
||||
size_t lastDot = path.find_last_of('.');
|
||||
if (lastDot != std::string::npos) {
|
||||
return path.substr(0, lastDot);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
// 运行环境配置文件解析
|
||||
void XNScenarioManager::AnalysisScenarioXml(const QString &XmlPath)
|
||||
bool XNScenarioManager::AnalysisScenarioXml(const std::string &XmlPath)
|
||||
{
|
||||
Q_D(XNScenarioManager);
|
||||
QFile file(XmlPath);
|
||||
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
LOG_ERROR("0x2100 打开运行环境描述文件: %1出错,错误信息: %2", XmlPath,
|
||||
file.errorString());
|
||||
emit AnalyzeScenarioXmlFailed();
|
||||
return;
|
||||
T_D();
|
||||
std::ifstream file(XmlPath);
|
||||
if (!file.is_open()) {
|
||||
LOG_ERROR("0x2100 打开运行环境描述文件: %1出错,错误信息: %2", XmlPath, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
QDomDocument doc;
|
||||
if (!doc.setContent(&file)) {
|
||||
tinyxml2::XMLDocument doc;
|
||||
if (doc.LoadFile(XmlPath.c_str()) != tinyxml2::XML_SUCCESS) {
|
||||
LOG_ERROR("0x2100 解析XML文件: %1 失败", XmlPath);
|
||||
file.close();
|
||||
emit AnalyzeScenarioXmlFailed();
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
QDomElement root = doc.documentElement();
|
||||
tinyxml2::XMLElement *root = doc.FirstChildElement("Scenario");
|
||||
// 读取环境信息
|
||||
QDomElement envInfo = root.firstChildElement("Environment");
|
||||
QString OSName = envInfo.attribute("OSName");
|
||||
QString version = envInfo.attribute("Version");
|
||||
QString kernel = envInfo.attribute("RTXVersion");
|
||||
double basefreq = envInfo.attribute("BaseFrequency").toDouble();
|
||||
emit SetBaseFreq(basefreq);
|
||||
tinyxml2::XMLElement *envInfo = root->FirstChildElement("Environment");
|
||||
std::string OSName = envInfo->Attribute("OSName");
|
||||
std::string version = envInfo->Attribute("Version");
|
||||
std::string kernel = envInfo->Attribute("RTXVersion");
|
||||
// 设置工作目录
|
||||
QString rootPath = envInfo.attribute("WorkPath");
|
||||
emit SetWorkPath(rootPath);
|
||||
std::string rootPath = envInfo->Attribute("WorkPath");
|
||||
GetFramework()->SetWorkPath(rootPath);
|
||||
// 设置模型库目录
|
||||
QString modelPath = rootPath + envInfo.attribute("ModelsPath");
|
||||
emit SetModelPath(modelPath);
|
||||
std::string modelPath = rootPath + envInfo->Attribute("ModelsPath");
|
||||
GetFramework()->SetModelPath(modelPath);
|
||||
// 设置服务库目录
|
||||
QString servicePath = rootPath + envInfo.attribute("ServicesPath");
|
||||
emit SetServicePath(servicePath);
|
||||
quint32 domainID = envInfo.attribute("DomainID").toUInt();
|
||||
emit SetDomainID(domainID);
|
||||
std::string servicePath = rootPath + envInfo->Attribute("ServicesPath");
|
||||
GetFramework()->SetServicePath(servicePath);
|
||||
// 设置域ID
|
||||
uint32_t domainID = std::stoul(envInfo->Attribute("DomainID"));
|
||||
GetFramework()->GetDDSManager()->SetDomainID(domainID);
|
||||
// 读取CPU亲和性
|
||||
QString cpuAff = envInfo.attribute("CPUAffinity");
|
||||
QStringList cpuAffList = cpuAff.split(",");
|
||||
std::string cpuAff = envInfo->Attribute("CPUAffinity");
|
||||
std::vector<std::string> cpuAffList = split(cpuAff, ",");
|
||||
|
||||
//读取服务列表
|
||||
QDomElement serviceList = root.firstChildElement("ServicesList");
|
||||
for (int i = 0; i < serviceList.elementsByTagName("Service").count(); i++) {
|
||||
QDomElement service = serviceList.elementsByTagName("Service").at(i).toElement();
|
||||
QString serviceName = service.attribute("Name");
|
||||
QString libName = service.attribute("ClassName");
|
||||
libName = libName.left(libName.lastIndexOf('.'));
|
||||
QString dynamicLibName = servicePath + "lib" + libName + ".so";
|
||||
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");
|
||||
libName = getFileNameWithoutExt(libName);
|
||||
std::string dynamicLibName = servicePath + "lib" + libName + ".so";
|
||||
// 加载动态库
|
||||
emit LoadService(dynamicLibName, libName);
|
||||
GetFramework()->GetServiceManager()->LoadService(dynamicLibName, libName, 0);
|
||||
service = service->NextSiblingElement("Service");
|
||||
}
|
||||
}
|
||||
|
||||
// 默认按CAE模式,创建5个线程
|
||||
// emit AddThreadPool("100Hz thread", FreqLevel::BaseFreq, 99, 1, 1.0E9 / basefreq);
|
||||
// emit AddThreadPool("50Hz thread", FreqLevel::BaseFreq, 89, 1, 1.0E9 / basefreq);
|
||||
// emit AddThreadPool("25Hz thread", FreqLevel::BaseFreq, 79, 1, 1.0E9 / basefreq);
|
||||
// emit AddThreadPool("12.5Hz thread", FreqLevel::BaseFreq, 69, 1, 1.0E9 / basefreq);
|
||||
// emit AddThreadPool("6.25Hz thread", FreqLevel::BaseFreq, 59, 1, 1.0E9 / basefreq);
|
||||
// 读取模型分组
|
||||
for (int i = 0; i < root.elementsByTagName("ModelGroup").count(); i++) {
|
||||
// 读取模型分组信息
|
||||
QDomElement modelGroup = root.elementsByTagName("ModelGroup").at(i).toElement();
|
||||
tinyxml2::XMLElement *modelGroup = root->FirstChildElement("ModelGroup");
|
||||
while (modelGroup) {
|
||||
// 读取模型分组名称
|
||||
QString modelGroupName = modelGroup.attribute("Name");
|
||||
std::string modelGroupName = modelGroup->Attribute("Name");
|
||||
// 读取模型分组频率
|
||||
int modelGroupFreq = modelGroup.attribute("FreqGroup").toInt();
|
||||
if (modelGroupFreq > 5 || modelGroupFreq < 0) {
|
||||
LOG_ERROR("0x2100 模型分组频率设置错误,频率值:%1", modelGroupFreq);
|
||||
emit AnalyzeScenarioXmlFailed();
|
||||
return;
|
||||
}
|
||||
double modelGroupFreq = std::stod(modelGroup->Attribute("Freq"));
|
||||
// 读取模型分组优先级
|
||||
int modelGroupPriority = modelGroup.attribute("Priority").toInt();
|
||||
int modelGroupPriority = std::stoi(modelGroup->Attribute("Priority"));
|
||||
if (modelGroupPriority > 99 || modelGroupPriority < 0) {
|
||||
LOG_ERROR("0x2100 模型分组优先级设置错误,优先级值:%1", modelGroupPriority);
|
||||
emit AnalyzeScenarioXmlFailed();
|
||||
return;
|
||||
LOG_ERROR("0x2100 模型分组优先级设置错误,优先级值:%d", modelGroupPriority);
|
||||
return false;
|
||||
}
|
||||
// 读取模型分组CPU亲和性
|
||||
QString modelGroupCPUAff = modelGroup.attribute("CPUAff");
|
||||
QStringList modelGroupCPUAffList = modelGroupCPUAff.split(",");
|
||||
for (int j = 0; j < modelGroupCPUAffList.count(); j++) {
|
||||
if (!cpuAffList.contains(modelGroupCPUAffList.at(j))) {
|
||||
LOG_ERROR("0x2100 模型分组CPU亲和性设置错误,CPU亲和性值:%1,进程CPU亲和性值:%2",
|
||||
modelGroupCPUAffList.at(j), cpuAff);
|
||||
emit AnalyzeScenarioXmlFailed();
|
||||
return;
|
||||
std::string modelGroupCPUAff = modelGroup->Attribute("CPUAff");
|
||||
std::vector<std::string> modelGroupCPUAffList = 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 (int j = 0; j < modelGroupCPUAffList.count(); j++) {
|
||||
ThreadCpuAffinity |= 1 << cpuAffList.indexOf(modelGroupCPUAffList.at(j));
|
||||
}
|
||||
|
||||
emit AddThreadPool(modelGroupName, (FreqLevel)modelGroupFreq, modelGroupPriority,
|
||||
ThreadCpuAffinity, (1.0E9 / basefreq) * pow(2.0, modelGroupFreq));
|
||||
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);
|
||||
|
||||
// 读取模型列表
|
||||
for (int j = 0; j < modelGroup.elementsByTagName("Model").count(); j++) {
|
||||
QDomElement model = modelGroup.elementsByTagName("Model").at(j).toElement();
|
||||
QString modelName = model.attribute("Name");
|
||||
QString libName = model.attribute("ClassName");
|
||||
libName = libName.left(libName.lastIndexOf('.'));
|
||||
// 获得动态库的路径
|
||||
QString dynamicLibName = modelPath + "lib" + libName + ".so";
|
||||
tinyxml2::XMLElement *model = modelGroup->FirstChildElement("Model");
|
||||
while (model) {
|
||||
std::string modelName = model->Attribute("Name");
|
||||
std::string libName = model->Attribute("ClassName");
|
||||
libName = getFileNameWithoutExt(libName);
|
||||
std::string dynamicLibName = modelPath + "lib" + libName + ".so";
|
||||
// 加载动态库
|
||||
emit LoadModel(dynamicLibName, libName);
|
||||
GetFramework()->GetModelManager()->LoadModel(dynamicLibName, libName, 0, threadID);
|
||||
model = model->NextSiblingElement("Model");
|
||||
}
|
||||
}
|
||||
// TODO 提交事件
|
||||
|
||||
emit AnalyzeScenarioXmlSuccess();
|
||||
modelGroup = modelGroup->NextSiblingElement("ModelGroup");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -11,7 +11,7 @@
|
||||
#pragma once
|
||||
#include "XNBaseFrameObject.h"
|
||||
|
||||
class XNScenarioManagerPrivate;
|
||||
struct XNScenarioManagerPrivate;
|
||||
|
||||
/**
|
||||
* @brief 运行环境描述管理器类
|
||||
@ -19,14 +19,13 @@ class XNScenarioManagerPrivate;
|
||||
*/
|
||||
class XNScenarioManager : public XNBaseFrameObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DECLARE_PRIVATE(XNScenarioManager)
|
||||
Q_DISABLE_COPY(XNScenarioManager)
|
||||
XN_METATYPE(XNScenarioManager, XNBaseFrameObject)
|
||||
XN_DECLARE_PRIVATE(XNScenarioManager)
|
||||
public:
|
||||
/**
|
||||
* @brief 运行环境描述管理器类默认构造函数
|
||||
*/
|
||||
explicit XNScenarioManager(QObject *parent = nullptr);
|
||||
XNScenarioManager();
|
||||
|
||||
/**
|
||||
* @brief 运行环境描述管理器类析构函数
|
||||
@ -39,110 +38,39 @@ protected:
|
||||
* @param p:私有结构体指针
|
||||
* @details 子类构造时调用此构造函数,传入子类的私有结构体指针
|
||||
*/
|
||||
XNScenarioManager(XNScenarioManagerPrivate &dd, QObject *parent = nullptr);
|
||||
XNScenarioManager(PrivateType *p);
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief 获取运行环境名称
|
||||
* @return const XNString&: 运行环境名称
|
||||
*/
|
||||
const QString &GetSimName();
|
||||
const std::string &GetSimName();
|
||||
|
||||
/**
|
||||
* @brief 设置运行环境名称
|
||||
* @param simName: XNString类型,运行环境名称
|
||||
*/
|
||||
void SetSimName(QString &simName);
|
||||
void SetSimName(const std::string &simName);
|
||||
|
||||
/**
|
||||
* @brief 获取运行环境开始时间
|
||||
* @return const XNTime&: 运行环境开始时间
|
||||
*/
|
||||
const QDateTime &GetSimStartTime();
|
||||
|
||||
/**
|
||||
* @brief 设置运行环境开始时间
|
||||
* @param startTime: QDateTime类型,运行环境开始时间
|
||||
*/
|
||||
void SetSimStartTime(QDateTime &startTime);
|
||||
|
||||
signals:
|
||||
/**
|
||||
* @brief 信号,用于通知线程管理器添加线程
|
||||
*/
|
||||
void AddThreadPool(QString name, FreqLevel freq, quint32 priority, quint32 CPUAff,
|
||||
double RunInter);
|
||||
|
||||
/**
|
||||
* @brief 信号,用于通知模型管理器加载模型
|
||||
*/
|
||||
void LoadModel(const QString &modelPath, const QString &className);
|
||||
|
||||
/**
|
||||
* @brief 信号,用于通知服务管理器加载服务
|
||||
*/
|
||||
void LoadService(const QString &servicePath, const QString &className);
|
||||
|
||||
/**
|
||||
* @brief 信号,用于通知框架设置工作路径
|
||||
*/
|
||||
void SetWorkPath(const QString &workPath);
|
||||
|
||||
/**
|
||||
* @brief 信号,用于通知框架设置模型库路径
|
||||
*/
|
||||
void SetModelPath(const QString &modelPath);
|
||||
|
||||
/**
|
||||
* @brief 信号,用于通知框架设置服务库路径
|
||||
*/
|
||||
void SetServicePath(const QString &servicePath);
|
||||
|
||||
/**
|
||||
* @brief 信号,用于通知框架设置CPU亲和性
|
||||
*/
|
||||
void SetCpuAffinity(quint32 cpuAffinity);
|
||||
|
||||
/**
|
||||
* @brief 设置基础运行频率
|
||||
* @param freq: 基础运行频率,单位Hz
|
||||
*/
|
||||
void SetBaseFreq(const double &freq);
|
||||
|
||||
/**
|
||||
* @brief 设置DDS域ID
|
||||
* @param domainID: DDS域ID
|
||||
*/
|
||||
void SetDomainID(quint32 domainID);
|
||||
|
||||
/**
|
||||
* @brief 解析配置文件成功
|
||||
*/
|
||||
void AnalyzeScenarioXmlSuccess();
|
||||
|
||||
/**
|
||||
* @brief 解析配置文件失败
|
||||
*/
|
||||
void AnalyzeScenarioXmlFailed();
|
||||
|
||||
public slots:
|
||||
public:
|
||||
/**
|
||||
* @brief 初始化运行环境描述管理器
|
||||
* @return true: 初始化成功
|
||||
* @return false: 初始化失败
|
||||
* @details 运行环境描述管理器的初始化接口函数
|
||||
*/
|
||||
virtual void OnInitialize() override;
|
||||
virtual bool Initialize() override;
|
||||
|
||||
/**
|
||||
* @brief 仿真运行前最后处理
|
||||
* @note 运行环境描述管理器在系统运行开始前的准备工作
|
||||
*/
|
||||
virtual void OnPrepareForExecute() override;
|
||||
virtual bool PrepareForExecute() override;
|
||||
|
||||
/**
|
||||
* @brief 运行环境配置文件解析
|
||||
* @param XmlPath: QString类型,运行环境配置文件解析路径
|
||||
* @param XmlPath: std::string类型,运行环境配置文件解析路径
|
||||
*/
|
||||
virtual void AnalysisScenarioXml(const QString &XmlPath);
|
||||
virtual bool AnalysisScenarioXml(const std::string &XmlPath);
|
||||
};
|
||||
|
@ -14,19 +14,9 @@
|
||||
/**
|
||||
* @brief 运行环境描述管理器类私有结构体
|
||||
*/
|
||||
class XNScenarioManagerPrivate : public XNBaseFrameObjectPrivate
|
||||
{
|
||||
|
||||
public:
|
||||
Q_DECLARE_PUBLIC(XNScenarioManager)
|
||||
explicit XNScenarioManagerPrivate(XNScenarioManager *q) : XNBaseFrameObjectPrivate(q) {}
|
||||
struct XNScenarioManagerPrivate : public XNBaseFrameObjectPrivate {
|
||||
/**
|
||||
* @brief 运行环境名称
|
||||
*/
|
||||
QString _ScenarioName;
|
||||
|
||||
/**
|
||||
* @brief 运行环境开始时间
|
||||
*/
|
||||
QDateTime _SimStartTime;
|
||||
std::string _ScenarioName;
|
||||
};
|
||||
|
@ -4,13 +4,14 @@
|
||||
#include <QLibrary>
|
||||
#include <QMetaType>
|
||||
#include <QObject>
|
||||
#include <dlfcn.h>
|
||||
#include <filesystem>
|
||||
|
||||
XNServiceManager::XNServiceManager(QObject *parent)
|
||||
: XNBaseFrameObject(*new XNServiceManagerPrivate(this), parent)
|
||||
XNServiceManager::XNServiceManager() : XNBaseFrameObject(new XNServiceManagerPrivate())
|
||||
{
|
||||
setUniqueId(4);
|
||||
setObjectName("XNServiceManager");
|
||||
Q_D(XNServiceManager);
|
||||
SetUniqueId(4);
|
||||
SetObjectName("XNServiceManager");
|
||||
T_D();
|
||||
d->ServiceIDAssigned.resize(10000, false);
|
||||
}
|
||||
|
||||
@ -18,107 +19,91 @@ XNServiceManager::~XNServiceManager()
|
||||
{
|
||||
}
|
||||
|
||||
XNServiceManager::XNServiceManager(XNServiceManagerPrivate &dd, QObject *parent)
|
||||
: XNBaseFrameObject(dd, parent)
|
||||
XNServiceManager::XNServiceManager(PrivateType *p) : XNBaseFrameObject(p)
|
||||
{
|
||||
}
|
||||
|
||||
void XNServiceManager::OnInitialize()
|
||||
bool XNServiceManager::Initialize()
|
||||
{
|
||||
Q_D(XNServiceManager);
|
||||
T_D();
|
||||
LOG_INFO("XNServiceManager Initialize Success!");
|
||||
d->_status = XNFrameObjectStatus::Initialized;
|
||||
emit Initialize();
|
||||
return true;
|
||||
}
|
||||
|
||||
void XNServiceManager::OnPrepareForExecute()
|
||||
bool XNServiceManager::PrepareForExecute()
|
||||
{
|
||||
Q_D(XNServiceManager);
|
||||
T_D();
|
||||
d->_status = XNFrameObjectStatus::Ready;
|
||||
LOG_INFO("XNServiceManager is prepared!");
|
||||
emit PrepareForExecute();
|
||||
return true;
|
||||
}
|
||||
|
||||
void XNServiceManager::OnLoadService(const QString &servicePath, const QString &serviceName)
|
||||
void XNServiceManager::LoadService(const std::string &servicePath, const std::string &serviceName,
|
||||
uint32_t initialType)
|
||||
{
|
||||
Q_D(XNServiceManager);
|
||||
QLibrary lib(servicePath);
|
||||
if (lib.load()) {
|
||||
typedef void (*InitialServiceFunc)();
|
||||
QString initialServiceName = "Initial" + serviceName;
|
||||
T_D();
|
||||
void *handle = dlopen(servicePath.c_str(), RTLD_LAZY);
|
||||
if (handle) {
|
||||
typedef XNServiceObjectPtr (*InitialServiceFunc)();
|
||||
std::string initialServiceName = "Initial" + serviceName;
|
||||
InitialServiceFunc initialService =
|
||||
(InitialServiceFunc)lib.resolve(initialServiceName.toUtf8().constData());
|
||||
(InitialServiceFunc)dlsym(handle, initialServiceName.c_str());
|
||||
if (initialService) {
|
||||
initialService();
|
||||
QMetaType metaType = QMetaType::fromName(serviceName.toUtf8().constData());
|
||||
if (metaType.isValid()) {
|
||||
QObject *obj = static_cast<QObject *>(metaType.create());
|
||||
if (obj) {
|
||||
XNServiceObject *service = qobject_cast<XNServiceObject *>(obj);
|
||||
XNServiceObjectPtr service = initialService();
|
||||
if (service) {
|
||||
quint32 serviceID = RegisterService();
|
||||
uint32_t serviceID = RegisterService();
|
||||
if (serviceID == 0) {
|
||||
LOG_WARNING("0x2174 Assign Service ID Failed, Service ID is used up!");
|
||||
delete obj;
|
||||
dlclose(handle);
|
||||
return;
|
||||
}
|
||||
service->setParent(this);
|
||||
service->setObjectName(serviceName);
|
||||
service->setUniqueId(serviceID);
|
||||
QString configFilePath =
|
||||
QFileInfo(servicePath).absolutePath() + "/" + serviceName + ".scfg";
|
||||
service->SetXmlPath(configFilePath);
|
||||
connect(this, &XNServiceManager::PrepareForExecute, service,
|
||||
&XNServiceObject::OnPrepareForExecute);
|
||||
service->OnInitialize();
|
||||
service->SetUniqueId(serviceID);
|
||||
service->SetObjectName(serviceName);
|
||||
service->SetFramework(GetFramework());
|
||||
// 使用std::filesystem处理路径
|
||||
std::filesystem::path configPath =
|
||||
std::filesystem::path(servicePath).parent_path() / (serviceName + ".scfg");
|
||||
service->SetXmlPath(configPath.string());
|
||||
|
||||
// 注册服务到管理器
|
||||
d->ServiceList[serviceID] = service;
|
||||
|
||||
// 初始化服务
|
||||
service->Initialize(initialType);
|
||||
} else {
|
||||
LOG_WARNING("0x2175 Service %1 Instantiation Failed, Not a subclass of "
|
||||
"XNServiceObject!",
|
||||
serviceName);
|
||||
delete obj;
|
||||
LOG_WARNING("0x2173 Service %s Not found in dynamic link library %s!",
|
||||
serviceName.c_str(), servicePath.c_str());
|
||||
dlclose(handle);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
LOG_WARNING(
|
||||
"0x2176 Service %1 Instantiation Failed, Not a subclass of QObject!",
|
||||
serviceName);
|
||||
delete obj;
|
||||
"0x2177 Service %s Initialization Failed, Function InitialService Not Found!",
|
||||
serviceName.c_str());
|
||||
dlclose(handle);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
LOG_WARNING("0x2173 Service %1 Not found in dynamic link library %2!", serviceName,
|
||||
servicePath);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
LOG_WARNING("0x2177 Service %1 Initialization Failed, Function InitialService Not "
|
||||
"Found!",
|
||||
serviceName);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
LOG_WARNING("0x2172 Service %1 Dynamic link library loading failed! Error: %2", serviceName,
|
||||
lib.errorString());
|
||||
LOG_WARNING("0x2172 Service %s Dynamic link library loading failed! Error: %s",
|
||||
serviceName.c_str(), dlerror());
|
||||
}
|
||||
}
|
||||
|
||||
XNServiceObject *XNServiceManager::GetService(quint32 serviceID)
|
||||
XNServiceObjectPtr XNServiceManager::GetService(uint32_t serviceID)
|
||||
{
|
||||
Q_D(XNServiceManager);
|
||||
if (d->ServiceIDAssigned[serviceID - 20000]) {
|
||||
QList<XNServiceObject *> serviceList = findChildren<XNServiceObject *>();
|
||||
for (auto &service : serviceList) {
|
||||
if (service->getUniqueId() == serviceID)
|
||||
return service;
|
||||
T_D();
|
||||
if (d->ServiceIDAssigned[serviceID - 20000]
|
||||
&& d->ServiceList.find(serviceID) != d->ServiceList.end()) {
|
||||
return d->ServiceList[serviceID];
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
return nullptr;
|
||||
} else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
quint32 XNServiceManager::RegisterService()
|
||||
uint32_t XNServiceManager::RegisterService()
|
||||
{
|
||||
Q_D(XNServiceManager);
|
||||
T_D();
|
||||
// 从20000~29999的编号中分配ID
|
||||
for (int i = 0; i < 10000; i++) {
|
||||
if (d->ServiceIDAssigned[i])
|
||||
|
@ -3,26 +3,35 @@
|
||||
|
||||
// 添加前向声明
|
||||
class XNServiceObject;
|
||||
class XNServiceManagerPrivate;
|
||||
XNCLASS_PTR_DECLARE(XNServiceObject)
|
||||
|
||||
struct XNServiceManagerPrivate;
|
||||
|
||||
class XNServiceManager : public XNBaseFrameObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DECLARE_PRIVATE(XNServiceManager)
|
||||
Q_DISABLE_COPY(XNServiceManager)
|
||||
XN_METATYPE(XNServiceManager, XNBaseFrameObject)
|
||||
XN_DECLARE_PRIVATE(XNServiceManager)
|
||||
public:
|
||||
explicit XNServiceManager(QObject *parent = nullptr);
|
||||
/**
|
||||
* @brief 服务管理器类默认构造函数
|
||||
*/
|
||||
XNServiceManager();
|
||||
|
||||
/**
|
||||
* @brief 服务管理器类析构函数
|
||||
*/
|
||||
virtual ~XNServiceManager();
|
||||
|
||||
protected:
|
||||
XNServiceManager(XNServiceManagerPrivate &dd, QObject *parent = nullptr);
|
||||
|
||||
public slots:
|
||||
virtual void OnInitialize() override;
|
||||
virtual void OnPrepareForExecute() override;
|
||||
void OnLoadService(const QString &servicePath, const QString &serviceName);
|
||||
XNServiceManager(PrivateType *p);
|
||||
|
||||
public:
|
||||
XNServiceObject *GetService(quint32 serviceID);
|
||||
quint32 RegisterService();
|
||||
virtual bool Initialize() override;
|
||||
virtual bool PrepareForExecute() override;
|
||||
void LoadService(const std::string &servicePath, const std::string &serviceName,
|
||||
uint32_t initialType);
|
||||
|
||||
public:
|
||||
XNServiceObjectPtr GetService(uint32_t serviceID);
|
||||
uint32_t RegisterService();
|
||||
};
|
||||
|
@ -1,16 +1,16 @@
|
||||
#pragma once
|
||||
#include "XNBaseFrameObject_p.h"
|
||||
|
||||
class XNServiceManagerPrivate : public XNBaseFrameObjectPrivate
|
||||
{
|
||||
public:
|
||||
Q_DECLARE_PUBLIC(XNServiceManager)
|
||||
|
||||
explicit XNServiceManagerPrivate(XNServiceManager *q) : XNBaseFrameObjectPrivate(q) {}
|
||||
|
||||
struct XNServiceManagerPrivate : public XNBaseFrameObjectPrivate {
|
||||
/**
|
||||
* @brief 服务ID库
|
||||
* @details 所有服务已用ID的存储库
|
||||
*/
|
||||
QVector<bool> ServiceIDAssigned;
|
||||
std::vector<bool> ServiceIDAssigned;
|
||||
|
||||
/**
|
||||
* @brief 服务列表
|
||||
* @details 所有服务的存储库
|
||||
*/
|
||||
std::map<uint32_t, XNServiceObjectPtr> ServiceList;
|
||||
};
|
@ -1,7 +1,9 @@
|
||||
#include "XNServiceObject.h"
|
||||
#include "XNServiceObject_p.h"
|
||||
#include "XNEventManager.h"
|
||||
#include "XNFramework.h"
|
||||
|
||||
XNServiceObject::XNServiceObject(QObject *parent) : XNObject(parent)
|
||||
XNServiceObject::XNServiceObject() : XNObject(new XNServiceObjectPrivate())
|
||||
{
|
||||
}
|
||||
|
||||
@ -9,179 +11,191 @@ XNServiceObject::~XNServiceObject()
|
||||
{
|
||||
}
|
||||
|
||||
XNServiceObject::XNServiceObject(XNServiceObjectPrivate &dd, QObject *parent) : XNObject(dd, parent)
|
||||
XNServiceObject::XNServiceObject(PrivateType *p) : XNObject(p)
|
||||
{
|
||||
}
|
||||
|
||||
const QString &XNServiceObject::GetVersion()
|
||||
const std::string &XNServiceObject::GetVersion()
|
||||
{
|
||||
Q_D(XNServiceObject);
|
||||
T_D();
|
||||
return d->_sVersion;
|
||||
}
|
||||
|
||||
const QString &XNServiceObject::GetDescription()
|
||||
const std::string &XNServiceObject::GetDescription()
|
||||
{
|
||||
Q_D(XNServiceObject);
|
||||
T_D();
|
||||
return d->_sDescription;
|
||||
}
|
||||
|
||||
const QString &XNServiceObject::GetAuthor()
|
||||
const std::string &XNServiceObject::GetAuthor()
|
||||
{
|
||||
Q_D(XNServiceObject);
|
||||
T_D();
|
||||
return d->_sAuthor;
|
||||
}
|
||||
|
||||
const QString &XNServiceObject::GetXmlPath()
|
||||
const std::string &XNServiceObject::GetXmlPath()
|
||||
{
|
||||
Q_D(XNServiceObject);
|
||||
T_D();
|
||||
return d->_sXmlPath;
|
||||
}
|
||||
|
||||
const QDateTime &XNServiceObject::GetCreateTime()
|
||||
const XNTimePoint &XNServiceObject::GetCreateTime()
|
||||
{
|
||||
Q_D(XNServiceObject);
|
||||
T_D();
|
||||
return d->_cCreateTime;
|
||||
}
|
||||
|
||||
const QDateTime &XNServiceObject::GetChangeTime()
|
||||
const XNTimePoint &XNServiceObject::GetChangeTime()
|
||||
{
|
||||
Q_D(XNServiceObject);
|
||||
T_D();
|
||||
return d->_cChangeTime;
|
||||
}
|
||||
|
||||
void XNServiceObject::SetVersion(const QString &version)
|
||||
void XNServiceObject::SetVersion(const std::string &version)
|
||||
{
|
||||
Q_D(XNServiceObject);
|
||||
T_D();
|
||||
d->_sVersion = version;
|
||||
}
|
||||
|
||||
void XNServiceObject::SetDescription(const QString &sDescription)
|
||||
void XNServiceObject::SetDescription(const std::string &sDescription)
|
||||
{
|
||||
Q_D(XNServiceObject);
|
||||
T_D();
|
||||
d->_sDescription = sDescription;
|
||||
}
|
||||
|
||||
void XNServiceObject::SetAuthor(const QString &sAuthor)
|
||||
void XNServiceObject::SetAuthor(const std::string &sAuthor)
|
||||
{
|
||||
Q_D(XNServiceObject);
|
||||
T_D();
|
||||
d->_sAuthor = sAuthor;
|
||||
}
|
||||
|
||||
void XNServiceObject::SetXmlPath(const QString &sXmlPath)
|
||||
void XNServiceObject::SetXmlPath(const std::string &sXmlPath)
|
||||
{
|
||||
Q_D(XNServiceObject);
|
||||
T_D();
|
||||
d->_sXmlPath = sXmlPath;
|
||||
}
|
||||
|
||||
void XNServiceObject::SetCreateTime(const QDateTime &cTime)
|
||||
void XNServiceObject::SetCreateTime(const XNTimePoint &cTime)
|
||||
{
|
||||
Q_D(XNServiceObject);
|
||||
T_D();
|
||||
d->_cCreateTime = cTime;
|
||||
}
|
||||
|
||||
void XNServiceObject::SetChangeTime(const QDateTime &cTime)
|
||||
void XNServiceObject::SetChangeTime(const XNTimePoint &cTime)
|
||||
{
|
||||
Q_D(XNServiceObject);
|
||||
T_D();
|
||||
d->_cChangeTime = cTime;
|
||||
}
|
||||
|
||||
int XNServiceObject::RegisterEventHandler(const QString &eventName,
|
||||
std::function<void(const QVariant &)> callback,
|
||||
int XNServiceObject::RegisterEventHandler(const std::string &eventName, XNEventCallback callback,
|
||||
bool async, XNEvent::Priority priority)
|
||||
{
|
||||
// 注册事件处理器
|
||||
Q_D(XNServiceObject);
|
||||
if (d->pEventManager) {
|
||||
return d->pEventManager->RegisterEventHandler(eventName, callback, getUniqueId(), async,
|
||||
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 QString &eventName, const QVariant &eventData,
|
||||
void XNServiceObject::TriggerEvent(const std::string &eventName, const std::any &eventData,
|
||||
bool forceAsync, XNEvent::Priority priority)
|
||||
{
|
||||
// 触发事件
|
||||
Q_D(XNServiceObject);
|
||||
if (d->pEventManager) {
|
||||
d->pEventManager->TriggerEvent(eventName, eventData, forceAsync, priority);
|
||||
T_D();
|
||||
auto framework = GetFramework();
|
||||
if (framework) {
|
||||
auto eventManager = framework->GetEventManager();
|
||||
if (eventManager) {
|
||||
eventManager->TriggerEvent(eventName, eventData, forceAsync, priority);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int XNServiceObject::RegisterRTEventHandler(const QString &eventName,
|
||||
std::function<void(const QVariant &)> callback)
|
||||
int XNServiceObject::RegisterRTEventHandler(const std::string &eventName, XNEventCallback callback)
|
||||
{
|
||||
return RegisterEventHandler(eventName, callback, true, XNEvent::Priority::RealTime);
|
||||
}
|
||||
|
||||
void XNServiceObject::TriggerRTEvent(const QString &eventName, const QVariant &eventData)
|
||||
void XNServiceObject::TriggerRTEvent(const std::string &eventName, const std::any &eventData)
|
||||
{
|
||||
TriggerEvent(eventName, eventData, true, XNEvent::Priority::RealTime);
|
||||
}
|
||||
|
||||
void XNServiceObject::OnInitialize()
|
||||
void XNServiceObject::Initialize(uint32_t initialType)
|
||||
{
|
||||
Q_D(XNServiceObject);
|
||||
// 获取事件管理器
|
||||
XNServiceManager *serviceManager = qobject_cast<XNServiceManager *>(parent());
|
||||
if (serviceManager == nullptr) {
|
||||
LOG_WARNING("Failed to get ServiceManager!");
|
||||
return;
|
||||
}
|
||||
|
||||
d->pEventManager = serviceManager->parent()->findChild<XNEventManager *>();
|
||||
if (d->pEventManager == nullptr) {
|
||||
LOG_WARNING("Failed to get EventManager!");
|
||||
return;
|
||||
}
|
||||
|
||||
QFile file(GetXmlPath());
|
||||
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
T_D();
|
||||
if (initialType == 0) {
|
||||
tinyxml2::XMLDocument doc;
|
||||
if (doc.LoadFile(GetXmlPath().c_str()) != tinyxml2::XML_SUCCESS) {
|
||||
LOG_WARNING("Failed to open the service configuration file: %1!", GetXmlPath());
|
||||
return;
|
||||
}
|
||||
QDomDocument doc;
|
||||
doc.setContent(&file);
|
||||
|
||||
QDomElement rootNode = doc.documentElement();
|
||||
QString serviceName = rootNode.firstChildElement("Name").text();
|
||||
if (serviceName != objectName()) {
|
||||
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!",
|
||||
objectName(), serviceName);
|
||||
tinyxml2::XMLElement *rootNode = doc.RootElement();
|
||||
if (!rootNode) {
|
||||
LOG_WARNING("Invalid XML file format: %1!", GetXmlPath());
|
||||
return;
|
||||
}
|
||||
d->_sDescription = rootNode.firstChildElement("Description").text();
|
||||
d->_sAuthor = rootNode.firstChildElement("Author").text();
|
||||
d->_sVersion = rootNode.firstChildElement("Version").text();
|
||||
d->_cCreateTime =
|
||||
QDateTime::fromString(rootNode.firstChildElement("CreateTime").text(), Qt::ISODate);
|
||||
d->_cChangeTime =
|
||||
QDateTime::fromString(rootNode.firstChildElement("ChangeTime").text(), Qt::ISODate);
|
||||
|
||||
QDomElement nodeCmds = rootNode.firstChildElement("CommandList");
|
||||
for (QDomElement nodeCmd = nodeCmds.firstChildElement("Command"); !nodeCmd.isNull();
|
||||
nodeCmd = nodeCmd.nextSiblingElement("Command")) {
|
||||
QString cmdName = nodeCmd.attribute("Name");
|
||||
QString cmdDescription = nodeCmd.attribute("Description");
|
||||
QString cmdCall = nodeCmd.attribute("Call");
|
||||
const char *serviceName = rootNode->FirstChildElement("Name")->GetText();
|
||||
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 = rootNode->FirstChildElement("Description")->GetText();
|
||||
d->_sAuthor = rootNode->FirstChildElement("Author")->GetText();
|
||||
d->_sVersion = rootNode->FirstChildElement("Version")->GetText();
|
||||
|
||||
// 解析时间
|
||||
const char *createTimeStr = rootNode->FirstChildElement("CreateTime")->GetText();
|
||||
const char *changeTimeStr = rootNode->FirstChildElement("ChangeTime")->GetText();
|
||||
d->_cCreateTime = parseISOTime(createTimeStr);
|
||||
d->_cChangeTime = parseISOTime(changeTimeStr);
|
||||
|
||||
tinyxml2::XMLElement *nodeCmds = rootNode->FirstChildElement("CommandList");
|
||||
if (nodeCmds) {
|
||||
for (tinyxml2::XMLElement *nodeCmd = nodeCmds->FirstChildElement("Command");
|
||||
nodeCmd != nullptr; nodeCmd = nodeCmd->NextSiblingElement("Command")) {
|
||||
const char *cmdName = nodeCmd->Attribute("Name");
|
||||
const char *cmdDescription = nodeCmd->Attribute("Description");
|
||||
const char *cmdCall = nodeCmd->Attribute("Call");
|
||||
// TODO: 处理命令信息
|
||||
}
|
||||
}
|
||||
} else {
|
||||
}
|
||||
}
|
||||
|
||||
void XNServiceObject::OnPrepareForExecute()
|
||||
void XNServiceObject::PrepareForExecute()
|
||||
{
|
||||
Q_D(XNServiceObject);
|
||||
T_D();
|
||||
RegisterDDSParticipant();
|
||||
}
|
||||
|
||||
void XNServiceObject::RegisterDDSParticipant()
|
||||
{
|
||||
Q_D(XNServiceObject);
|
||||
T_D();
|
||||
//TODO 注册服务状态主题参与者
|
||||
}
|
||||
|
||||
XNEventManager *XNServiceObject::GetEventManager() const
|
||||
XNFrameworkPtr XNServiceObject::GetFramework() const
|
||||
{
|
||||
Q_D(const XNServiceObject);
|
||||
return d->pEventManager;
|
||||
T_D();
|
||||
return d->pFramework;
|
||||
}
|
||||
|
||||
void XNServiceObject::SetFramework(XNFrameworkPtr framework)
|
||||
{
|
||||
T_D();
|
||||
d->pFramework = framework;
|
||||
}
|
||||
|
@ -3,68 +3,59 @@
|
||||
#include "XNObject.h"
|
||||
#include "XNServiceManager.h"
|
||||
#include "XNEventManager.h"
|
||||
|
||||
class XNServiceObjectPrivate;
|
||||
struct XNServiceObjectPrivate;
|
||||
|
||||
class XNServiceObject : public XNObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DECLARE_PRIVATE(XNServiceObject)
|
||||
Q_DISABLE_COPY(XNServiceObject)
|
||||
|
||||
Q_PROPERTY(QString description READ GetDescription WRITE SetDescription)
|
||||
Q_PROPERTY(QString author READ GetAuthor WRITE SetAuthor)
|
||||
Q_PROPERTY(QString xmlPath READ GetXmlPath WRITE SetXmlPath)
|
||||
Q_PROPERTY(QDateTime createTime READ GetCreateTime WRITE SetCreateTime)
|
||||
Q_PROPERTY(QDateTime changeTime READ GetChangeTime WRITE SetChangeTime)
|
||||
Q_PROPERTY(QString version READ GetVersion WRITE SetVersion)
|
||||
|
||||
XN_METATYPE(XNServiceObject, XNObject)
|
||||
XN_DECLARE_PRIVATE(XNServiceObject)
|
||||
public:
|
||||
explicit XNServiceObject(QObject *parent = nullptr);
|
||||
XNServiceObject();
|
||||
virtual ~XNServiceObject();
|
||||
|
||||
protected:
|
||||
explicit XNServiceObject(XNServiceObjectPrivate &dd, QObject *parent = nullptr);
|
||||
XNServiceObject(PrivateType *p);
|
||||
|
||||
public:
|
||||
const QString &GetVersion();
|
||||
const QString &GetDescription();
|
||||
const QString &GetAuthor();
|
||||
const QString &GetXmlPath();
|
||||
const QDateTime &GetCreateTime();
|
||||
const QDateTime &GetChangeTime();
|
||||
const std::string &GetVersion();
|
||||
const std::string &GetDescription();
|
||||
const std::string &GetAuthor();
|
||||
const std::string &GetXmlPath();
|
||||
const XNTimePoint &GetCreateTime();
|
||||
const XNTimePoint &GetChangeTime();
|
||||
|
||||
void SetVersion(const QString &version);
|
||||
void SetDescription(const QString &description);
|
||||
void SetAuthor(const QString &author);
|
||||
void SetXmlPath(const QString &xmlPath);
|
||||
void SetCreateTime(const QDateTime &createTime);
|
||||
void SetChangeTime(const QDateTime &changeTime);
|
||||
void SetVersion(const std::string &version);
|
||||
void SetDescription(const std::string &description);
|
||||
void SetAuthor(const std::string &author);
|
||||
void SetXmlPath(const std::string &xmlPath);
|
||||
void SetCreateTime(const XNTimePoint &createTime);
|
||||
void SetChangeTime(const XNTimePoint &changeTime);
|
||||
|
||||
int RegisterEventHandler(const QString &eventName,
|
||||
std::function<void(const QVariant &)> callback, bool async = false,
|
||||
int RegisterEventHandler(const std::string &eventName, XNEventCallback callback,
|
||||
bool async = false,
|
||||
XNEvent::Priority priority = XNEvent::Priority::Normal);
|
||||
|
||||
void TriggerEvent(const QString &eventName, const QVariant &eventData = QVariant(),
|
||||
void TriggerEvent(const std::string &eventName, const std::any &eventData = std::any(),
|
||||
bool forceAsync = false,
|
||||
XNEvent::Priority priority = XNEvent::Priority::Normal);
|
||||
|
||||
int RegisterRTEventHandler(const QString &eventName,
|
||||
std::function<void(const QVariant &)> callback);
|
||||
int RegisterRTEventHandler(const std::string &eventName, XNEventCallback callback);
|
||||
|
||||
void TriggerRTEvent(const QString &eventName, const QVariant &eventData = QVariant());
|
||||
void TriggerRTEvent(const std::string &eventName, const std::any &eventData = std::any());
|
||||
|
||||
public slots:
|
||||
virtual void OnInitialize();
|
||||
virtual void OnPrepareForExecute();
|
||||
virtual void Initialize(uint32_t initialType);
|
||||
virtual void PrepareForExecute();
|
||||
|
||||
public:
|
||||
virtual void RegisterDDSParticipant();
|
||||
|
||||
private:
|
||||
XNEventManager *GetEventManager() const;
|
||||
void SetFramework(XNFrameworkPtr framework);
|
||||
|
||||
protected:
|
||||
XNFrameworkPtr GetFramework() const;
|
||||
};
|
||||
|
||||
XNCLASS_PTR_DECLARE(XNServiceObject)
|
||||
|
||||
#define XN_DECLARE_DDS_SERVICE() \
|
||||
public: \
|
||||
virtual void RegisterDDSParticipant() override;
|
||||
@ -74,11 +65,11 @@ public:
|
||||
{ \
|
||||
XNServiceObject::RegisterDDSParticipant(); \
|
||||
Q_D(class); \
|
||||
XNServiceManager *serviceManager = qobject_cast<XNServiceManager *>(parent()); \
|
||||
if (serviceManager == nullptr) \
|
||||
auto framework = GetFramework(); \
|
||||
if (!framework) \
|
||||
return; \
|
||||
XNDDSManager *ddsManager = serviceManager->parent()->findChild<XNDDSManager *>(); \
|
||||
if (ddsManager == nullptr) \
|
||||
XNDDSManagerPtr ddsManager = framework->GetDDSManager(); \
|
||||
if (!ddsManager) \
|
||||
return; \
|
||||
quint32 MyID = getUniqueId();
|
||||
|
||||
@ -90,3 +81,10 @@ public:
|
||||
#topic, MyID, std::bind(fun, this, std::placeholders::_1));
|
||||
|
||||
#define XN_REGISTER_SERVICE_END_SERVICE(class) }
|
||||
|
||||
#define XN_SERVICE_INITIALIZE(ClassName) \
|
||||
extern "C" XNServiceObjectPtr Initial##ClassName() \
|
||||
{ \
|
||||
ClassNamePtr obj = std::make_shared<ClassName>(); \
|
||||
return obj; \
|
||||
}
|
||||
|
@ -1,21 +1,13 @@
|
||||
#pragma once
|
||||
#include "XNObject_p.h"
|
||||
#include <QHash>
|
||||
#include <fastdds/dds/publisher/DataWriter.hpp>
|
||||
#include "XNEventManager.h"
|
||||
class XNServiceObjectPrivate : public XNObjectPrivate
|
||||
{
|
||||
public:
|
||||
Q_DECLARE_PUBLIC(XNServiceObject)
|
||||
explicit XNServiceObjectPrivate(XNServiceObject *q) : XNObjectPrivate(q) {}
|
||||
|
||||
QString _sDescription;
|
||||
QString _sAuthor;
|
||||
QString _sXmlPath;
|
||||
QDateTime _cCreateTime;
|
||||
QDateTime _cChangeTime;
|
||||
QString _sVersion;
|
||||
QHash<QString, FAST_DDS_MACRO::DataWriter *> _dataWriters;
|
||||
|
||||
XNEventManager *pEventManager;
|
||||
struct XNServiceObjectPrivate : public XNObjectPrivate {
|
||||
std::string _sDescription;
|
||||
std::string _sAuthor;
|
||||
std::string _sXmlPath;
|
||||
XNTimePoint _cCreateTime;
|
||||
XNTimePoint _cChangeTime;
|
||||
std::string _sVersion;
|
||||
std::unordered_map<std::string, FAST_DDS_MACRO::DataWriter *> _dataWriters;
|
||||
XNFrameworkPtr pFramework;
|
||||
};
|
||||
|
@ -10,152 +10,65 @@
|
||||
*/
|
||||
#include "XNLogger.h"
|
||||
#include "XNThread.h"
|
||||
#include "XNThread_p.h"
|
||||
#include "XNFramework.h"
|
||||
#include "XNThreadManager.h"
|
||||
#include "XNDDSManager.h"
|
||||
#include "XNIDL/XNSimStatusPubSubTypes.hpp"
|
||||
|
||||
/**
|
||||
* @brief 线程类私有结构体
|
||||
*/
|
||||
class XNThreadPrivate
|
||||
XNThread::XNThread(std::string name, double freq, uint32_t priority, uint32_t CPUAff)
|
||||
: XNObject(new XNThreadPrivate())
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief 宏定义,用于声明公有数据成员
|
||||
*/
|
||||
Q_DECLARE_PUBLIC(XNThread)
|
||||
|
||||
/**
|
||||
* @brief 构造函数
|
||||
* @param q 线程类指针
|
||||
*/
|
||||
explicit XNThreadPrivate(XNThread *q) : q_ptr(q) {}
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief 线程类指针
|
||||
*/
|
||||
XNThread *q_ptr;
|
||||
/**
|
||||
* @brief 线程运行频率组
|
||||
*/
|
||||
FreqLevel _eRunFreq = FreqLevel::BaseFreq;
|
||||
/**
|
||||
* @brief 线程运行优先级
|
||||
*/
|
||||
quint32 _uPriority = 0;
|
||||
/**
|
||||
* @brief 线程CPU亲和性掩码
|
||||
* @details 按位表示某CPU核是否使用,从低到高,0表示不使用,1表示使用。例如:0x00000003表示使用0,1号CPU
|
||||
*/
|
||||
quint32 _uAffinity = 0;
|
||||
/**
|
||||
* @brief 线程运行频率
|
||||
*/
|
||||
double _setFreq = BASE_RUN_FREQ;
|
||||
/**
|
||||
* @brief 线程调度任务表
|
||||
*/
|
||||
QVector<QMap<quint32, QVector<XNCallBack> > > _funVec;
|
||||
/**
|
||||
* @brief pthread线程调度参数
|
||||
*/
|
||||
sched_param param;
|
||||
/**
|
||||
* @brief pthread线程属性
|
||||
*/
|
||||
pthread_attr_t attr;
|
||||
/**
|
||||
* @brief pthread线程
|
||||
*/
|
||||
pthread_t thread;
|
||||
/**
|
||||
* @brief 线程睡眠时间控制
|
||||
*/
|
||||
PERIOD_INFO pinfo;
|
||||
/**
|
||||
* @brief 线程控制锁
|
||||
*/
|
||||
pthread_mutex_t _mtx = PTHREAD_MUTEX_INITIALIZER;
|
||||
/**
|
||||
* @brief 线程控制条件变量
|
||||
*/
|
||||
pthread_cond_t _cond = PTHREAD_COND_INITIALIZER;
|
||||
/**
|
||||
* @brief 线程运行状态
|
||||
*/
|
||||
RunStatus _eRunStatus = RunStatus::NotStart;
|
||||
/**
|
||||
* @brief 线程执行进度
|
||||
*/
|
||||
quint32 _RunPosition = 0;
|
||||
/**
|
||||
* @brief 线程执行计数
|
||||
*/
|
||||
int count = 0;
|
||||
/**
|
||||
* @brief 线程执行时间统计
|
||||
*/
|
||||
timespec _lastRunTime;
|
||||
/**
|
||||
* @brief 线程运行状态主题写入器
|
||||
*/
|
||||
FAST_DDS_MACRO::DataWriter *writer;
|
||||
/**
|
||||
* @brief 线程ID
|
||||
*/
|
||||
quint32 _threadID = 0;
|
||||
};
|
||||
|
||||
// 默认构造函数
|
||||
XNThread::XNThread(QObject *parent) : QObject(parent), d_ptr(new XNThreadPrivate(this))
|
||||
{
|
||||
}
|
||||
|
||||
XNThread::XNThread(QObject *parent, QString name, FreqLevel freq, quint32 priority, quint32 CPUAff,
|
||||
double RunInter)
|
||||
: QObject(parent), d_ptr(new XNThreadPrivate(this))
|
||||
{
|
||||
Q_D(XNThread);
|
||||
setObjectName(name);
|
||||
d->_eRunFreq = freq;
|
||||
SetObjectName(name);
|
||||
T_D();
|
||||
d->_uPriority = priority;
|
||||
d->_uAffinity = CPUAff;
|
||||
d->pinfo.period_ns = RunInter;
|
||||
d->_setFreq = 1.0E9 / RunInter;
|
||||
InitialFunPool();
|
||||
d->pinfo.period_ns = 1.0E9 / freq;
|
||||
d->_setFreq = freq;
|
||||
d->_funVec.resize(32);
|
||||
//InitialFunPool();
|
||||
}
|
||||
|
||||
// 默认析构函数
|
||||
XNThread::~XNThread(void)
|
||||
{
|
||||
Q_D(XNThread);
|
||||
delete d;
|
||||
}
|
||||
|
||||
XNFrameworkPtr XNThread::GetFramework()
|
||||
{
|
||||
T_D();
|
||||
return d->_framework;
|
||||
}
|
||||
|
||||
void XNThread::SetFramework(XNFrameworkPtr framework)
|
||||
{
|
||||
T_D();
|
||||
d->_framework = framework;
|
||||
}
|
||||
|
||||
// 初始化函数
|
||||
bool XNThread::Initialize()
|
||||
{
|
||||
Q_D(XNThread);
|
||||
T_D();
|
||||
int ret;
|
||||
// 初始化线程参数
|
||||
ret = pthread_attr_init(&(d->attr));
|
||||
if (ret) {
|
||||
LOG_ERROR("0x2210 Thread: %1 Initialize Attribute Failed!", objectName());
|
||||
LOG_ERROR("0x2210 Thread: %1 Initialize Attribute Failed!", GetObjectName());
|
||||
return false;
|
||||
}
|
||||
|
||||
// 设置线程栈空间大小
|
||||
ret = pthread_attr_setstacksize(&(d->attr), PTHREAD_STACK_MIN);
|
||||
if (ret) {
|
||||
LOG_ERROR("0x2211 Thread: %1 Set Stack Space Failed!", objectName());
|
||||
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!", objectName());
|
||||
LOG_ERROR("0x2212 Thread: %1 Set Scheduling Policy Failed!", GetObjectName());
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -163,21 +76,21 @@ bool XNThread::Initialize()
|
||||
d->param.sched_priority = d->_uPriority;
|
||||
ret = pthread_attr_setschedparam(&(d->attr), &d->param);
|
||||
if (ret) {
|
||||
LOG_ERROR("0x2213 Thread: %1 Set Priority Failed!", objectName());
|
||||
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!", objectName());
|
||||
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!", objectName());
|
||||
LOG_ERROR("0x2215 Thread: %1 Create Failed!", GetObjectName());
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -186,34 +99,32 @@ bool XNThread::Initialize()
|
||||
return false;
|
||||
}
|
||||
|
||||
// if (objectName() == "TimeManagerThread")
|
||||
// return true;
|
||||
XNThreadManager *threadManager = qobject_cast<XNThreadManager *>(parent());
|
||||
if (threadManager == nullptr) {
|
||||
LOG_WARNING("0x2216 Thread: %1 get ThreadManager Failed!", objectName());
|
||||
XNFrameworkPtr framework = GetFramework();
|
||||
if (!framework) {
|
||||
LOG_WARNING("0x2216 Thread: %1 get Framework Failed!", GetObjectName());
|
||||
return true;
|
||||
}
|
||||
|
||||
XNDDSManager *ddsManager = threadManager->parent()->findChild<XNDDSManager *>();
|
||||
if (ddsManager == nullptr) {
|
||||
LOG_WARNING("0x2216 Thread: %1 get DDSManager Failed!", objectName());
|
||||
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!", objectName());
|
||||
LOG_WARNING("0x2217 Thread: %1 get DDS Writer Failed!", GetObjectName());
|
||||
return true;
|
||||
}
|
||||
LOG_INFO("Thread: %1 is prepared!", objectName());
|
||||
LOG_INFO("Thread: %1 is prepared!", GetObjectName());
|
||||
return true;
|
||||
}
|
||||
|
||||
// 仿真控制
|
||||
void XNThread::OnSimControl(quint32 objectId, SimControlCmd cmd)
|
||||
void XNThread::SimControl(uint32_t objectId, SimControlCmd cmd)
|
||||
{
|
||||
Q_D(XNThread);
|
||||
T_D();
|
||||
if (objectId == 0) {
|
||||
switch (cmd) {
|
||||
case SimControlCmd::Start:
|
||||
@ -235,7 +146,7 @@ void XNThread::OnSimControl(quint32 objectId, SimControlCmd cmd)
|
||||
// 开始执行
|
||||
void XNThread::Start()
|
||||
{
|
||||
Q_D(XNThread);
|
||||
T_D();
|
||||
pthread_mutex_lock(&d->_mtx);
|
||||
// 设置运行状态
|
||||
if (d->_eRunStatus == RunStatus::NotStart || d->_eRunStatus == RunStatus::Suspend) {
|
||||
@ -243,26 +154,26 @@ void XNThread::Start()
|
||||
}
|
||||
pthread_cond_signal(&d->_cond);
|
||||
pthread_mutex_unlock(&d->_mtx);
|
||||
LOG_INFO("Thread: %1 Start!", objectName());
|
||||
LOG_INFO("Thread: %1 Start!", GetObjectName());
|
||||
}
|
||||
|
||||
// 暂停执行
|
||||
void XNThread::Pause()
|
||||
{
|
||||
Q_D(XNThread);
|
||||
T_D();
|
||||
pthread_mutex_lock(&d->_mtx);
|
||||
// 设置运行状态
|
||||
if (d->_eRunStatus == RunStatus::Runing) {
|
||||
d->_eRunStatus = RunStatus::Suspend;
|
||||
}
|
||||
pthread_mutex_unlock(&d->_mtx);
|
||||
LOG_INFO("Thread: %1 Pause!", objectName());
|
||||
LOG_INFO("Thread: %1 Pause!", GetObjectName());
|
||||
}
|
||||
|
||||
// 继续执行
|
||||
void XNThread::Continue()
|
||||
{
|
||||
Q_D(XNThread);
|
||||
T_D();
|
||||
pthread_mutex_lock(&d->_mtx);
|
||||
// 设置运行状态
|
||||
if (d->_eRunStatus == RunStatus::Suspend) {
|
||||
@ -275,7 +186,7 @@ void XNThread::Continue()
|
||||
// 停止执行
|
||||
void XNThread::Stop(bool force)
|
||||
{
|
||||
Q_D(XNThread);
|
||||
T_D();
|
||||
if (force) {
|
||||
pthread_mutex_lock(&d->_mtx);
|
||||
// 设置运行状态
|
||||
@ -291,34 +202,34 @@ void XNThread::Stop(bool force)
|
||||
pthread_mutex_unlock(&d->_mtx);
|
||||
Join();
|
||||
}
|
||||
LOG_INFO("Thread: %1 Stop!", objectName());
|
||||
LOG_INFO("Thread: %1 Stop!", GetObjectName());
|
||||
}
|
||||
|
||||
// 加入线程
|
||||
void XNThread::Join()
|
||||
{
|
||||
Q_D(XNThread);
|
||||
T_D();
|
||||
pthread_join(d->thread, NULL);
|
||||
}
|
||||
|
||||
// 分离线程
|
||||
void XNThread::Detach()
|
||||
{
|
||||
Q_D(XNThread);
|
||||
T_D();
|
||||
pthread_detach(d->thread);
|
||||
}
|
||||
|
||||
// 获取线程运行状态
|
||||
RunStatus XNThread::GetRunStatus()
|
||||
{
|
||||
Q_D(XNThread);
|
||||
T_D();
|
||||
return d->_eRunStatus;
|
||||
}
|
||||
|
||||
// 向线程添加周期性函数
|
||||
void XNThread::AddFunction(XNCallBack fun, FreqLevel freq, quint32 pos, quint32 priorty)
|
||||
void XNThread::AddFunction(XNCallBack fun, FreqLevel freq, uint32_t pos, uint32_t priorty)
|
||||
{
|
||||
Q_D(XNThread);
|
||||
T_D();
|
||||
for (int i = 0; i < d->_funVec.size();) {
|
||||
if (i + pos >= d->_funVec.size())
|
||||
break;
|
||||
@ -350,60 +261,51 @@ void XNThread::AddFunction(XNCallBack fun, FreqLevel freq, quint32 pos, quint32
|
||||
}
|
||||
|
||||
// 获取线程运行频率
|
||||
const FreqLevel &XNThread::GetRunFrequecy()
|
||||
const double &XNThread::GetRunFrequecy()
|
||||
{
|
||||
Q_D(XNThread);
|
||||
return d->_eRunFreq;
|
||||
T_D();
|
||||
return d->_setFreq;
|
||||
}
|
||||
|
||||
// 设置线程运行频率
|
||||
void XNThread::SetRunFrequecy(const FreqLevel &eRunFrequecy)
|
||||
void XNThread::SetRunFrequecy(const double &dRunFrequecy)
|
||||
{
|
||||
Q_D(XNThread);
|
||||
d->_eRunFreq = eRunFrequecy;
|
||||
InitialFunPool();
|
||||
T_D();
|
||||
d->_setFreq = dRunFrequecy;
|
||||
}
|
||||
|
||||
// 获取线程运行优先级
|
||||
const quint32 &XNThread::GetRunPriority()
|
||||
const uint32_t &XNThread::GetRunPriority()
|
||||
{
|
||||
Q_D(XNThread);
|
||||
T_D();
|
||||
return d->_uPriority;
|
||||
}
|
||||
|
||||
// 设置线程运行优先级
|
||||
void XNThread::SetRunPriority(const quint32 &uRunPriority)
|
||||
void XNThread::SetRunPriority(const uint32_t &uRunPriority)
|
||||
{
|
||||
Q_D(XNThread);
|
||||
T_D();
|
||||
d->_uPriority = uRunPriority;
|
||||
}
|
||||
|
||||
// 获取线程CPU亲和性掩码
|
||||
const quint32 &XNThread::GetCPUAffinity()
|
||||
const uint32_t &XNThread::GetCPUAffinity()
|
||||
{
|
||||
Q_D(XNThread);
|
||||
T_D();
|
||||
return d->_uAffinity;
|
||||
}
|
||||
|
||||
// 设置线程CPU亲和性掩码
|
||||
void XNThread::SetCPUAffinity(const quint32 &uCPUAffinity)
|
||||
void XNThread::SetCPUAffinity(const uint32_t &uCPUAffinity)
|
||||
{
|
||||
Q_D(XNThread);
|
||||
T_D();
|
||||
d->_uAffinity = uCPUAffinity;
|
||||
}
|
||||
|
||||
// 设置线程运行间隔
|
||||
void XNThread::SetRunInter(const double &dRunInter)
|
||||
{
|
||||
Q_D(XNThread);
|
||||
d->pinfo.period_ns = dRunInter;
|
||||
d->_setFreq = 1.0E9 / dRunInter;
|
||||
}
|
||||
|
||||
// 获取线程运行间隔
|
||||
void XNThread::OnSetStartTime(const timespec &startTime)
|
||||
void XNThread::SetStartTime(const timespec &startTime)
|
||||
{
|
||||
Q_D(XNThread);
|
||||
T_D();
|
||||
d->pinfo.next_period = startTime;
|
||||
d->_lastRunTime = startTime;
|
||||
}
|
||||
@ -411,7 +313,7 @@ void XNThread::OnSetStartTime(const timespec &startTime)
|
||||
// 执行线程CPU亲和性设置
|
||||
bool XNThread::OnSetCPUAffinity()
|
||||
{
|
||||
Q_D(XNThread);
|
||||
T_D();
|
||||
cpu_set_t mask;
|
||||
CPU_ZERO(&mask);
|
||||
int cpuNum = sysconf(_SC_NPROCESSORS_CONF);
|
||||
@ -420,7 +322,7 @@ bool XNThread::OnSetCPUAffinity()
|
||||
CPU_SET(i, &mask);
|
||||
}
|
||||
if (pthread_setaffinity_np(d->thread, sizeof(mask), &mask) == -1) {
|
||||
LOG_WARNING("0x2216 线程: %1 设置CPU亲和性失败!", objectName());
|
||||
LOG_WARNING("0x2216 线程: %1 设置CPU亲和性失败!", GetObjectName());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@ -430,7 +332,8 @@ bool XNThread::OnSetCPUAffinity()
|
||||
void *XNThread::ThreadFunction(void *args)
|
||||
{
|
||||
// 获取创建线程类的私有变量结构体指针
|
||||
XNThreadPrivate *temp = ((XNThread *)args)->d_ptr;
|
||||
ThisType *thisPtr = (ThisType *)args;
|
||||
PrivateType *temp = thisPtr->GetPP();
|
||||
|
||||
// 获取当前时间
|
||||
// clock_gettime(CLOCK_MONOTONIC, &(temp->pinfo.next_period));
|
||||
@ -461,7 +364,7 @@ void *XNThread::ThreadFunction(void *args)
|
||||
// 任务执行
|
||||
auto &funMap = temp->_funVec[temp->_RunPosition++];
|
||||
for (auto &funv : funMap) {
|
||||
for (auto &fun : funv) {
|
||||
for (auto &fun : funv.second) {
|
||||
fun();
|
||||
}
|
||||
}
|
||||
@ -476,16 +379,16 @@ void *XNThread::ThreadFunction(void *args)
|
||||
pthread_mutex_unlock(&temp->_mtx);
|
||||
|
||||
// 填写DDS主题数据
|
||||
quint32 setFreq = (1.0E9 / temp->pinfo.period_ns) < 1.0 ? 1 : (quint32)temp->_setFreq;
|
||||
uint32_t setFreq = (1.0E9 / temp->pinfo.period_ns) < 1.0 ? 1 : (uint32_t)temp->_setFreq;
|
||||
if (temp->writer != nullptr && temp->count > 0 && temp->count % setFreq == 0) {
|
||||
timespec now;
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
double seconds = (double)(now.tv_sec - temp->_lastRunTime.tv_sec)
|
||||
+ (double)(now.tv_nsec - temp->_lastRunTime.tv_nsec) / 1.0E9;
|
||||
XNSim::XNSimStatus::XNThreadStatus threadStatus;
|
||||
threadStatus.XNThreadName(temp->q_ptr->objectName().toStdString());
|
||||
threadStatus.XNThreadName(thisPtr->GetObjectName());
|
||||
threadStatus.XNThreadID(pthread_self());
|
||||
threadStatus.XNThreadSt((quint32)temp->_eRunStatus);
|
||||
threadStatus.XNThreadSt((uint32_t)temp->_eRunStatus);
|
||||
threadStatus.XNThreadAff(temp->_uAffinity);
|
||||
threadStatus.XNThreadPro(temp->_uPriority);
|
||||
threadStatus.XNThRunCnt(temp->count);
|
||||
@ -494,7 +397,7 @@ void *XNThread::ThreadFunction(void *args)
|
||||
temp->writer->write(&threadStatus);
|
||||
temp->_lastRunTime = now;
|
||||
LOG_DEBUG("Thread: %1 Write DDS! SetFreq: %2 Hz, CurFreq: %3 Hz",
|
||||
temp->q_ptr->objectName(), temp->_setFreq, temp->_setFreq / seconds);
|
||||
thisPtr->GetObjectName(), temp->_setFreq, temp->_setFreq / seconds);
|
||||
}
|
||||
temp->count++;
|
||||
|
||||
@ -514,43 +417,43 @@ void *XNThread::ThreadFunction(void *args)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// 初始化线程调度表
|
||||
void XNThread::InitialFunPool()
|
||||
{
|
||||
Q_D(XNThread);
|
||||
// 设置循环表长度
|
||||
switch (d->_eRunFreq) {
|
||||
case FreqLevel::BaseFreq:
|
||||
d->_funVec.resize(32);
|
||||
break;
|
||||
case FreqLevel::HalfFreq:
|
||||
d->_funVec.resize(16);
|
||||
break;
|
||||
case FreqLevel::QuarterFreq:
|
||||
d->_funVec.resize(8);
|
||||
break;
|
||||
case FreqLevel::EighthFreq:
|
||||
d->_funVec.resize(4);
|
||||
break;
|
||||
case FreqLevel::SixteenthFreq:
|
||||
d->_funVec.resize(2);
|
||||
break;
|
||||
default:
|
||||
d->_funVec.resize(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// // 初始化线程调度表
|
||||
// void XNThread::InitialFunPool()
|
||||
// {
|
||||
// T_D();
|
||||
// // 设置循环表长度
|
||||
// switch (d->_eRunFreq) {
|
||||
// case FreqLevel::BaseFreq:
|
||||
// d->_funVec.resize(32);
|
||||
// break;
|
||||
// case FreqLevel::HalfFreq:
|
||||
// d->_funVec.resize(16);
|
||||
// break;
|
||||
// case FreqLevel::QuarterFreq:
|
||||
// d->_funVec.resize(8);
|
||||
// break;
|
||||
// case FreqLevel::EighthFreq:
|
||||
// d->_funVec.resize(4);
|
||||
// break;
|
||||
// case FreqLevel::SixteenthFreq:
|
||||
// d->_funVec.resize(2);
|
||||
// break;
|
||||
// default:
|
||||
// d->_funVec.resize(1);
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
|
||||
// 获取线程ID
|
||||
const quint32 &XNThread::GetThreadID()
|
||||
const uint32_t &XNThread::GetThreadID()
|
||||
{
|
||||
Q_D(XNThread);
|
||||
T_D();
|
||||
return d->_threadID;
|
||||
}
|
||||
|
||||
// 设置线程ID
|
||||
void XNThread::SetThreadID(const quint32 &threadID)
|
||||
void XNThread::SetThreadID(const uint32_t &threadID)
|
||||
{
|
||||
Q_D(XNThread);
|
||||
T_D();
|
||||
d->_threadID = threadID;
|
||||
}
|
||||
|
@ -9,36 +9,43 @@
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
#include <QObject>
|
||||
#include <QThread>
|
||||
#include "XNCore_global.h"
|
||||
#include "XNObject.h"
|
||||
|
||||
class XNThreadPrivate;
|
||||
struct XNThreadPrivate;
|
||||
|
||||
/**
|
||||
* @brief 调度线程类
|
||||
* @details 调度所有模型提交的周期性执行函数
|
||||
*/
|
||||
class XNCORE_EXPORT XNThread : public QObject
|
||||
class XNCORE_EXPORT XNThread : public XNObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY(XNThread)
|
||||
Q_DECLARE_PRIVATE(XNThread)
|
||||
XN_METATYPE(XNThread, XNObject)
|
||||
XN_DECLARE_PRIVATE(XNThread)
|
||||
|
||||
public:
|
||||
explicit XNThread(QObject *parent = nullptr);
|
||||
XNThread(QObject *parent = nullptr, QString name = "", FreqLevel freq = FreqLevel::BaseFreq,
|
||||
quint32 priority = 99, quint32 CPUAff = 0, double RunInter = BASE_RUN_INTER);
|
||||
XNThread() = delete;
|
||||
|
||||
protected:
|
||||
XNThreadPrivate *d_ptr;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief 默认析构函数
|
||||
*/
|
||||
virtual ~XNThread();
|
||||
|
||||
explicit XNThread(std::string name = "", double freq = BASE_RUN_FREQ, uint32_t priority = 99,
|
||||
uint32_t CPUAff = 0);
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief 获取框架对象
|
||||
* @return 框架对象
|
||||
*/
|
||||
XNFrameworkPtr GetFramework();
|
||||
|
||||
/**
|
||||
* @brief 设置框架对象
|
||||
* @param framework 框架对象
|
||||
*/
|
||||
void SetFramework(XNFrameworkPtr framework);
|
||||
|
||||
/**
|
||||
* @brief 线程初始化
|
||||
* @return true: 初始化成功
|
||||
@ -46,26 +53,19 @@ public:
|
||||
*/
|
||||
bool Initialize();
|
||||
|
||||
public slots:
|
||||
/**
|
||||
* @brief 仿真控制
|
||||
* @param objectId: 对象ID
|
||||
* @param cmd: 仿真控制命令
|
||||
*/
|
||||
void OnSimControl(quint32 objectId, SimControlCmd cmd);
|
||||
void SimControl(uint32_t objectId, SimControlCmd cmd);
|
||||
|
||||
/**
|
||||
* @brief 设置线程运行的开始时间
|
||||
* @param simTime: timespec结构体类型,用于线程纳秒睡眠计算的开始时间
|
||||
* @details 通过设置统一的开始时间,使个线程能同步执行
|
||||
*/
|
||||
void OnSetStartTime(const timespec &simTime);
|
||||
|
||||
/**
|
||||
* @brief 设置线程运行间隔
|
||||
* @param dRunInter: double类型,线程运行间隔,单位纳秒
|
||||
*/
|
||||
void SetRunInter(const double &dRunInter);
|
||||
void SetStartTime(const timespec &simTime);
|
||||
|
||||
/**
|
||||
* @brief 加入线程
|
||||
@ -78,19 +78,73 @@ public slots:
|
||||
*/
|
||||
void Detach();
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief 获取线程ID
|
||||
* @return const quint32&: 线程ID
|
||||
*/
|
||||
const quint32 &GetThreadID();
|
||||
const uint32_t &GetThreadID();
|
||||
|
||||
/**
|
||||
* @brief 设置线程ID
|
||||
* @param threadID: 线程ID
|
||||
*/
|
||||
void SetThreadID(const quint32 &threadID);
|
||||
void SetThreadID(const uint32_t &threadID);
|
||||
|
||||
/**
|
||||
* @brief 获取运行状态
|
||||
* @return RunStatus: 运行状态枚举
|
||||
*/
|
||||
RunStatus GetRunStatus();
|
||||
|
||||
/**
|
||||
* @brief 获取线程运行频率
|
||||
* @return const double&:线程运行频率
|
||||
*/
|
||||
const double &GetRunFrequecy();
|
||||
|
||||
/**
|
||||
* @brief 设置线程运行频率
|
||||
* @param eRunFrequecy: double类型,线程运行频率
|
||||
*/
|
||||
void SetRunFrequecy(const double &dRunFrequecy);
|
||||
|
||||
/**
|
||||
* @brief 获取线程运行优先级
|
||||
* @return const UINT32&:运行优先级,0~99,99最高
|
||||
*/
|
||||
const uint32_t &GetRunPriority();
|
||||
|
||||
/**
|
||||
* @brief 设置线程运行优先级
|
||||
* @param uRunPriority: UINT32类型,运行优先级,0~99,99最高
|
||||
*/
|
||||
void SetRunPriority(const uint32_t &uRunPriority);
|
||||
|
||||
/**
|
||||
* @brief 设置线程CPU亲和性掩码
|
||||
* @return const UINT32&: CPU亲和性掩码,按位表示某CPU核是否使用,从低到高,0表示不使用,1表示使用。
|
||||
* 例如:0x00000003表示使用0,1号CPU
|
||||
*/
|
||||
const uint32_t &GetCPUAffinity();
|
||||
|
||||
/**
|
||||
* @brief 获取线程CPU亲和性掩码
|
||||
* @param uCPUAffinity: UINT32类型,CPU亲和性掩码,按位表示某CPU核是否使用,从低到高,0表示不使用,1表示使用。
|
||||
* 例如:0x00000003表示使用0,1号CPU
|
||||
*/
|
||||
void SetCPUAffinity(const uint32_t &uCPUAffinity);
|
||||
|
||||
/**
|
||||
* @brief 向线程添加周期性函数
|
||||
* @param fun:XNCallBack函数包装器类型,需要提交的函数的包装
|
||||
* @param freq:FreqLevel类型,提交的函数运行频率组
|
||||
* @param pos:UINT32类型,提交的函数运行节点号
|
||||
* @param priorty:UINT32类型,提交的函数运行优先级,99~0,优先级数值越大,优先级越高
|
||||
* @details 根据运行频率组和节点号向调度线程任务表中添加周期性函数
|
||||
*/
|
||||
void AddFunction(XNCallBack fun, FreqLevel freq, uint32_t pos, uint32_t priorty);
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief 控制线程开始
|
||||
* @return true: 线程启动成功
|
||||
@ -120,61 +174,6 @@ public:
|
||||
*/
|
||||
void Stop(bool force = false);
|
||||
|
||||
/**
|
||||
* @brief 获取运行状态
|
||||
* @return RunStatus: 运行状态枚举
|
||||
*/
|
||||
RunStatus GetRunStatus();
|
||||
|
||||
/**
|
||||
* @brief 获取线程运行频率族
|
||||
* @return const FreqLevel&:线程运行频率族
|
||||
*/
|
||||
const FreqLevel &GetRunFrequecy();
|
||||
|
||||
/**
|
||||
* @brief 设置线程运行频率族
|
||||
* @param eRunFrequecy: FreqLevel枚举类,线程运行频率族
|
||||
*/
|
||||
void SetRunFrequecy(const FreqLevel &eRunFrequecy);
|
||||
|
||||
/**
|
||||
* @brief 获取线程运行优先级
|
||||
* @return const UINT32&:运行优先级,0~99,99最高
|
||||
*/
|
||||
const quint32 &GetRunPriority();
|
||||
|
||||
/**
|
||||
* @brief 设置线程运行优先级
|
||||
* @param uRunPriority: UINT32类型,运行优先级,0~99,99最高
|
||||
*/
|
||||
void SetRunPriority(const quint32 &uRunPriority);
|
||||
|
||||
/**
|
||||
* @brief 设置线程CPU亲和性掩码
|
||||
* @return const UINT32&: CPU亲和性掩码,按位表示某CPU核是否使用,从低到高,0表示不使用,1表示使用。
|
||||
* 例如:0x00000003表示使用0,1号CPU
|
||||
*/
|
||||
const quint32 &GetCPUAffinity();
|
||||
|
||||
/**
|
||||
* @brief 获取线程CPU亲和性掩码
|
||||
* @param uCPUAffinity: UINT32类型,CPU亲和性掩码,按位表示某CPU核是否使用,从低到高,0表示不使用,1表示使用。
|
||||
* 例如:0x00000003表示使用0,1号CPU
|
||||
*/
|
||||
void SetCPUAffinity(const quint32 &uCPUAffinity);
|
||||
|
||||
/**
|
||||
* @brief 向线程添加周期性函数
|
||||
* @param fun:XNCallBack函数包装器类型,需要提交的函数的包装
|
||||
* @param freq:FreqLevel类型,提交的函数运行频率组
|
||||
* @param pos:UINT32类型,提交的函数运行节点号
|
||||
* @param priorty:UINT32类型,提交的函数运行优先级,99~0,优先级数值越大,优先级越高
|
||||
* @details 根据运行频率组和节点号向调度线程任务表中添加周期性函数
|
||||
*/
|
||||
void AddFunction(XNCallBack fun, FreqLevel freq, quint32 pos, quint32 priorty);
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief 执行线程CPU亲和性设置
|
||||
* @return true: 设置线程CPU亲和性成功
|
||||
@ -189,8 +188,10 @@ private:
|
||||
*/
|
||||
static void *ThreadFunction(void *args);
|
||||
|
||||
/**
|
||||
* @brief 初始化周期性函数表
|
||||
*/
|
||||
void InitialFunPool();
|
||||
// /**
|
||||
// * @brief 初始化周期性函数表
|
||||
// */
|
||||
//void InitialFunPool();
|
||||
};
|
||||
|
||||
XNCLASS_PTR_DECLARE(XNThread)
|
@ -11,39 +11,40 @@
|
||||
#include "XNThreadManager.h"
|
||||
#include "XNThreadManager_p.h"
|
||||
#include "XNFramework.h"
|
||||
#include "XNTimeManager.h"
|
||||
#include "XNModelManager.h"
|
||||
|
||||
// 默认构造函数
|
||||
XNThreadManager::XNThreadManager(QObject *parent)
|
||||
: XNBaseFrameObject(*new XNThreadManagerPrivate(this), parent)
|
||||
XNThreadManager::XNThreadManager() : XNBaseFrameObject(new XNThreadManagerPrivate())
|
||||
{
|
||||
setUniqueId(3);
|
||||
setObjectName("XNThreadManager");
|
||||
SetUniqueId(3);
|
||||
SetObjectName("XNThreadManager");
|
||||
}
|
||||
|
||||
XNThreadManager::~XNThreadManager()
|
||||
{
|
||||
}
|
||||
|
||||
XNThreadManager::XNThreadManager(XNThreadManagerPrivate &dd, QObject *parent)
|
||||
: XNBaseFrameObject(dd, parent)
|
||||
XNThreadManager::XNThreadManager(PrivateType *p) : XNBaseFrameObject(p)
|
||||
{
|
||||
}
|
||||
|
||||
// 初始化函数
|
||||
void XNThreadManager::OnInitialize()
|
||||
bool XNThreadManager::Initialize()
|
||||
{
|
||||
Q_D(XNThreadManager);
|
||||
T_D();
|
||||
d->_eRunStatus = RunStatus::NotStart;
|
||||
d->threadList.clear();
|
||||
d->funList.clear();
|
||||
LOG_INFO("XNThreadManager Initialize Success!");
|
||||
d->_status = XNFrameObjectStatus::Initialized;
|
||||
emit Initialize();
|
||||
return true;
|
||||
}
|
||||
|
||||
// 开始控制
|
||||
void XNThreadManager::OnStart()
|
||||
void XNThreadManager::Start()
|
||||
{
|
||||
Q_D(XNThreadManager);
|
||||
T_D();
|
||||
// 如果当前状态是未开始状态
|
||||
if (d->_eRunStatus == RunStatus::NotStart) {
|
||||
// 状态切换为正在运行
|
||||
@ -52,9 +53,9 @@ void XNThreadManager::OnStart()
|
||||
}
|
||||
|
||||
// 停止控制
|
||||
void XNThreadManager::OnAbort()
|
||||
void XNThreadManager::Abort()
|
||||
{
|
||||
Q_D(XNThreadManager);
|
||||
T_D();
|
||||
// 如果当前状态不是停止状态
|
||||
if (d->_eRunStatus != RunStatus::Aborted) {
|
||||
// 状态切换为停止
|
||||
@ -63,9 +64,9 @@ void XNThreadManager::OnAbort()
|
||||
}
|
||||
|
||||
// 暂停控制
|
||||
void XNThreadManager::OnPause()
|
||||
void XNThreadManager::Pause()
|
||||
{
|
||||
Q_D(XNThreadManager);
|
||||
T_D();
|
||||
// 如果当前是正在运行状态
|
||||
if (d->_eRunStatus == RunStatus::Runing) {
|
||||
// 状态切换为暂停
|
||||
@ -74,9 +75,9 @@ void XNThreadManager::OnPause()
|
||||
}
|
||||
|
||||
// 继续控制
|
||||
void XNThreadManager::OnContinue()
|
||||
void XNThreadManager::Continue()
|
||||
{
|
||||
Q_D(XNThreadManager);
|
||||
T_D();
|
||||
// 如果当前是暂停状态
|
||||
if (d->_eRunStatus == RunStatus::Suspend) {
|
||||
//TODO 这里需要重新设置一下时间信息,不然启动后会加速运行至设定的时间
|
||||
@ -88,49 +89,46 @@ void XNThreadManager::OnContinue()
|
||||
// 获取当前运行状态
|
||||
RunStatus XNThreadManager::GetStatus()
|
||||
{
|
||||
Q_D(XNThreadManager);
|
||||
T_D();
|
||||
return d->_eRunStatus;
|
||||
}
|
||||
|
||||
// 添加周期性函数
|
||||
void XNThreadManager::OnRegisterFunction(quint32 id, XNCallBack fun, quint32 freqGroup,
|
||||
quint32 RunPos, quint32 RunPriorty)
|
||||
void XNThreadManager::RegisterFunction(uint32_t id, XNCallBack fun, uint32_t threadID,
|
||||
uint32_t freqGroup, uint32_t RunPos, uint32_t RunPriorty)
|
||||
{
|
||||
Q_D(XNThreadManager);
|
||||
T_D();
|
||||
// 如果周期性函数校验通过
|
||||
if (IsFunParamRight(id, freqGroup, RunPos)) {
|
||||
// 存储提交的函数
|
||||
funInfoPtr sFunInfo = funInfoPtr::create();
|
||||
funInfoPtr sFunInfo = std::make_shared<funInfo>();
|
||||
sFunInfo->fun = fun;
|
||||
sFunInfo->threadID = threadID;
|
||||
sFunInfo->freqGroup = freqGroup;
|
||||
sFunInfo->RunPos = RunPos;
|
||||
sFunInfo->RunPriority = RunPriorty;
|
||||
d->funList[id].push_back(sFunInfo);
|
||||
// 加入线程任务池
|
||||
auto threadPool = this->findChildren<XNThread *>();
|
||||
for (auto thread : threadPool) {
|
||||
if ((quint32)thread->GetRunFrequecy() == freqGroup) {
|
||||
thread->AddFunction(fun, (FreqLevel)freqGroup, RunPos, RunPriorty);
|
||||
break;
|
||||
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);
|
||||
}
|
||||
}
|
||||
LOG_INFO("Model [ %1] register periodic function success! Run node: %2-%3 Priority: %4", id,
|
||||
freqGroup, RunPos, RunPriorty);
|
||||
}
|
||||
}
|
||||
|
||||
// 注册函数校验
|
||||
bool XNThreadManager::IsFunParamRight(quint32 id, quint32 freqGroup, quint32 RunPos)
|
||||
bool XNThreadManager::IsFunParamRight(uint32_t id, uint32_t freqGroup, uint32_t RunPos)
|
||||
{
|
||||
quint32 ufreq = freqGroup;
|
||||
// 检查提交的函数是否符合规定
|
||||
if (ufreq < 0 || ufreq > 5) {
|
||||
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 > pow(2, freqGroup)) {
|
||||
} 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!",
|
||||
@ -141,115 +139,89 @@ bool XNThreadManager::IsFunParamRight(quint32 id, quint32 freqGroup, quint32 Run
|
||||
}
|
||||
|
||||
// 仿真运行前做最后处理
|
||||
void XNThreadManager::OnPrepareForExecute()
|
||||
bool XNThreadManager::PrepareForExecute()
|
||||
{
|
||||
Q_D(XNThreadManager);
|
||||
T_D();
|
||||
PERIOD_INFO pinfo;
|
||||
clock_gettime(CLOCK_MONOTONIC, &(pinfo.next_period));
|
||||
emit SetStartTime(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...");
|
||||
auto threadPool = this->findChildren<XNThread *>();
|
||||
for (auto &thread : threadPool) {
|
||||
bool bRet = thread->Initialize();
|
||||
for (auto &thread : d->threadList) {
|
||||
bool bRet = thread.second->Initialize();
|
||||
if (!bRet) {
|
||||
emit PrepareForExecuteFailed();
|
||||
return;
|
||||
LOG_ERROR("Thread [ %1 ] PrepareForExecute Failed!", thread.first);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
d->_status = XNFrameObjectStatus::Ready;
|
||||
// 通知模型管理器进行最后准备
|
||||
LOG_INFO("XNThreadManager is prepared!");
|
||||
emit PrepareForExecute();
|
||||
return true;
|
||||
}
|
||||
|
||||
// 添加线程
|
||||
void XNThreadManager::OnAddThreadPool(QString name, FreqLevel freq, quint32 priority,
|
||||
quint32 CPUAff, double RunInter)
|
||||
uint32_t XNThreadManager::AddThreadPool(std::string name, double freq, uint32_t priority,
|
||||
uint32_t CPUAff)
|
||||
{
|
||||
Q_D(XNThreadManager);
|
||||
T_D();
|
||||
// 创建线程对象
|
||||
XNThread *thread = new XNThread(this, name, freq, priority, CPUAff, RunInter);
|
||||
// 连接信号和槽
|
||||
//connect(this, &XNThreadManager::SetRunInter, thread, &XNThread::SetRunInter);
|
||||
connect(this, &XNThreadManager::SetStartTime, thread, &XNThread::OnSetStartTime);
|
||||
connect(this, &XNThreadManager::SimControl, thread, &XNThread::OnSimControl);
|
||||
XNThreadPtr thread = std::make_shared<XNThread>(name, freq, priority, CPUAff);
|
||||
thread->SetThreadID(AllocateThreadID());
|
||||
LOG_INFO("Add Thread Success, Frequency: %1 Hz, Interval: %2 ns.",
|
||||
d->dRunFreq / pow(2, (quint32)freq), RunInter);
|
||||
d->threadCount++;
|
||||
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::OnSimControl(quint32 objectId, SimControlCmd cmd)
|
||||
void XNThreadManager::SimControl(uint32_t objectId, SimControlCmd cmd)
|
||||
{
|
||||
T_D();
|
||||
if (objectId == 0) {
|
||||
switch (cmd) {
|
||||
case SimControlCmd::Start:
|
||||
OnStart();
|
||||
Start();
|
||||
break;
|
||||
case SimControlCmd::Abort:
|
||||
OnAbort();
|
||||
Abort();
|
||||
break;
|
||||
case SimControlCmd::Continue:
|
||||
OnContinue();
|
||||
Continue();
|
||||
break;
|
||||
case SimControlCmd::Suspend:
|
||||
OnPause();
|
||||
Pause();
|
||||
break;
|
||||
}
|
||||
}
|
||||
emit SimControl(objectId, cmd);
|
||||
for (auto &thread : d->threadList) {
|
||||
thread.second->SimControl(objectId, cmd);
|
||||
}
|
||||
|
||||
// 设置模型运行基频
|
||||
void XNThreadManager::OnSetBaseFreq(const double &dBaseFreq)
|
||||
{
|
||||
Q_D(XNThreadManager);
|
||||
d->dRunFreq = dBaseFreq;
|
||||
d->dRunInter = 1.0e9 / dBaseFreq;
|
||||
//emit SetRunInter(d->dRunInter);
|
||||
LOG_INFO("Set engine base run frequency to %1 Hz, interval: %2 ns.", d->dRunFreq, d->dRunInter);
|
||||
}
|
||||
|
||||
// 获得模型运行基频
|
||||
const double &XNThreadManager::GetBaseFreq()
|
||||
{
|
||||
Q_D(XNThreadManager);
|
||||
return d->dRunFreq;
|
||||
}
|
||||
|
||||
// 获得模型运行基础间隔
|
||||
const double &XNThreadManager::GetBaseInter()
|
||||
{
|
||||
Q_D(XNThreadManager);
|
||||
return d->dRunInter;
|
||||
}
|
||||
|
||||
// 通过运行间隔设置基频
|
||||
void XNThreadManager::SetBaseFreqByInter(const double &dBaseInter)
|
||||
{
|
||||
Q_D(XNThreadManager);
|
||||
d->dRunFreq = 1.0e9 / dBaseInter;
|
||||
d->dRunInter = dBaseInter;
|
||||
LOG_INFO("Set engine base run frequency to %1 Hz, interval: %2 ns.", d->dRunFreq, d->dRunInter);
|
||||
}
|
||||
|
||||
// 获取线程数量
|
||||
quint32 XNThreadManager::GetThreadCount()
|
||||
uint32_t XNThreadManager::GetThreadCount()
|
||||
{
|
||||
Q_D(XNThreadManager);
|
||||
return d->threadCount;
|
||||
T_D();
|
||||
return d->threadList.size();
|
||||
}
|
||||
|
||||
// 分配线程ID
|
||||
quint32 XNThreadManager::AllocateThreadID()
|
||||
uint32_t XNThreadManager::AllocateThreadID()
|
||||
{
|
||||
Q_D(XNThreadManager);
|
||||
T_D();
|
||||
//从5000到9999分配线程ID
|
||||
static quint32 threadID = 5000;
|
||||
while (d->threadIDMap.contains(threadID)) {
|
||||
static uint32_t threadID = 5000;
|
||||
while (d->threadList.find(threadID) != d->threadList.end()) {
|
||||
threadID++;
|
||||
}
|
||||
d->threadIDMap.insert(threadID);
|
||||
d->threadList[threadID] = nullptr;
|
||||
return threadID;
|
||||
}
|
||||
|
@ -11,7 +11,7 @@
|
||||
#pragma once
|
||||
#include "XNBaseFrameObject.h"
|
||||
|
||||
class XNThreadManagerPrivate;
|
||||
struct XNThreadManagerPrivate;
|
||||
|
||||
/**
|
||||
* @brief 线程管理器类
|
||||
@ -19,15 +19,14 @@ class XNThreadManagerPrivate;
|
||||
*/
|
||||
class XNThreadManager : public XNBaseFrameObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DECLARE_PRIVATE(XNThreadManager)
|
||||
Q_DISABLE_COPY(XNThreadManager)
|
||||
XN_METATYPE(XNThreadManager, XNBaseFrameObject)
|
||||
XN_DECLARE_PRIVATE(XNThreadManager)
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief 线程管理器类默认构造函数
|
||||
*/
|
||||
explicit XNThreadManager(QObject *parent = nullptr);
|
||||
XNThreadManager();
|
||||
|
||||
/**
|
||||
* @brief 线程管理器类析构函数
|
||||
@ -41,53 +40,32 @@ protected:
|
||||
* @param parent:QObject类型,父对象指针
|
||||
* @details 子类构造时调用此构造函数,传入子类的私有结构体指针
|
||||
*/
|
||||
XNThreadManager(XNThreadManagerPrivate &dd, QObject *parent = nullptr);
|
||||
XNThreadManager(PrivateType *p);
|
||||
|
||||
signals:
|
||||
/**
|
||||
* @brief 设置仿真开始时间信号
|
||||
* @param simTime: timespec结构体类型,用于线程纳秒睡眠计算的开始时间
|
||||
* @details 通过设置统一的开始时间,使个线程能同步执行
|
||||
*/
|
||||
void SetStartTime(const timespec &simTime);
|
||||
|
||||
/**
|
||||
* @brief 设置线程运行间隔信号
|
||||
* @param dRunInter: double类型,线程运行间隔,单位纳秒
|
||||
*/
|
||||
void SetRunInter(const double &dRunInter);
|
||||
|
||||
/**
|
||||
* @brief 仿真控制信号
|
||||
* @param objectId: 对象ID
|
||||
* @param cmd: 仿真控制命令
|
||||
*/
|
||||
void SimControl(quint32 objectId, SimControlCmd cmd);
|
||||
|
||||
public slots:
|
||||
public:
|
||||
/**
|
||||
* @brief 开始控制
|
||||
* @details 控制线程管理器开始运行接口
|
||||
*/
|
||||
void OnStart();
|
||||
void Start();
|
||||
|
||||
/**
|
||||
* @brief 停止控制
|
||||
* @details 控制线程管理器停止运行接口
|
||||
*/
|
||||
void OnAbort();
|
||||
void Abort();
|
||||
|
||||
/**
|
||||
* @brief 暂停控制
|
||||
* @details 控制线程管理器暂停运行接口
|
||||
*/
|
||||
void OnPause();
|
||||
void Pause();
|
||||
|
||||
/**
|
||||
* @brief 继续控制
|
||||
* @details 控制线程管理器继续运行接口
|
||||
*/
|
||||
void OnContinue();
|
||||
void Continue();
|
||||
|
||||
/**
|
||||
* @brief 初始化线程管理器
|
||||
@ -95,29 +73,21 @@ public slots:
|
||||
* @return false: 初始化失败
|
||||
* @details 线程管理器的初始化接口函数
|
||||
*/
|
||||
virtual void OnInitialize() override;
|
||||
virtual bool Initialize() override;
|
||||
|
||||
/**
|
||||
* @brief 仿真运行前最后处理
|
||||
* @note 线程管理器在所有线程开始执行前的准备工作
|
||||
*/
|
||||
virtual void OnPrepareForExecute() override;
|
||||
virtual bool PrepareForExecute() override;
|
||||
|
||||
/**
|
||||
* @brief 仿真控制
|
||||
* @param objectId: 对象ID
|
||||
* @param cmd: 仿真控制命令
|
||||
*/
|
||||
void OnSimControl(quint32 objectId, SimControlCmd cmd);
|
||||
void SimControl(uint32_t objectId, SimControlCmd cmd);
|
||||
|
||||
/**
|
||||
* @brief 设置仿真系统运行基频
|
||||
* @param dBaseFreq: double类型,频率值,单位Hz
|
||||
* @details 仿真系统所有线程以此基频的 1 或 1/2 或 1/4 或 1/8 或 1/16 或 1/32 倍运行
|
||||
*/
|
||||
void OnSetBaseFreq(const double &dBaseFreq);
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief 获取运行状态
|
||||
* @return RunStatus: 枚举类,线程运行状态
|
||||
@ -125,50 +95,29 @@ public:
|
||||
*/
|
||||
RunStatus GetStatus();
|
||||
|
||||
/**
|
||||
* @brief 获得仿真系统运行基频
|
||||
* @return const double&: 频率值,单位Hz
|
||||
*/
|
||||
const double &GetBaseFreq();
|
||||
|
||||
/**
|
||||
* @brief 获得仿真系统运行基础间隔
|
||||
* @return const double&: 运行周期值,单位纳秒
|
||||
* @details 模型基础运行间隔由基频计算获得
|
||||
*/
|
||||
const double &GetBaseInter();
|
||||
|
||||
/**
|
||||
* @brief 通过运行间隔设置基频
|
||||
* @param dBaseInter:double类型,运行周期值,单位纳秒
|
||||
* @details 使用运行间隔计算得到基频并设置
|
||||
*/
|
||||
void SetBaseFreqByInter(const double &dBaseInter);
|
||||
|
||||
/**
|
||||
* @brief 获取线程数量
|
||||
* @return quint32: 线程数量
|
||||
*/
|
||||
quint32 GetThreadCount();
|
||||
uint32_t GetThreadCount();
|
||||
|
||||
public slots:
|
||||
/**
|
||||
* @brief 添加一个线程
|
||||
* @param name: XNString类型,线程名称
|
||||
* @param freq: FreqLevel枚举类型,线程运行频率组
|
||||
* @param freq: double类型,线程运行频率,单位Hz
|
||||
* @param priority: UINT32类型,线程运行优先级,99~0,优先级数值越大,优先级越高
|
||||
* @param CPUAff: UINT32类型,线程的CPU亲和性掩码,按位表示某CPU核是否使用,从低到高,0表示不使用,1表示使用。
|
||||
* 例如:0x00000003表示使用0,1号CPU
|
||||
* @param RunInter: double类型,线程的运行周期,单位纳秒
|
||||
* @details 按照设置的参数创建线程
|
||||
*/
|
||||
virtual void OnAddThreadPool(QString name, FreqLevel freq, quint32 priority, quint32 CPUAff,
|
||||
double RunInter);
|
||||
virtual uint32_t AddThreadPool(std::string name, double freq, uint32_t priority,
|
||||
uint32_t 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,优先级数值越大,优先级越高
|
||||
@ -176,8 +125,8 @@ public slots:
|
||||
* @return false: 添加失败
|
||||
* @details 根据运行频率组和节点号向对应的线程中添加周期性函数
|
||||
*/
|
||||
void OnRegisterFunction(quint32 id, XNCallBack fun, quint32 freqGroup, quint32 RunPos,
|
||||
quint32 RunPriorty);
|
||||
void RegisterFunction(uint32_t id, XNCallBack fun, uint32_t threadID, uint32_t freqGroup,
|
||||
uint32_t RunPos, uint32_t RunPriorty);
|
||||
|
||||
private:
|
||||
/**
|
||||
@ -187,7 +136,7 @@ private:
|
||||
* @return true:提交的函数频率与节点号符合规则
|
||||
* @return false:提交的函数频率与节点号不符合规则
|
||||
*/
|
||||
bool IsFunParamRight(quint32 ModelID, quint32 freqGroup, quint32 RunPos);
|
||||
bool IsFunParamRight(uint32_t ModelID, uint32_t freqGroup, uint32_t RunPos);
|
||||
|
||||
quint32 AllocateThreadID();
|
||||
uint32_t AllocateThreadID();
|
||||
};
|
@ -20,55 +20,46 @@ struct funInfo {
|
||||
* @brief 周期性函数包装器
|
||||
*/
|
||||
XNCallBack fun;
|
||||
/**
|
||||
* @brief 线程ID
|
||||
*/
|
||||
uint32_t threadID;
|
||||
/**
|
||||
* @brief 运行频率组
|
||||
*/
|
||||
quint32 freqGroup;
|
||||
uint32_t freqGroup;
|
||||
/**
|
||||
* @brief 运行节点
|
||||
*/
|
||||
quint32 RunPos;
|
||||
uint32_t RunPos;
|
||||
/**
|
||||
* @brief 运行优先级
|
||||
*/
|
||||
quint32 RunPriority;
|
||||
uint32_t RunPriority;
|
||||
};
|
||||
/**
|
||||
* @brief 声明周期性函数存储结构体的智能指针
|
||||
*/
|
||||
using funInfoPtr = QSharedPointer<funInfo>;
|
||||
using funInfoPtr = std::shared_ptr<funInfo>;
|
||||
|
||||
/**
|
||||
* @brief 线程管理器类私有结构体
|
||||
*/
|
||||
class XNThreadManagerPrivate : public XNBaseFrameObjectPrivate
|
||||
{
|
||||
public:
|
||||
XNThreadManagerPrivate(XNThreadManager *q) : XNBaseFrameObjectPrivate(q) {}
|
||||
Q_DECLARE_PUBLIC(XNThreadManager)
|
||||
private:
|
||||
struct XNThreadManagerPrivate : public XNBaseFrameObjectPrivate {
|
||||
/**
|
||||
* @brief 所有线程运行状态
|
||||
*/
|
||||
RunStatus _eRunStatus;
|
||||
/**
|
||||
* @brief 线程列表
|
||||
*/
|
||||
std::map<uint32_t, XNThreadPtr> threadList;
|
||||
/**
|
||||
* @brief 周期性函数存储列表
|
||||
*/
|
||||
QMap<quint32, std::vector<funInfoPtr> > funList;
|
||||
/**
|
||||
* @brief 基础运行频率
|
||||
*/
|
||||
double dRunFreq = BASE_RUN_FREQ;
|
||||
/**
|
||||
* @brief 基础运行间隔
|
||||
*/
|
||||
double dRunInter = BASE_RUN_INTER;
|
||||
std::map<uint32_t, std::vector<funInfoPtr> > funList;
|
||||
/**
|
||||
* @brief 线程ID
|
||||
*/
|
||||
QSet<quint32> threadIDMap;
|
||||
/**
|
||||
* @brief 线程数量
|
||||
*/
|
||||
quint32 threadCount = 0;
|
||||
std::set<uint32_t> threadIDMap;
|
||||
};
|
||||
|
76
XNCore/XNThread_p.h
Normal file
76
XNCore/XNThread_p.h
Normal file
@ -0,0 +1,76 @@
|
||||
#pragma once
|
||||
#include "XNObject_p.h"
|
||||
/**
|
||||
* @brief 线程类私有结构体
|
||||
*/
|
||||
struct XNThreadPrivate : public XNObjectPrivate {
|
||||
/**
|
||||
* @brief 框架对象
|
||||
*/
|
||||
XNFrameworkPtr _framework;
|
||||
/**
|
||||
* @brief 线程运行优先级
|
||||
*/
|
||||
uint32_t _uPriority = 0;
|
||||
/**
|
||||
* @brief 线程CPU亲和性掩码
|
||||
* @details 按位表示某CPU核是否使用,从低到高,0表示不使用,1表示使用。例如:0x00000003表示使用0,1号CPU
|
||||
*/
|
||||
uint32_t _uAffinity = 0;
|
||||
/**
|
||||
* @brief 线程运行频率
|
||||
*/
|
||||
double _setFreq = BASE_RUN_FREQ;
|
||||
/**
|
||||
* @brief 线程调度任务表
|
||||
*/
|
||||
std::vector<std::map<uint32_t, std::vector<XNCallBack> > > _funVec;
|
||||
/**
|
||||
* @brief pthread线程调度参数
|
||||
*/
|
||||
sched_param param;
|
||||
/**
|
||||
* @brief pthread线程属性
|
||||
*/
|
||||
pthread_attr_t attr;
|
||||
/**
|
||||
* @brief pthread线程
|
||||
*/
|
||||
pthread_t thread;
|
||||
/**
|
||||
* @brief 线程睡眠时间控制
|
||||
*/
|
||||
PERIOD_INFO pinfo;
|
||||
/**
|
||||
* @brief 线程控制锁
|
||||
*/
|
||||
pthread_mutex_t _mtx = PTHREAD_MUTEX_INITIALIZER;
|
||||
/**
|
||||
* @brief 线程控制条件变量
|
||||
*/
|
||||
pthread_cond_t _cond = PTHREAD_COND_INITIALIZER;
|
||||
/**
|
||||
* @brief 线程运行状态
|
||||
*/
|
||||
RunStatus _eRunStatus = RunStatus::NotStart;
|
||||
/**
|
||||
* @brief 线程执行进度
|
||||
*/
|
||||
uint32_t _RunPosition = 0;
|
||||
/**
|
||||
* @brief 线程执行计数
|
||||
*/
|
||||
int count = 0;
|
||||
/**
|
||||
* @brief 线程执行时间统计
|
||||
*/
|
||||
timespec _lastRunTime;
|
||||
/**
|
||||
* @brief 线程运行状态主题写入器
|
||||
*/
|
||||
FAST_DDS_MACRO::DataWriter *writer;
|
||||
/**
|
||||
* @brief 线程ID
|
||||
*/
|
||||
uint32_t _threadID = 0;
|
||||
};
|
@ -12,47 +12,46 @@
|
||||
#include "XNTimeManager_p.h"
|
||||
#include "XNDDSManager.h"
|
||||
#include "XNThreadManager.h"
|
||||
#include "XNFramework.h"
|
||||
#include "XNIDL/XNSimStatusPubSubTypes.hpp"
|
||||
|
||||
typedef std::shared_ptr<XNThread> XNThreadPtr;
|
||||
|
||||
XNTimeManager::XNTimeManager(QObject *parent)
|
||||
: XNBaseFrameObject(*new XNTimeManagerPrivate(this), parent)
|
||||
XNTimeManager::XNTimeManager() : XNBaseFrameObject(new XNTimeManagerPrivate())
|
||||
{
|
||||
setUniqueId(2);
|
||||
setObjectName("XNTimeManager");
|
||||
SetUniqueId(2);
|
||||
SetObjectName("XNTimeManager");
|
||||
}
|
||||
|
||||
XNTimeManager::~XNTimeManager()
|
||||
{
|
||||
}
|
||||
|
||||
XNTimeManager::XNTimeManager(XNTimeManagerPrivate &dd, QObject *parent)
|
||||
: XNBaseFrameObject(dd, parent)
|
||||
XNTimeManager::XNTimeManager(PrivateType *p) : XNBaseFrameObject(p)
|
||||
{
|
||||
}
|
||||
|
||||
QDateTime XNTimeManager::GetSimTime()
|
||||
std::chrono::system_clock::time_point XNTimeManager::GetSimTime()
|
||||
{
|
||||
Q_D(XNTimeManager);
|
||||
T_D();
|
||||
pthread_mutex_lock(&(d->_mtx));
|
||||
QDateTime sSimTime = d->_SimTime;
|
||||
auto simTime = d->_SimTime;
|
||||
pthread_mutex_unlock(&(d->_mtx));
|
||||
return sSimTime;
|
||||
return simTime;
|
||||
}
|
||||
|
||||
void XNTimeManager::OnSetStartTime(const timespec &simTime)
|
||||
void XNTimeManager::SetStartTime(const timespec &simTime)
|
||||
{
|
||||
Q_D(XNTimeManager);
|
||||
d->_SimStartTime = QDateTime::fromSecsSinceEpoch(simTime.tv_sec);
|
||||
d->_SimStartTime = d->_SimStartTime.addMSecs(simTime.tv_nsec / 1000000.0);
|
||||
//d->_TimeManagerThread->OnSetStartTime(simTime);
|
||||
//d->_TimeManagerThread->Initialize();
|
||||
T_D();
|
||||
// 将timespec转换为chrono::system_clock::time_point
|
||||
auto duration =
|
||||
std::chrono::seconds(simTime.tv_sec) + std::chrono::nanoseconds(simTime.tv_nsec);
|
||||
d->_SimStartTime = std::chrono::system_clock::time_point(duration);
|
||||
}
|
||||
|
||||
void XNTimeManager::OnStart()
|
||||
void XNTimeManager::Start()
|
||||
{
|
||||
Q_D(XNTimeManager);
|
||||
T_D();
|
||||
if (d->_eRunStatus == RunStatus::NotStart) {
|
||||
LOG_INFO("XNSim Start!");
|
||||
d->_eRunStatus = RunStatus::Runing;
|
||||
@ -61,9 +60,9 @@ void XNTimeManager::OnStart()
|
||||
}
|
||||
}
|
||||
|
||||
void XNTimeManager::OnAbort()
|
||||
void XNTimeManager::Abort()
|
||||
{
|
||||
Q_D(XNTimeManager);
|
||||
T_D();
|
||||
if (d->_eRunStatus != RunStatus::Aborted) {
|
||||
LOG_INFO("XNSim Abort!");
|
||||
d->_eRunStatus = RunStatus::Aborted;
|
||||
@ -72,9 +71,9 @@ void XNTimeManager::OnAbort()
|
||||
}
|
||||
}
|
||||
|
||||
void XNTimeManager::OnPause()
|
||||
void XNTimeManager::Pause()
|
||||
{
|
||||
Q_D(XNTimeManager);
|
||||
T_D();
|
||||
if (d->_eRunStatus == RunStatus::Runing) {
|
||||
LOG_INFO("XNSim Pause!");
|
||||
d->_eRunStatus = RunStatus::Suspend;
|
||||
@ -83,9 +82,9 @@ void XNTimeManager::OnPause()
|
||||
}
|
||||
}
|
||||
|
||||
void XNTimeManager::OnContinue()
|
||||
void XNTimeManager::Continue()
|
||||
{
|
||||
Q_D(XNTimeManager);
|
||||
T_D();
|
||||
if (d->_eRunStatus == RunStatus::Suspend) {
|
||||
LOG_INFO("XNSim Continue!");
|
||||
d->_eRunStatus = RunStatus::Runing;
|
||||
@ -96,34 +95,33 @@ void XNTimeManager::OnContinue()
|
||||
|
||||
RunStatus XNTimeManager::GetStatus()
|
||||
{
|
||||
Q_D(XNTimeManager);
|
||||
T_D();
|
||||
return d->_eRunStatus;
|
||||
}
|
||||
|
||||
void XNTimeManager::OnSimControl(quint32 objectId, SimControlCmd cmd)
|
||||
void XNTimeManager::SimControl(uint32_t objectId, SimControlCmd cmd)
|
||||
{
|
||||
if (objectId == 0) {
|
||||
switch (cmd) {
|
||||
case SimControlCmd::Start:
|
||||
OnStart();
|
||||
Start();
|
||||
break;
|
||||
case SimControlCmd::Abort:
|
||||
OnAbort();
|
||||
Abort();
|
||||
break;
|
||||
case SimControlCmd::Continue:
|
||||
OnContinue();
|
||||
Continue();
|
||||
break;
|
||||
case SimControlCmd::Suspend:
|
||||
OnPause();
|
||||
Pause();
|
||||
break;
|
||||
}
|
||||
}
|
||||
emit SimControl(objectId, cmd);
|
||||
}
|
||||
|
||||
void XNTimeManager::OnInitialize()
|
||||
bool XNTimeManager::Initialize()
|
||||
{
|
||||
Q_D(XNTimeManager);
|
||||
T_D();
|
||||
// 初始化锁
|
||||
pthread_mutex_init(&(d->_mtx), NULL);
|
||||
|
||||
@ -150,23 +148,23 @@ void XNTimeManager::OnInitialize()
|
||||
|
||||
LOG_INFO("XNTimeManager Initialize Success!");
|
||||
d->_status = XNFrameObjectStatus::Initialized;
|
||||
emit Initialize();
|
||||
return true;
|
||||
}
|
||||
|
||||
void XNTimeManager::OnPrepareForExecute()
|
||||
bool XNTimeManager::PrepareForExecute()
|
||||
{
|
||||
Q_D(XNTimeManager);
|
||||
T_D();
|
||||
d->_status = XNFrameObjectStatus::Ready;
|
||||
LOG_INFO("XNTimeManager is prepared!");
|
||||
emit PrepareForExecute();
|
||||
return true;
|
||||
}
|
||||
|
||||
void XNTimeManager::StepExecute()
|
||||
{
|
||||
Q_D(XNTimeManager);
|
||||
T_D();
|
||||
// TODO 提交事件
|
||||
// 时间推进
|
||||
pthread_mutex_lock(&(d->_mtx));
|
||||
d->_SimTime = d->_SimTime.addMSecs(BASE_RUN_INTER * 1.0E6);
|
||||
d->_SimTime += std::chrono::microseconds(static_cast<int64_t>(BASE_RUN_INTER * 1.0E6));
|
||||
pthread_mutex_unlock(&(d->_mtx));
|
||||
}
|
||||
|
@ -10,9 +10,9 @@
|
||||
*/
|
||||
#pragma once
|
||||
#include "XNBaseFrameObject.h"
|
||||
#include <QDateTime>
|
||||
#include <chrono>
|
||||
|
||||
class XNTimeManagerPrivate;
|
||||
struct XNTimeManagerPrivate;
|
||||
|
||||
/**
|
||||
* @brief 时间管理器类
|
||||
@ -20,16 +20,14 @@ class XNTimeManagerPrivate;
|
||||
*/
|
||||
class XNCORE_EXPORT XNTimeManager : public XNBaseFrameObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY(XNTimeManager);
|
||||
Q_DECLARE_PRIVATE(XNTimeManager);
|
||||
XN_METATYPE(XNTimeManager, XNBaseFrameObject)
|
||||
XN_DECLARE_PRIVATE(XNTimeManager)
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief 构造函数
|
||||
* @param parent: 父对象
|
||||
*/
|
||||
explicit XNTimeManager(QObject *parent = nullptr);
|
||||
XNTimeManager();
|
||||
|
||||
/**
|
||||
* @brief 析构函数
|
||||
@ -39,63 +37,46 @@ public:
|
||||
protected:
|
||||
/**
|
||||
* @brief 构造函数
|
||||
* @param dd: 私有数据成员
|
||||
* @param parent: 父对象
|
||||
* @param p: 私有数据成员
|
||||
*/
|
||||
XNTimeManager(XNTimeManagerPrivate &dd, QObject *parent = nullptr);
|
||||
XNTimeManager(PrivateType *p);
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief 获取当前仿真时间
|
||||
* @return QDateTime: 当前仿真时间
|
||||
* @return std::chrono::system_clock::time_point: 当前仿真时间
|
||||
*/
|
||||
QDateTime GetSimTime();
|
||||
XNTimePoint GetSimTime();
|
||||
|
||||
signals:
|
||||
/**
|
||||
* @brief 设置仿真开始时间信号
|
||||
* @param simTime: timespec结构体类型,用于线程纳秒睡眠计算的开始时间
|
||||
* @details 通过设置统一的开始时间,使个线程能同步执行
|
||||
*/
|
||||
void SetStartTime(const timespec &simTime);
|
||||
|
||||
/**
|
||||
* @brief 仿真控制信号
|
||||
* @param objectId: 对象ID
|
||||
* @param cmd: 仿真控制命令
|
||||
*/
|
||||
void SimControl(quint32 objectId, SimControlCmd cmd);
|
||||
|
||||
public slots:
|
||||
/**
|
||||
* @brief 设置仿真开始时间
|
||||
* @param simTime: timespec类型,仿真开始时间
|
||||
*/
|
||||
void OnSetStartTime(const timespec &simTime);
|
||||
void SetStartTime(const timespec &simTime);
|
||||
|
||||
/**
|
||||
* @brief 开始控制
|
||||
* @details 控制时间管理器线程开始运行接口
|
||||
*/
|
||||
void OnStart();
|
||||
void Start();
|
||||
|
||||
/**
|
||||
* @brief 停止控制
|
||||
* @details 控制时间管理器线程停止运行接口
|
||||
*/
|
||||
void OnAbort();
|
||||
void Abort();
|
||||
|
||||
/**
|
||||
* @brief 暂停控制
|
||||
* @details 控制时间管理器线程暂停运行接口
|
||||
*/
|
||||
void OnPause();
|
||||
void Pause();
|
||||
|
||||
/**
|
||||
* @brief 继续控制
|
||||
* @details 控制时间管理器线程继续运行接口
|
||||
*/
|
||||
void OnContinue();
|
||||
void Continue();
|
||||
|
||||
/**
|
||||
* @brief 初始化时间管理器
|
||||
@ -103,22 +84,21 @@ public slots:
|
||||
* @return false: 初始化失败
|
||||
* @details 时间管理器的初始化接口函数
|
||||
*/
|
||||
virtual void OnInitialize() override;
|
||||
virtual bool Initialize() override;
|
||||
|
||||
/**
|
||||
* @brief 仿真运行前最后处理
|
||||
* @note 时间管理器在开始执行前的准备工作
|
||||
*/
|
||||
virtual void OnPrepareForExecute() override;
|
||||
virtual bool PrepareForExecute() override;
|
||||
|
||||
/**
|
||||
* @brief 仿真控制
|
||||
* @param objectId: 对象ID
|
||||
* @param cmd: 仿真控制命令
|
||||
*/
|
||||
void OnSimControl(quint32 objectId, SimControlCmd cmd);
|
||||
void SimControl(uint32_t objectId, SimControlCmd cmd);
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief 获取运行状态
|
||||
* @return RunStatus: 枚举类,时间管理器线程运行状态
|
||||
|
@ -11,21 +11,12 @@
|
||||
#pragma once
|
||||
#include "XNBaseFrameObject_p.h"
|
||||
#include "XNThread.h"
|
||||
#include <chrono>
|
||||
|
||||
/**
|
||||
* @brief 时间管理器类私有结构体
|
||||
*/
|
||||
class XNTimeManagerPrivate : public XNBaseFrameObjectPrivate
|
||||
{
|
||||
public:
|
||||
Q_DECLARE_PUBLIC(XNTimeManager)
|
||||
|
||||
explicit XNTimeManagerPrivate(XNTimeManager *q) : XNBaseFrameObjectPrivate(q)
|
||||
{
|
||||
_eRunStatus = RunStatus::NotStart;
|
||||
}
|
||||
|
||||
private:
|
||||
struct XNTimeManagerPrivate : public XNBaseFrameObjectPrivate {
|
||||
/*
|
||||
* @brief 仿真运行状态
|
||||
*/
|
||||
@ -33,11 +24,11 @@ private:
|
||||
/**
|
||||
* @brief 仿真开始时间
|
||||
*/
|
||||
QDateTime _SimStartTime;
|
||||
std::chrono::system_clock::time_point _SimStartTime;
|
||||
/**
|
||||
* @brief 当前仿真时间
|
||||
*/
|
||||
QDateTime _SimTime;
|
||||
std::chrono::system_clock::time_point _SimTime;
|
||||
/**
|
||||
* @brief 时间管理器线程智能指针
|
||||
*/
|
||||
|
72
XNModels/XNGroundHandling/.vscode/settings.json
vendored
72
XNModels/XNGroundHandling/.vscode/settings.json
vendored
@ -1,6 +1,76 @@
|
||||
{
|
||||
"files.associations": {
|
||||
"*.cpp": "cpp",
|
||||
"qobject": "cpp"
|
||||
"qobject": "cpp",
|
||||
"cctype": "cpp",
|
||||
"clocale": "cpp",
|
||||
"cmath": "cpp",
|
||||
"csignal": "cpp",
|
||||
"cstdarg": "cpp",
|
||||
"cstddef": "cpp",
|
||||
"cstdio": "cpp",
|
||||
"cstdlib": "cpp",
|
||||
"cstring": "cpp",
|
||||
"ctime": "cpp",
|
||||
"cwchar": "cpp",
|
||||
"cwctype": "cpp",
|
||||
"any": "cpp",
|
||||
"array": "cpp",
|
||||
"atomic": "cpp",
|
||||
"bit": "cpp",
|
||||
"*.tcc": "cpp",
|
||||
"bitset": "cpp",
|
||||
"chrono": "cpp",
|
||||
"codecvt": "cpp",
|
||||
"compare": "cpp",
|
||||
"complex": "cpp",
|
||||
"concepts": "cpp",
|
||||
"condition_variable": "cpp",
|
||||
"cstdint": "cpp",
|
||||
"deque": "cpp",
|
||||
"list": "cpp",
|
||||
"map": "cpp",
|
||||
"set": "cpp",
|
||||
"unordered_map": "cpp",
|
||||
"unordered_set": "cpp",
|
||||
"vector": "cpp",
|
||||
"exception": "cpp",
|
||||
"algorithm": "cpp",
|
||||
"functional": "cpp",
|
||||
"iterator": "cpp",
|
||||
"memory": "cpp",
|
||||
"memory_resource": "cpp",
|
||||
"numeric": "cpp",
|
||||
"optional": "cpp",
|
||||
"random": "cpp",
|
||||
"ratio": "cpp",
|
||||
"regex": "cpp",
|
||||
"string": "cpp",
|
||||
"string_view": "cpp",
|
||||
"system_error": "cpp",
|
||||
"tuple": "cpp",
|
||||
"type_traits": "cpp",
|
||||
"utility": "cpp",
|
||||
"future": "cpp",
|
||||
"initializer_list": "cpp",
|
||||
"iomanip": "cpp",
|
||||
"iosfwd": "cpp",
|
||||
"iostream": "cpp",
|
||||
"istream": "cpp",
|
||||
"limits": "cpp",
|
||||
"mutex": "cpp",
|
||||
"new": "cpp",
|
||||
"ostream": "cpp",
|
||||
"ranges": "cpp",
|
||||
"span": "cpp",
|
||||
"sstream": "cpp",
|
||||
"stdexcept": "cpp",
|
||||
"stop_token": "cpp",
|
||||
"streambuf": "cpp",
|
||||
"thread": "cpp",
|
||||
"cinttypes": "cpp",
|
||||
"typeindex": "cpp",
|
||||
"typeinfo": "cpp",
|
||||
"variant": "cpp"
|
||||
}
|
||||
}
|
@ -137,6 +137,16 @@ void XNGroundHandling::StepUpdate()
|
||||
OnOutput();
|
||||
}
|
||||
|
||||
// template <class T1, class T2>
|
||||
// void CopyInputData(T1 *model_input, const T2 &dds_input)
|
||||
// {
|
||||
// Q_D(XNGroundHandling);
|
||||
// QMutexLocker locker(&d->_mutex);
|
||||
// if (dds_input.l_04_i_gdcomac_frz_l1()) {
|
||||
// model_input->l_04_i_gdcomac_frz_l1 = dds_input.l_04_i_gdcomac_frz_l1().value();
|
||||
// }
|
||||
// }
|
||||
|
||||
void XNGroundHandling::OnInput(const XNSim::ATA04::GroundHandling_input &input)
|
||||
{
|
||||
Q_D(XNGroundHandling);
|
||||
|
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
#include "XNGroundHandling_global.h"
|
||||
#include <XNCore/XNModelObject.h>
|
||||
#include "../XNGroundHandlingInterface/XNGroundHandlingPubSubTypes.hpp"
|
||||
#include "../XNGroundHandlingInterface/XNGroundHandlingInterface.hpp"
|
||||
|
||||
class XNGroundHandlingPrivate;
|
||||
|
||||
|
@ -3794,20 +3794,30 @@ public:
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief This function sets a value in member groundhandling_model_heartbeat
|
||||
* @param _groundhandling_model_heartbeat New value for member groundhandling_model_heartbeat
|
||||
* @brief This function copies the value in member groundhandling_model_heartbeat
|
||||
* @param _groundhandling_model_heartbeat New value to be copied in member groundhandling_model_heartbeat
|
||||
*/
|
||||
eProsima_user_DllExport void groundhandling_model_heartbeat(
|
||||
int32_t _groundhandling_model_heartbeat)
|
||||
const eprosima::fastcdr::optional<int32_t>& _groundhandling_model_heartbeat)
|
||||
{
|
||||
m_groundhandling_model_heartbeat = _groundhandling_model_heartbeat;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief This function returns the value of member groundhandling_model_heartbeat
|
||||
* @return Value of member groundhandling_model_heartbeat
|
||||
* @brief This function moves the value in member groundhandling_model_heartbeat
|
||||
* @param _groundhandling_model_heartbeat New value to be moved in member groundhandling_model_heartbeat
|
||||
*/
|
||||
eProsima_user_DllExport int32_t groundhandling_model_heartbeat() const
|
||||
eProsima_user_DllExport void groundhandling_model_heartbeat(
|
||||
eprosima::fastcdr::optional<int32_t>&& _groundhandling_model_heartbeat)
|
||||
{
|
||||
m_groundhandling_model_heartbeat = std::move(_groundhandling_model_heartbeat);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief This function returns a constant reference to member groundhandling_model_heartbeat
|
||||
* @return Constant reference to member groundhandling_model_heartbeat
|
||||
*/
|
||||
eProsima_user_DllExport const eprosima::fastcdr::optional<int32_t>& groundhandling_model_heartbeat() const
|
||||
{
|
||||
return m_groundhandling_model_heartbeat;
|
||||
}
|
||||
@ -3816,7 +3826,7 @@ public:
|
||||
* @brief This function returns a reference to member groundhandling_model_heartbeat
|
||||
* @return Reference to member groundhandling_model_heartbeat
|
||||
*/
|
||||
eProsima_user_DllExport int32_t& groundhandling_model_heartbeat()
|
||||
eProsima_user_DllExport eprosima::fastcdr::optional<int32_t>& groundhandling_model_heartbeat()
|
||||
{
|
||||
return m_groundhandling_model_heartbeat;
|
||||
}
|
||||
@ -3825,7 +3835,7 @@ public:
|
||||
|
||||
private:
|
||||
|
||||
int32_t m_groundhandling_model_heartbeat{0};
|
||||
eprosima::fastcdr::optional<int32_t> m_groundhandling_model_heartbeat;
|
||||
|
||||
};
|
||||
|
||||
|
@ -84,7 +84,7 @@ module XNSim
|
||||
};
|
||||
struct GroundHandling_heartbeat
|
||||
{
|
||||
long groundhandling_model_heartbeat;
|
||||
@optional long groundhandling_model_heartbeat;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -30,7 +30,7 @@ constexpr uint32_t XNSim_ATA04_GroundHandling_input_max_key_cdr_typesize {0UL};
|
||||
constexpr uint32_t XNSim_ATA04_GroundHandling_output_max_cdr_typesize {1328UL};
|
||||
constexpr uint32_t XNSim_ATA04_GroundHandling_output_max_key_cdr_typesize {0UL};
|
||||
|
||||
constexpr uint32_t XNSim_ATA04_GroundHandling_heartbeat_max_cdr_typesize {8UL};
|
||||
constexpr uint32_t XNSim_ATA04_GroundHandling_heartbeat_max_cdr_typesize {12UL};
|
||||
constexpr uint32_t XNSim_ATA04_GroundHandling_heartbeat_max_key_cdr_typesize {0UL};
|
||||
|
||||
|
||||
|
@ -1229,7 +1229,10 @@ void serialize_key(
|
||||
|
||||
static_cast<void>(scdr);
|
||||
static_cast<void>(data);
|
||||
scdr << data.groundhandling_model_heartbeat();
|
||||
if (data.groundhandling_model_heartbeat().has_value())
|
||||
{
|
||||
scdr << data.groundhandling_model_heartbeat().value();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -4,8 +4,7 @@ namespace XNSim
|
||||
{
|
||||
namespace ATA04
|
||||
{
|
||||
GroundHandling_input_Interface::GroundHandling_input_Interface(QObject *parent)
|
||||
: XNDDSInterface(parent)
|
||||
GroundHandling_input_Interface::GroundHandling_input_Interface()
|
||||
{
|
||||
MAP_GET_DATA_FUNC(l_04_i_gdcomac_frz_l1);
|
||||
MAP_GET_DATA_FUNC(l_04_i_gdcomac_chocks_l1);
|
||||
@ -55,12 +54,10 @@ namespace ATA04
|
||||
void GroundHandling_input_Interface::inputDataListener(
|
||||
const XNSim::ATA04::GroundHandling_input &input)
|
||||
{
|
||||
QMutexLocker locker(&mutex);
|
||||
this->data = input;
|
||||
}
|
||||
|
||||
GroundHandling_output_Interface::GroundHandling_output_Interface(QObject *parent)
|
||||
: XNDDSInterface(parent)
|
||||
GroundHandling_output_Interface::GroundHandling_output_Interface()
|
||||
{
|
||||
MAP_GET_DATA_FUNC(l_04_o_gdcomac_frz_l1);
|
||||
MAP_GET_DATA_FUNC(l_04_o_gdcomac_ac_on_ground_l1);
|
||||
@ -106,22 +103,12 @@ namespace ATA04
|
||||
void GroundHandling_output_Interface::outputDataListener(
|
||||
const XNSim::ATA04::GroundHandling_output &output)
|
||||
{
|
||||
QMutexLocker locker(&mutex);
|
||||
this->data = output;
|
||||
}
|
||||
|
||||
GroundHandling_heartbeat_Interface::GroundHandling_heartbeat_Interface(QObject *parent)
|
||||
: XNDDSInterface(parent)
|
||||
GroundHandling_heartbeat_Interface::GroundHandling_heartbeat_Interface()
|
||||
{
|
||||
getDataFunction["groundhandling_model_heartbeat"] = [this]() {
|
||||
return QString::number(data.groundhandling_model_heartbeat());
|
||||
};
|
||||
getByteArrayFunction.push_back([this]() {
|
||||
QByteArray tmp;
|
||||
tmp.fromRawData(reinterpret_cast<const char *>(&data.groundhandling_model_heartbeat()),
|
||||
sizeof(data.groundhandling_model_heartbeat()));
|
||||
return tmp;
|
||||
});
|
||||
MAP_GET_DATA_FUNC(groundhandling_model_heartbeat);
|
||||
}
|
||||
|
||||
GroundHandling_heartbeat_Interface::~GroundHandling_heartbeat_Interface()
|
||||
@ -131,7 +118,6 @@ namespace ATA04
|
||||
void GroundHandling_heartbeat_Interface::heartbeatListener(
|
||||
const XNSim::ATA04::GroundHandling_heartbeat &heartbeat)
|
||||
{
|
||||
QMutexLocker locker(&mutex);
|
||||
this->data = heartbeat;
|
||||
}
|
||||
} // namespace ATA04
|
||||
|
@ -8,11 +8,101 @@ namespace ATA04
|
||||
{
|
||||
class GroundHandling_input_Interface : public XNDDSInterface
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit GroundHandling_input_Interface(QObject *parent);
|
||||
explicit GroundHandling_input_Interface();
|
||||
virtual ~GroundHandling_input_Interface();
|
||||
void inputDataListener(const XNSim::ATA04::GroundHandling_input &input);
|
||||
template <typename T>
|
||||
void getData(T *model_data)
|
||||
{
|
||||
if (model_data == nullptr)
|
||||
return;
|
||||
ASSIGN_VALUE_GET(l_04_i_gdcomac_frz_l1);
|
||||
ASSIGN_VALUE_GET(l_04_i_gdcomac_chocks_l1);
|
||||
ASSIGN_VALUE_GET(l_04_i_gdcomac_alt_agl_f8);
|
||||
ASSIGN_VALUE_GET(l_04_i_gdcomac_frzflt_l1);
|
||||
ASSIGN_VALUE_GET(l_04_i_gdcomac_p_f8);
|
||||
ASSIGN_VALUE_GET(l_04_i_gdcomac_q_f8);
|
||||
ASSIGN_VALUE_GET(l_04_i_gdcomac_r_f8);
|
||||
ASSIGN_VALUE_GET(l_04_i_gdcomac_ug_f8);
|
||||
ASSIGN_VALUE_GET(l_04_i_gdcomac_vg_f8);
|
||||
ASSIGN_VALUE_GET(l_04_i_gdcomac_wg_f8);
|
||||
ASSIGN_VALUE_GET(l_04_i_gdcomac_blcg_f8);
|
||||
ASSIGN_VALUE_GET(l_04_i_gdcomac_bscg_f8);
|
||||
ASSIGN_VALUE_GET(l_04_i_gdcomac_wlcg_f8);
|
||||
ASSIGN_VALUE_GET(l_04_i_gdcomac_pb_active_l1);
|
||||
ASSIGN_VALUE_GET(l_04_i_gdcomac_brake_torq_f8);
|
||||
ASSIGN_VALUE_GET(l_04_i_gdcomac_gear_f8);
|
||||
ASSIGN_VALUE_GET(l_04_i_gdcomac_gsteer_f8);
|
||||
ASSIGN_VALUE_GET(l_04_i_gdcomac_tire_pres_f8);
|
||||
ASSIGN_VALUE_GET(l_04_i_gdcomac_onjax_l1);
|
||||
ASSIGN_VALUE_GET(l_04_i_gdcomac_contdep_f8);
|
||||
ASSIGN_VALUE_GET(l_04_i_gdcomac_thetag_f8);
|
||||
ASSIGN_VALUE_GET(l_04_i_gdcomac_phig_f8);
|
||||
ASSIGN_VALUE_GET(l_04_i_gdcomac_rwyrgh_i2);
|
||||
ASSIGN_VALUE_GET(l_04_i_gdcomac_rwyhdg_f8);
|
||||
ASSIGN_VALUE_GET(l_04_i_gdcomac_reset_braketemp_l1);
|
||||
ASSIGN_VALUE_GET(l_04_i_gdcomac_reset_tirepress_l1);
|
||||
ASSIGN_VALUE_GET(l_04_i_gdcomac_temp_c_f8);
|
||||
ASSIGN_VALUE_GET(l_04_i_gdcomac_brake_temp_f8);
|
||||
ASSIGN_VALUE_GET(l_04_i_gdcomac_tire_tburst_l1);
|
||||
ASSIGN_VALUE_GET(l_04_i_gdcomac_tire_tflat_l1);
|
||||
ASSIGN_VALUE_GET(l_04_i_gdcomac_brk_reset_tpres_l1);
|
||||
ASSIGN_VALUE_GET(l_04_i_gdcomac_rcon_ci_f8);
|
||||
ASSIGN_VALUE_GET(l_04_i_gdcomac_pb_towforce_f8);
|
||||
ASSIGN_VALUE_GET(l_04_i_gdcomac_gsteer_state_i4);
|
||||
ASSIGN_VALUE_GET(l_04_i_gdcomac_trim_active_l1);
|
||||
ASSIGN_VALUE_GET(l_04_i_gdcomac_phi_deg_f8);
|
||||
ASSIGN_VALUE_GET(l_04_i_gdcomac_theta_deg_f8);
|
||||
ASSIGN_VALUE_GET(l_04_i_gdcomac_psi_deg_f8);
|
||||
ASSIGN_VALUE_GET(l_04_i_gdcomac_resetint_l1);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void setData(T *model_data)
|
||||
{
|
||||
if (model_data == nullptr)
|
||||
return;
|
||||
ASSIGN_VALUE_SET(l_04_i_gdcomac_frz_l1);
|
||||
ASSIGN_VALUE_SET(l_04_i_gdcomac_chocks_l1);
|
||||
ASSIGN_VALUE_SET(l_04_i_gdcomac_alt_agl_f8);
|
||||
ASSIGN_VALUE_SET(l_04_i_gdcomac_frzflt_l1);
|
||||
ASSIGN_VALUE_SET(l_04_i_gdcomac_p_f8);
|
||||
ASSIGN_VALUE_SET(l_04_i_gdcomac_q_f8);
|
||||
ASSIGN_VALUE_SET(l_04_i_gdcomac_r_f8);
|
||||
ASSIGN_VALUE_SET(l_04_i_gdcomac_ug_f8);
|
||||
ASSIGN_VALUE_SET(l_04_i_gdcomac_vg_f8);
|
||||
ASSIGN_VALUE_SET(l_04_i_gdcomac_wg_f8);
|
||||
ASSIGN_VALUE_SET(l_04_i_gdcomac_blcg_f8);
|
||||
ASSIGN_VALUE_SET(l_04_i_gdcomac_bscg_f8);
|
||||
ASSIGN_VALUE_SET(l_04_i_gdcomac_wlcg_f8);
|
||||
ASSIGN_VALUE_SET(l_04_i_gdcomac_pb_active_l1);
|
||||
ASSIGN_VALUE_SET(l_04_i_gdcomac_brake_torq_f8);
|
||||
ASSIGN_VALUE_SET(l_04_i_gdcomac_gear_f8);
|
||||
ASSIGN_VALUE_SET(l_04_i_gdcomac_gsteer_f8);
|
||||
ASSIGN_VALUE_SET(l_04_i_gdcomac_tire_pres_f8);
|
||||
ASSIGN_VALUE_SET(l_04_i_gdcomac_onjax_l1);
|
||||
ASSIGN_VALUE_SET(l_04_i_gdcomac_contdep_f8);
|
||||
ASSIGN_VALUE_SET(l_04_i_gdcomac_thetag_f8);
|
||||
ASSIGN_VALUE_SET(l_04_i_gdcomac_phig_f8);
|
||||
ASSIGN_VALUE_SET(l_04_i_gdcomac_rwyrgh_i2);
|
||||
ASSIGN_VALUE_SET(l_04_i_gdcomac_rwyhdg_f8);
|
||||
ASSIGN_VALUE_SET(l_04_i_gdcomac_reset_braketemp_l1);
|
||||
ASSIGN_VALUE_SET(l_04_i_gdcomac_reset_tirepress_l1);
|
||||
ASSIGN_VALUE_SET(l_04_i_gdcomac_temp_c_f8);
|
||||
ASSIGN_VALUE_SET(l_04_i_gdcomac_brake_temp_f8);
|
||||
ASSIGN_VALUE_SET(l_04_i_gdcomac_tire_tburst_l1);
|
||||
ASSIGN_VALUE_SET(l_04_i_gdcomac_tire_tflat_l1);
|
||||
ASSIGN_VALUE_SET(l_04_i_gdcomac_brk_reset_tpres_l1);
|
||||
ASSIGN_VALUE_SET(l_04_i_gdcomac_rcon_ci_f8);
|
||||
ASSIGN_VALUE_SET(l_04_i_gdcomac_pb_towforce_f8);
|
||||
ASSIGN_VALUE_SET(l_04_i_gdcomac_gsteer_state_i4);
|
||||
ASSIGN_VALUE_SET(l_04_i_gdcomac_trim_active_l1);
|
||||
ASSIGN_VALUE_SET(l_04_i_gdcomac_phi_deg_f8);
|
||||
ASSIGN_VALUE_SET(l_04_i_gdcomac_theta_deg_f8);
|
||||
ASSIGN_VALUE_SET(l_04_i_gdcomac_psi_deg_f8);
|
||||
ASSIGN_VALUE_SET(l_04_i_gdcomac_resetint_l1);
|
||||
}
|
||||
|
||||
private:
|
||||
XNSim::ATA04::GroundHandling_input data;
|
||||
@ -20,9 +110,8 @@ namespace ATA04
|
||||
|
||||
class GroundHandling_output_Interface : public XNDDSInterface
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit GroundHandling_output_Interface(QObject *parent);
|
||||
explicit GroundHandling_output_Interface();
|
||||
virtual ~GroundHandling_output_Interface();
|
||||
void outputDataListener(const XNSim::ATA04::GroundHandling_output &output);
|
||||
|
||||
@ -32,9 +121,8 @@ namespace ATA04
|
||||
|
||||
class GroundHandling_heartbeat_Interface : public XNDDSInterface
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit GroundHandling_heartbeat_Interface(QObject *parent);
|
||||
explicit GroundHandling_heartbeat_Interface();
|
||||
virtual ~GroundHandling_heartbeat_Interface();
|
||||
void heartbeatListener(const XNSim::ATA04::GroundHandling_heartbeat &heartbeat);
|
||||
|
||||
|
@ -4330,7 +4330,7 @@ void register_GroundHandling_heartbeat_type_identifier(
|
||||
return;
|
||||
}
|
||||
StructMemberFlag member_flags_groundhandling_model_heartbeat = TypeObjectUtils::build_struct_member_flag(eprosima::fastdds::dds::xtypes::TryConstructFailAction::DISCARD,
|
||||
false, false, false, false);
|
||||
true, false, false, false);
|
||||
MemberId member_id_groundhandling_model_heartbeat = 0x00000000;
|
||||
bool common_groundhandling_model_heartbeat_ec {false};
|
||||
CommonStructMember common_groundhandling_model_heartbeat {TypeObjectUtils::build_common_struct_member(member_id_groundhandling_model_heartbeat, member_flags_groundhandling_model_heartbeat, TypeObjectUtils::retrieve_complete_type_identifier(type_ids_groundhandling_model_heartbeat, common_groundhandling_model_heartbeat_ec))};
|
||||
@ -4342,6 +4342,19 @@ void register_GroundHandling_heartbeat_type_identifier(
|
||||
MemberName name_groundhandling_model_heartbeat = "groundhandling_model_heartbeat";
|
||||
eprosima::fastcdr::optional<AppliedBuiltinMemberAnnotations> member_ann_builtin_groundhandling_model_heartbeat;
|
||||
ann_custom_GroundHandling_heartbeat.reset();
|
||||
AppliedAnnotationSeq tmp_ann_custom_groundhandling_model_heartbeat;
|
||||
eprosima::fastcdr::optional<std::string> unit_groundhandling_model_heartbeat;
|
||||
eprosima::fastcdr::optional<AnnotationParameterValue> min_groundhandling_model_heartbeat;
|
||||
eprosima::fastcdr::optional<AnnotationParameterValue> max_groundhandling_model_heartbeat;
|
||||
eprosima::fastcdr::optional<std::string> hash_id_groundhandling_model_heartbeat;
|
||||
if (unit_groundhandling_model_heartbeat.has_value() || min_groundhandling_model_heartbeat.has_value() || max_groundhandling_model_heartbeat.has_value() || hash_id_groundhandling_model_heartbeat.has_value())
|
||||
{
|
||||
member_ann_builtin_groundhandling_model_heartbeat = TypeObjectUtils::build_applied_builtin_member_annotations(unit_groundhandling_model_heartbeat, min_groundhandling_model_heartbeat, max_groundhandling_model_heartbeat, hash_id_groundhandling_model_heartbeat);
|
||||
}
|
||||
if (!tmp_ann_custom_groundhandling_model_heartbeat.empty())
|
||||
{
|
||||
ann_custom_GroundHandling_heartbeat = tmp_ann_custom_groundhandling_model_heartbeat;
|
||||
}
|
||||
CompleteMemberDetail detail_groundhandling_model_heartbeat = TypeObjectUtils::build_complete_member_detail(name_groundhandling_model_heartbeat, member_ann_builtin_groundhandling_model_heartbeat, ann_custom_GroundHandling_heartbeat);
|
||||
CompleteStructMember member_groundhandling_model_heartbeat = TypeObjectUtils::build_complete_struct_member(common_groundhandling_model_heartbeat, detail_groundhandling_model_heartbeat);
|
||||
TypeObjectUtils::add_complete_struct_member(member_seq_GroundHandling_heartbeat, member_groundhandling_model_heartbeat);
|
||||
|
Loading…
x
Reference in New Issue
Block a user