libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
LibXR::Topic Class Reference

主题(Topic)管理类 / Topic management class More...

#include <message.hpp>

Collaboration diagram for LibXR::Topic:
[legend]

Data Structures

struct  ASyncBlock
 异步订阅块,继承自 SuberBlock Asynchronous subscription block, inheriting from SuberBlock More...
 
class  ASyncSubscriber
 异步订阅者类,用于订阅异步数据 Asynchronous subscriber class for subscribing to asynchronous data More...
 
struct  Block
 存储主题运行状态和静态配置。Stores topic runtime state and static configuration. More...
 
class  Callback
 
struct  CallbackBlock
 回调订阅块,继承自 SuberBlock Callback subscription block, inheriting from SuberBlock More...
 
class  Domain
 主题域(Domain)管理器,用于组织多个主题。Domain manager for organizing multiple topics. More...
 
struct  Message
 带时间戳的类型化消息。Timestamped typed message. More...
 
struct  MessageView
 带时间戳的类型化消息视图。Timestamped typed message view. More...
 
struct  QueueBlock
 队列订阅块,继承自 SuberBlock Queue subscription block, inheriting from SuberBlock More...
 
class  QueuedSubscriber
 
class  Server
 服务器类,负责解析数据并将其分发到相应的主题 Server class responsible for parsing data and distributing it to corresponding topics More...
 
struct  SuberBlock
 订阅者信息存储结构。Structure storing subscriber information. More...
 
struct  SyncBlock
 同步订阅者存储结构。Structure storing synchronous subscriber data. More...
 
class  SyncSubscriber
 同步订阅者类,允许同步方式接收数据。Synchronous subscriber class allowing data reception in a synchronous manner. More...
 

Public Types

enum class  SuberType : uint8_t { SYNC , ASYNC , QUEUE , CALLBACK }
 订阅者类型。Subscriber type. More...
 
enum class  ASyncSubscriberState : uint32_t { IDLE = 0 , WAITING = 1 , DATA_READY = UINT32_MAX }
 
typedef RBTree< uint32_t >::Node< Block > * TopicHandle
 主题句柄,指向存储数据的红黑树节点。Handle pointing to a red-black tree node storing data.
 

Public Member Functions

void RegisterCallback (Callback &cb)
 注册回调函数 Registers a callback function
 
 Topic ()
 默认构造函数,创建一个空的 Topic 实例 Default constructor, creates an empty Topic instance
 
 Topic (const char *name, uint32_t max_length, Domain *domain=nullptr, bool multi_publisher=false, bool cache=false, bool check_length=false)
 构造函数,使用指定名称、最大长度、域及其他选项初始化主题 Constructor to initialize a topic with the specified name, maximum length, domain, and options
 
 Topic (TopicHandle topic)
 通过句柄构造主题 Constructs a topic from a topic handle
 
void EnableCache ()
 启用主题的缓存功能 Enables caching for the topic
 
template<typename Data >
void Publish (Data &data)
 发布数据 Publishes data
 
template<typename Data >
void Publish (Data &data, MicrosecondTimestamp timestamp)
 
void Publish (void *addr, uint32_t size)
 以原始地址和大小发布数据 Publishes data using raw address and size
 
void Publish (void *addr, uint32_t size, MicrosecondTimestamp timestamp)
 
template<typename Data >
void PublishFromCallback (Data &data, bool in_isr)
 在回调函数中发布数据 Publishes data in a callback
 
template<typename Data >
void PublishFromCallback (Data &data, MicrosecondTimestamp timestamp, bool in_isr)
 
void PublishFromCallback (void *addr, uint32_t size, bool in_isr)
 在回调函数中以原始地址和大小发布数据 Publishes data using raw address and size in a callback
 
void PublishFromCallback (void *addr, uint32_t size, MicrosecondTimestamp timestamp, bool in_isr)
 
template<typename Data >
ErrorCode DumpData (PackedData< Data > &data)
 转储数据到 PackedData Dumps data into PackedData format
 
template<SizeLimitMode Mode = SizeLimitMode::MORE>
ErrorCode DumpData (RawData data)
 转储数据到原始缓冲区。Dumps data into a raw buffer.
 
template<SizeLimitMode Mode = SizeLimitMode::MORE>
ErrorCode DumpData (RawData data, MicrosecondTimestamp &timestamp)
 
template<typename Data >
requires (!std::same_as<std::remove_cv_t<Data>, RawData>)
ErrorCode DumpData (Data &data)
 转储数据到普通数据结构 Dumps data into a normal data structure
 
template<typename Data >
requires (!std::same_as<std::remove_cv_t<Data>, RawData>)
ErrorCode DumpData (Data &data, MicrosecondTimestamp &timestamp)
 
MicrosecondTimestamp GetTimestamp () const
 
 operator TopicHandle ()
 Topic 转换为 TopicHandle Converts Topic to TopicHandle
 
uint32_t GetKey () const
 获取主题的键值 Gets the key value of the topic
 

Static Public Member Functions

static void Lock (TopicHandle topic)
 锁定主题,防止其被多个订阅者同时访问。Lock the topic to prevent it from being accessed by multiple subscribers at the same time.
 
static void Unlock (TopicHandle topic)
 解锁主题。Unlock the topic.
 
static void LockFromCallback (TopicHandle topic)
 从回调中锁定主题,防止其被多个订阅者同时访问。Lock the topic from a callback to prevent it from being accessed by multiple subscribers at the same time.
 
static void UnlockFromCallback (TopicHandle topic)
 从回调中解锁主题。Unlock the topic from a callback.
 
static MicrosecondTimestamp NowTimestamp ()
 生成默认发布时刻。Create the default publish timestamp.
 
template<typename Data >
static Topic CreateTopic (const char *name, Domain *domain=nullptr, bool multi_publisher=false, bool cache=false, bool check_length=false)
 创建一个新的主题 Creates a new topic
 
static TopicHandle Find (const char *name, Domain *domain=nullptr)
 在指定域中查找主题 Finds a topic in the specified domain
 
template<typename Data >
static TopicHandle FindOrCreate (const char *name, Domain *domain=nullptr, bool multi_publisher=false, bool cache=false, bool check_length=false)
 在指定域中查找或创建主题 Finds or creates a topic in the specified domain
 
static void PackData (uint32_t topic_name_crc32, RawData buffer, MicrosecondTimestamp timestamp, ConstRawData data)
 打包数据
 
static TopicHandle WaitTopic (const char *name, uint32_t timeout=UINT32_MAX, Domain *domain=nullptr)
 等待主题的创建并返回其句柄 Waits for a topic to be created and returns its handle
 

Private Types

enum class  LockState : uint32_t { UNLOCKED = 0 , LOCKED = 1 , USE_MUTEX = UINT32_MAX }
 

Private Member Functions

template<SizeLimitMode Mode = SizeLimitMode::MORE>
ErrorCode DumpPayload (RawData buffer, MicrosecondTimestamp &timestamp)
 
template<SizeLimitMode Mode = SizeLimitMode::MORE>
ErrorCode DumpPacket (RawData buffer)
 
void PublishRaw (void *addr, uint32_t size, MicrosecondTimestamp timestamp, bool from_callback, bool in_isr)
 

Static Private Member Functions

static void EnsureDomainRegistry ()
 
static DomainEnsureDefaultDomain ()
 
template<typename Data >
static void CheckSubscriberDataSize (Topic topic)
 校验订阅者数据类型和主题最大长度是否兼容。 Checks whether subscriber data type is compatible with topic max length.
 
template<typename Data >
static RawData NewSubscriberBuffer ()
 为异步订阅者分配长期存在的接收缓冲区。 Allocates a long-lived receive buffer for an async subscriber.
 
static void CheckPublishSize (TopicHandle topic, uint32_t size)
 
static RawData StorePublishedData (TopicHandle topic, void *addr, uint32_t size, MicrosecondTimestamp timestamp)
 
static void DispatchSubscriber (SuberBlock &block, MicrosecondTimestamp timestamp, RawData data, bool from_callback, bool in_isr)
 
static void DispatchSubscribers (TopicHandle topic, MicrosecondTimestamp timestamp, RawData data, bool from_callback, bool in_isr)
 

Private Attributes

TopicHandle block_ = nullptr
 主题句柄,指向当前主题的内存块 Topic handle pointing to the memory block of the current topic
 

Static Private Attributes

static RBTree< uint32_t > * domain_ = nullptr
 主题域的红黑树结构,存储不同的主题 Red-Black Tree structure for storing different topics in the domain
 
static Domaindef_domain_ = nullptr
 默认的主题域,所有未指定域的主题都会归入此域 Default domain where all topics without a specified domain are assigned
 

Detailed Description

主题(Topic)管理类 / Topic management class

该类提供了基于发布-订阅模式的主题管理,支持同步、异步、队列和回调订阅者,以及数据的缓存和校验机制。 This class provides topic management based on the publish-subscribe model, supporting synchronous, asynchronous, queue-based, and callback subscribers, as well as data caching and validation mechanisms.

Note
Topic、subscriber 和 server 应在初始化阶段创建,并在应用运行期间长期存在。 该消息系统遵循 libxr 的静态生命周期模型: 初始化阶段允许分配,发布、回调和解析热路径不应产生动态分配。 Topics, subscribers, and servers are expected to be created during initialization and kept alive for the application lifetime. The message system follows libxr's static lifetime model: allocation is allowed during initialization, while publish, callback, and parser hot paths should not allocate dynamically.

Definition at line 60 of file message.hpp.

Member Typedef Documentation

◆ TopicHandle

主题句柄,指向存储数据的红黑树节点。Handle pointing to a red-black tree node storing data.

Definition at line 135 of file message.hpp.

Member Enumeration Documentation

◆ ASyncSubscriberState

enum class LibXR::Topic::ASyncSubscriberState : uint32_t
strong

Definition at line 163 of file subscriber.hpp.

164{
165 IDLE = 0,
166 WAITING = 1,
167 DATA_READY = UINT32_MAX
168};

◆ LockState

enum class LibXR::Topic::LockState : uint32_t
strongprivate

Definition at line 62 of file message.hpp.

63 {
64 UNLOCKED = 0,
65 LOCKED = 1,
66 USE_MUTEX = UINT32_MAX,
67 };

◆ SuberType

enum class LibXR::Topic::SuberType : uint8_t
strong

订阅者类型。Subscriber type.

Enumerator
SYNC 

同步订阅者。Synchronous subscriber.

ASYNC 

异步订阅者。Asynchronous subscriber.

QUEUE 

队列订阅者。Queued subscriber.

CALLBACK 

回调订阅者。Callback subscriber.

Definition at line 11 of file subscriber.hpp.

12{
13 SYNC,
14 ASYNC,
15 QUEUE,
16 CALLBACK,
17};
@ SYNC
同步订阅者。Synchronous subscriber.
@ ASYNC
异步订阅者。Asynchronous subscriber.
@ QUEUE
队列订阅者。Queued subscriber.
@ CALLBACK
回调订阅者。Callback subscriber.

Constructor & Destructor Documentation

◆ Topic() [1/3]

Topic::Topic ( )

默认构造函数,创建一个空的 Topic 实例 Default constructor, creates an empty Topic instance

Definition at line 132 of file topic.cpp.

132{}

◆ Topic() [2/3]

Topic::Topic ( const char * name,
uint32_t max_length,
Domain * domain = nullptr,
bool multi_publisher = false,
bool cache = false,
bool check_length = false )

构造函数,使用指定名称、最大长度、域及其他选项初始化主题 Constructor to initialize a topic with the specified name, maximum length, domain, and options

Parameters
name主题名称 Topic name
max_length数据的最大长度 Maximum length of data
domain主题所属的域(默认为 nullptr)Domain to which the topic belongs (default: nullptr)
multi_publisher是否允许多个订阅者(默认为 false)Whether to allow multiple subscribers (default: false)
cache是否启用缓存(默认为 false)Whether to enable caching (default: false)
check_length是否检查数据长度(默认为 false)Whether to check data length (default: false)
Note
包含初始化期动态内存分配,主题应长期存在。 Contains initialization-time dynamic allocation; topics are expected to be long-lived.
未启用缓存时,Topic 只保留最近一次发布数据的地址;调用者必须保证该地址在 DumpData() 前仍然有效。多发布者主题使用 mutex,不支持 PublishFromCallback()。 Without cache, Topic keeps only the last published address; the caller must keep it valid until DumpData(). Multi-publisher topics use a mutex and do not support PublishFromCallback().

Definition at line 134 of file topic.cpp.

136{
137 ASSERT(name != nullptr);
138
139 if (domain == nullptr)
140 {
141 domain = EnsureDefaultDomain();
142 }
143
144 auto crc32 = CRC32::Calculate(name, strlen(name));
145
146 auto topic = domain->node_->data_.Search<Block>(crc32);
147
148 if (topic)
149 {
150 ASSERT(topic->data_.max_length == max_length);
151 ASSERT(topic->data_.check_length == check_length);
152
153 if (multi_publisher && !topic->data_.mutex)
154 {
155 ASSERT(false);
156 }
157
158 block_ = topic;
159 }
160 else
161 {
162 block_ = new RBTree<uint32_t>::Node<Block>;
163 block_->data_.max_length = max_length;
164 block_->data_.crc32 = crc32;
165 block_->data_.data.addr_ = nullptr;
166 block_->data_.timestamp = MicrosecondTimestamp();
167 block_->data_.cache = false;
168 block_->data_.check_length = check_length;
169
170 if (multi_publisher)
171 {
172 block_->data_.mutex = new Mutex();
173 block_->data_.busy.store(LockState::USE_MUTEX, std::memory_order_release);
174 }
175 else
176 {
177 block_->data_.mutex = nullptr;
178 block_->data_.busy.store(LockState::UNLOCKED, std::memory_order_release);
179 }
180
181 domain->node_->data_.Insert(*block_, crc32);
182 }
183
184 if (cache && !block_->data_.cache)
185 {
186 EnableCache();
187 }
188}
static uint32_t Calculate(const void *raw, size_t len)
计算数据的 CRC32 校验码 / Computes the CRC32 checksum for the given data
Definition crc.hpp:254
微秒时间戳 / Microsecond timestamp
互斥锁类,提供线程同步机制 (Mutex class providing thread synchronization mechanisms).
Definition mutex.hpp:18
红黑树的泛型数据节点,继承自 BaseNode (Generic data node for Red-Black Tree, inheriting from BaseNode).
Definition rbt.hpp:64
Data data_
存储的数据 (Stored data).
Definition rbt.hpp:99
void EnableCache()
启用主题的缓存功能 Enables caching for the topic
Definition topic.cpp:210
TopicHandle block_
主题句柄,指向当前主题的内存块 Topic handle pointing to the memory block of the current topic
Definition message.hpp:547

◆ Topic() [3/3]

Topic::Topic ( TopicHandle topic)

通过句柄构造主题 Constructs a topic from a topic handle

Parameters
topic主题句柄 Topic handle

Definition at line 190 of file topic.cpp.

190: block_(topic) {}

Member Function Documentation

◆ CheckPublishSize()

void Topic::CheckPublishSize ( TopicHandle topic,
uint32_t size )
staticprivate

Definition at line 15 of file publish.cpp.

16{
17 if (topic->data_.check_length)
18 {
19 ASSERT(size == topic->data_.max_length);
20 }
21 else
22 {
23 ASSERT(size <= topic->data_.max_length);
24 }
25}

◆ CheckSubscriberDataSize()

template<typename Data >
static void LibXR::Topic::CheckSubscriberDataSize ( Topic topic)
inlinestaticprivate

校验订阅者数据类型和主题最大长度是否兼容。 Checks whether subscriber data type is compatible with topic max length.

Definition at line 573 of file message.hpp.

574 {
575 CheckTopicPayload<Data>();
576 if (topic.block_->data_.check_length)
577 {
578 ASSERT(topic.block_->data_.max_length == sizeof(Data));
579 }
580 else
581 {
582 ASSERT(topic.block_->data_.max_length <= sizeof(Data));
583 }
584 }

◆ CreateTopic()

template<typename Data >
static Topic LibXR::Topic::CreateTopic ( const char * name,
Domain * domain = nullptr,
bool multi_publisher = false,
bool cache = false,
bool check_length = false )
inlinestatic

创建一个新的主题 Creates a new topic

Template Parameters
Data主题数据类型 Topic data type
Parameters
name主题名称 Topic name
domain主题所属的域(默认为 nullptr)Domain to which the topic belongs (default: nullptr)
multi_publisher是否允许多个订阅者(默认为 false)Whether to allow multiple subscribers (default: false)
cache是否启用缓存(默认为 false)Whether to enable caching (default: false)
check_length是否检查数据长度(默认为 false)Whether to check data length (default: false)
Returns
创建的 Topic 实例 The created Topic instance
Note
包含初始化期动态内存分配,主题应长期存在。 Contains initialization-time dynamic allocation; topics are expected to be long-lived.

Definition at line 303 of file message.hpp.

306 {
307 CheckTopicPayload<Data>();
308 return Topic(name, sizeof(Data), domain, multi_publisher, cache, check_length);
309 }
Topic()
默认构造函数,创建一个空的 Topic 实例 Default constructor, creates an empty Topic instance
Definition topic.cpp:132

◆ DispatchSubscriber()

void Topic::DispatchSubscriber ( SuberBlock & block,
MicrosecondTimestamp timestamp,
RawData data,
bool from_callback,
bool in_isr )
staticprivate

Definition at line 45 of file publish.cpp.

47{
48 switch (block.type)
49 {
50 case SuberType::SYNC:
51 {
52 auto sync = static_cast<SyncBlock*>(&block);
53 uint32_t expected = SyncBlock::WAITING;
54 auto wake_waiter = sync->wait_state.compare_exchange_strong(
55 expected, SyncBlock::WAIT_CLAIMED, std::memory_order_acq_rel,
56 std::memory_order_acquire);
57
58 if (!wake_waiter)
59 {
60 break;
61 }
62
63 LibXR::Memory::FastCopy(sync->buff.addr_, data.addr_, data.size_);
64 sync->timestamp = timestamp;
65
66 if (from_callback)
67 {
68 sync->sem.PostFromCallback(in_isr);
69 }
70 else
71 {
72 sync->sem.Post();
73 }
74 break;
75 }
77 {
78 auto async = static_cast<ASyncBlock*>(&block);
79 if (async->state.load(std::memory_order_acquire) == ASyncSubscriberState::WAITING)
80 {
81 LibXR::Memory::FastCopy(async->buff.addr_, data.addr_, data.size_);
82 async->timestamp = timestamp;
83 async->state.store(ASyncSubscriberState::DATA_READY, std::memory_order_release);
84 }
85 break;
86 }
88 {
89 auto queue_block = static_cast<QueueBlock*>(&block);
90 queue_block->fun(timestamp, data, *queue_block);
91 break;
92 }
94 {
95 auto cb_block = static_cast<CallbackBlock*>(&block);
96 cb_block->cb.Run(from_callback && in_isr, timestamp, data);
97 break;
98 }
99 }
100}
回调函数封装块,提供参数绑定与擦除调用入口 / Callback block with bound argument and erased invoke entry
Definition libxr_cb.hpp:41
static void FastCopy(void *dst, const void *src, size_t size)
快速内存拷贝 / Fast memory copy
Definition libxr_mem.cpp:5
size_t size_
数据字节数 / Data size in bytes
void * addr_
数据起始地址 / Data start address

◆ DispatchSubscribers()

void Topic::DispatchSubscribers ( TopicHandle topic,
MicrosecondTimestamp timestamp,
RawData data,
bool from_callback,
bool in_isr )
staticprivate

Definition at line 102 of file publish.cpp.

104{
105 topic->data_.subers.Foreach<SuberBlock>(
106 [=](SuberBlock& block)
107 {
108 DispatchSubscriber(block, timestamp, data, from_callback, in_isr);
109 return ErrorCode::OK;
110 });
111}
@ OK
操作成功 | Operation successful

◆ DumpData() [1/5]

template<typename Data >
requires (!std::same_as<std::remove_cv_t<Data>, RawData>)
ErrorCode LibXR::Topic::DumpData ( Data & data)
inline

转储数据到普通数据结构 Dumps data into a normal data structure

Note
允许目标类型只覆盖当前 payload 的前缀,例如把扩展 payload 转储到基础 payload 结构。若目标类型大于当前 payload,则返回 SIZE_ERR。 The destination type may cover only a prefix of the current payload, for example dumping an extended payload into a base payload structure. SIZE_ERR is returned if the destination type is larger than the current payload.
Template Parameters
Data数据类型 Data type
Parameters
data存储数据的变量 Variable to store the data

Definition at line 495 of file message.hpp.

496 {
497 MicrosecondTimestamp timestamp;
498 return DumpData(data, timestamp);
499 }
ErrorCode DumpData(PackedData< Data > &data)
转储数据到 PackedData Dumps data into PackedData format
Definition packet.hpp:67

◆ DumpData() [2/5]

template<typename Data >
requires (!std::same_as<std::remove_cv_t<Data>, RawData>)
ErrorCode LibXR::Topic::DumpData ( Data & data,
MicrosecondTimestamp & timestamp )
inline

Definition at line 503 of file message.hpp.

504 {
505 CheckTopicPayload<Data>();
506 return DumpPayload<SizeLimitMode::LESS>(RawData(data), timestamp);
507 }

◆ DumpData() [3/5]

template<typename Data >
ErrorCode LibXR::Topic::DumpData ( PackedData< Data > & data)

转储数据到 PackedData Dumps data into PackedData format

Template Parameters
Data数据类型 Data type
Parameters
data存储数据的 PackedData 结构 PackedData structure to store data

Definition at line 67 of file packet.hpp.

68{
69 CheckTopicPayload<Data>();
70 if (block_->data_.data.addr_ == nullptr)
71 {
72 return ErrorCode::EMPTY;
73 }
74
75 ASSERT(sizeof(Data) == block_->data_.data.size_);
76
77 return DumpPacket<SizeLimitMode::NONE>(RawData(data));
78}
@ EMPTY
为空 | Empty

◆ DumpData() [4/5]

template<SizeLimitMode Mode = SizeLimitMode::MORE>
ErrorCode LibXR::Topic::DumpData ( RawData data)
inline

转储数据到原始缓冲区。Dumps data into a raw buffer.

Definition at line 469 of file message.hpp.

470 {
471 MicrosecondTimestamp timestamp;
472 return DumpPayload<Mode>(data, timestamp);
473 }

◆ DumpData() [5/5]

template<SizeLimitMode Mode = SizeLimitMode::MORE>
ErrorCode LibXR::Topic::DumpData ( RawData data,
MicrosecondTimestamp & timestamp )
inline

Definition at line 476 of file message.hpp.

477 {
478 return DumpPayload<Mode>(data, timestamp);
479 }

◆ DumpPacket()

template<SizeLimitMode Mode = SizeLimitMode::MORE>
ErrorCode LibXR::Topic::DumpPacket ( RawData buffer)
inlineprivate

Definition at line 641 of file message.hpp.

642 {
643 if (block_->data_.data.addr_ == nullptr)
644 {
645 return ErrorCode::EMPTY;
646 }
647
648 Assert::SizeLimitCheck<Mode>(PACK_BASE_SIZE + block_->data_.data.size_, buffer.size_);
649 Lock(block_);
650 PackData(block_->data_.crc32, buffer, block_->data_.timestamp, block_->data_.data);
651 Unlock(block_);
652
653 return ErrorCode::OK;
654 }
static void SizeLimitCheck(size_t limit, size_t size)
在非调试模式下的占位大小检查函数(无实际作用)。 Dummy size limit check for non-debug builds.
static void Unlock(TopicHandle topic)
解锁主题。Unlock the topic.
Definition topic.cpp:48
static void Lock(TopicHandle topic)
锁定主题,防止其被多个订阅者同时访问。Lock the topic to prevent it from being accessed by multiple subscribers at the sa...
Definition topic.cpp:30
static void PackData(uint32_t topic_name_crc32, RawData buffer, MicrosecondTimestamp timestamp, ConstRawData data)
打包数据
Definition packet.cpp:40

◆ DumpPayload()

template<SizeLimitMode Mode = SizeLimitMode::MORE>
ErrorCode LibXR::Topic::DumpPayload ( RawData buffer,
MicrosecondTimestamp & timestamp )
inlineprivate

Definition at line 599 of file message.hpp.

600 {
601 if (block_->data_.data.addr_ == nullptr)
602 {
603 return ErrorCode::EMPTY;
604 }
605
606 const size_t payload_size = block_->data_.data.size_;
607 size_t copy_size = payload_size;
608
609 if constexpr (Mode == SizeLimitMode::EQUAL)
610 {
611 if (payload_size != buffer.size_)
612 {
613 return ErrorCode::SIZE_ERR;
614 }
615 }
616 else if constexpr (Mode == SizeLimitMode::LESS)
617 {
618 if (payload_size < buffer.size_)
619 {
620 return ErrorCode::SIZE_ERR;
621 }
622 copy_size = buffer.size_;
623 }
624 else if constexpr (Mode == SizeLimitMode::MORE)
625 {
626 if (payload_size > buffer.size_)
627 {
628 return ErrorCode::SIZE_ERR;
629 }
630 }
631
632 Lock(block_);
633 timestamp = block_->data_.timestamp;
634 LibXR::Memory::FastCopy(buffer.addr_, block_->data_.data.addr_, copy_size);
635 Unlock(block_);
636
637 return ErrorCode::OK;
638 }
@ SIZE_ERR
尺寸错误 | Size error
@ LESS
尺寸必须小于 | Size must be less
@ EQUAL
尺寸必须相等 | Size must be equal
@ MORE
尺寸必须大于 | Size must be more

◆ EnableCache()

void Topic::EnableCache ( )

启用主题的缓存功能 Enables caching for the topic

Note
包含初始化期动态内存分配,缓存启用后应长期存在。 Contains initialization-time dynamic allocation; the cache is expected to remain enabled for the topic lifetime.

Definition at line 210 of file topic.cpp.

211{
212 Lock(block_);
213
214 if (!block_->data_.cache)
215 {
216 block_->data_.cache = true;
217 block_->data_.data.addr_ = new uint8_t[block_->data_.max_length];
218 }
219
220 Unlock(block_);
221}

◆ EnsureDefaultDomain()

Topic::Domain * Topic::EnsureDefaultDomain ( )
staticprivate

Definition at line 20 of file topic.cpp.

21{
22 if (!def_domain_)
23 {
24 def_domain_ = new Domain("libxr_def_domain");
25 }
26
27 return def_domain_;
28}
static Domain * def_domain_
默认的主题域,所有未指定域的主题都会归入此域 Default domain where all topics without a specified domain are assigned
Definition message.hpp:563

◆ EnsureDomainRegistry()

void Topic::EnsureDomainRegistry ( )
staticprivate

Definition at line 11 of file topic.cpp.

12{
13 if (!domain_)
14 {
15 domain_ = new RBTree<uint32_t>([](const uint32_t& a, const uint32_t& b)
16 { return static_cast<int>(a) - static_cast<int>(b); });
17 }
18}
红黑树实现,支持泛型键和值,并提供线程安全操作 (Red-Black Tree implementation supporting generic keys and values with thread...
Definition rbt.hpp:24
static RBTree< uint32_t > * domain_
主题域的红黑树结构,存储不同的主题 Red-Black Tree structure for storing different topics in the domain
Definition message.hpp:557

◆ Find()

Topic::TopicHandle Topic::Find ( const char * name,
Domain * domain = nullptr )
static

在指定域中查找主题 Finds a topic in the specified domain

Parameters
name主题名称 Topic name
domain主题所属的域(默认为 nullptr)Domain to search in (default: nullptr)
Returns
主题句柄,如果找到则返回对应的句柄,否则返回 nullptr Topic handle if found, otherwise returns nullptr
Note
查询不会创建默认域;默认域尚未初始化时返回 nullptr。 Lookup does not create the default domain; it returns nullptr when the default domain has not been initialized.

Definition at line 192 of file topic.cpp.

193{
194 ASSERT(name != nullptr);
195
196 if (domain == nullptr)
197 {
198 if (def_domain_ == nullptr)
199 {
200 return nullptr;
201 }
202 domain = def_domain_;
203 }
204
205 auto crc32 = CRC32::Calculate(name, strlen(name));
206
207 return domain->node_->data_.Search<Block>(crc32);
208}

◆ FindOrCreate()

template<typename Data >
static TopicHandle LibXR::Topic::FindOrCreate ( const char * name,
Domain * domain = nullptr,
bool multi_publisher = false,
bool cache = false,
bool check_length = false )
inlinestatic

在指定域中查找或创建主题 Finds or creates a topic in the specified domain

Template Parameters
Data数据类型 Data type
Parameters
name话题名称 Topic name
domain可选的域指针 Optional domain pointer (default: nullptr)
multi_publisher可选的多发布标志位 Optional multi-publisher flag
cache可选的缓存标志位 Optional cache flag (default: false)
check_length可选的数据长度检查标志位 Optional data length check flag (default: false)
Returns
TopicHandle 主题句柄 Topic handle
Note
包含初始化期动态内存分配,主题应长期存在。 Contains initialization-time dynamic allocation; topics are expected to be long-lived.

Definition at line 350 of file message.hpp.

353 {
354 CheckTopicPayload<Data>();
355 auto topic = Find(name, domain);
356 if (topic == nullptr)
357 {
358 topic =
359 CreateTopic<Data>(name, domain, multi_publisher, cache, check_length).block_;
360 }
361 return topic;
362 }
static TopicHandle Find(const char *name, Domain *domain=nullptr)
在指定域中查找主题 Finds a topic in the specified domain
Definition topic.cpp:192
static Topic CreateTopic(const char *name, Domain *domain=nullptr, bool multi_publisher=false, bool cache=false, bool check_length=false)
创建一个新的主题 Creates a new topic
Definition message.hpp:303

◆ GetKey()

uint32_t Topic::GetKey ( ) const

获取主题的键值 Gets the key value of the topic

Returns
uint32_t

Definition at line 244 of file topic.cpp.

245{
246 if (block_)
247 {
248 return block_->key;
249 }
250 else
251 {
252 return 0;
253 }
254}
Key key
节点键值 (Key associated with the node).
Definition rbt.hpp:41

◆ GetTimestamp()

MicrosecondTimestamp Topic::GetTimestamp ( ) const

Definition at line 256 of file topic.cpp.

257{
258 if (block_ == nullptr)
259 {
260 return MicrosecondTimestamp();
261 }
262 return block_->data_.timestamp;
263}

◆ Lock()

void Topic::Lock ( Topic::TopicHandle topic)
static

锁定主题,防止其被多个订阅者同时访问。Lock the topic to prevent it from being accessed by multiple subscribers at the same time.

Parameters
topic要锁定的主题。Topic to be locked.

Definition at line 30 of file topic.cpp.

31{
32 if (topic->data_.mutex)
33 {
34 topic->data_.mutex->Lock();
35 }
36 else
37 {
38 LockState expected = LockState::UNLOCKED;
39 if (!topic->data_.busy.compare_exchange_strong(expected, LockState::LOCKED))
40 {
41 /* Multiple threads are trying to lock the same topic */
42 ASSERT(false);
43 return;
44 }
45 }
46}

◆ LockFromCallback()

void Topic::LockFromCallback ( Topic::TopicHandle topic)
static

从回调中锁定主题,防止其被多个订阅者同时访问。Lock the topic from a callback to prevent it from being accessed by multiple subscribers at the same time.

Parameters
topic要锁定的主题。Topic to be locked.

Definition at line 60 of file topic.cpp.

61{
62 if (topic->data_.mutex)
63 {
64 ASSERT(false);
65 }
66 else
67 {
68 LockState expected = LockState::UNLOCKED;
69 if (!topic->data_.busy.compare_exchange_strong(expected, LockState::LOCKED))
70 {
71 /* Multiple threads are trying to lock the same topic */
72 ASSERT(false);
73 return;
74 }
75 }
76}

◆ NewSubscriberBuffer()

template<typename Data >
static RawData LibXR::Topic::NewSubscriberBuffer ( )
inlinestaticprivate

为异步订阅者分配长期存在的接收缓冲区。 Allocates a long-lived receive buffer for an async subscriber.

Definition at line 591 of file message.hpp.

592 {
593 CheckTopicPayload<Data>();
594 auto* data = new Data;
595 return RawData(*data);
596 }

◆ NowTimestamp()

MicrosecondTimestamp Topic::NowTimestamp ( )
static

生成默认发布时刻。Create the default publish timestamp.

Returns
当前 Timebase 微秒时间戳。Current Timebase microsecond timestamp.

Definition at line 9 of file publish.cpp.

10{
11 ASSERT(Timebase::timebase != nullptr);
13}
static Timebase * timebase
静态指针,用于存储全局时间基对象。 Static pointer storing the global timebase instance.
Definition timebase.hpp:119
static MicrosecondTimestamp GetMicroseconds()
获取当前时间的微秒级时间戳。 Gets the current timestamp in microseconds.
Definition timebase.hpp:49

◆ operator TopicHandle()

LibXR::Topic::operator TopicHandle ( )
inline

Topic 转换为 TopicHandle Converts Topic to TopicHandle

Returns
TopicHandle

Definition at line 530 of file message.hpp.

530{ return block_; }

◆ PackData()

void Topic::PackData ( uint32_t topic_name_crc32,
RawData buffer,
MicrosecondTimestamp timestamp,
ConstRawData data )
static

打包数据

Parameters
topic_name_crc32话题名称的 CRC32 校验码
buffer等待写入的包 Packed data to be written
timestamp需要打包的消息时间戳 Message timestamp to be packed
data需要打包的消息数据 Message data to be packed

Definition at line 40 of file packet.cpp.

42{
43 PackedData<uint8_t>* pack = reinterpret_cast<PackedData<uint8_t>*>(buffer.addr_);
44
45 LibXR::Memory::FastCopy(&pack->raw.data_, data.addr_, data.size_);
46
47 pack->raw.header_.prefix = PACKET_PREFIX;
48 pack->raw.header_.topic_name_crc32 = topic_name_crc32;
49 pack->raw.header_.SetDataLen(data.size_);
50 pack->raw.header_.SetTimestamp(timestamp);
51 pack->raw.header_.pack_header_crc8 =
52 CRC8::Calculate(&pack->raw, sizeof(PackedDataHeader) - sizeof(uint8_t));
53 uint8_t* crc8_pack = reinterpret_cast<uint8_t*>(
54 reinterpret_cast<uint8_t*>(pack) + PACK_BASE_SIZE + data.size_ - sizeof(uint8_t));
55 *crc8_pack = CRC8::Calculate(pack, PACK_BASE_SIZE - sizeof(uint8_t) + data.size_);
56}
static uint8_t Calculate(const void *raw, size_t len)
计算数据的 CRC8 校验码 / Computes the CRC8 checksum for the given data
Definition crc.hpp:67
size_t size_
数据字节数 / Data size in bytes
const void * addr_
数据起始地址 / Data start address

◆ Publish() [1/4]

template<typename Data >
void LibXR::Topic::Publish ( Data & data)
inline

发布数据 Publishes data

Template Parameters
Data数据类型 Data type
Parameters
data需要发布的数据 Data to be published

Definition at line 381 of file message.hpp.

382 {
383 CheckTopicPayload<Data>();
384 Publish(static_cast<void*>(&data), static_cast<uint32_t>(sizeof(Data)));
385 }
void Publish(Data &data)
发布数据 Publishes data
Definition message.hpp:381

◆ Publish() [2/4]

template<typename Data >
void LibXR::Topic::Publish ( Data & data,
MicrosecondTimestamp timestamp )
inline

Definition at line 388 of file message.hpp.

389 {
390 CheckTopicPayload<Data>();
391 Publish(static_cast<void*>(&data), static_cast<uint32_t>(sizeof(Data)), timestamp);
392 }

◆ Publish() [3/4]

void Topic::Publish ( void * addr,
uint32_t size )

以原始地址和大小发布数据 Publishes data using raw address and size

Parameters
addr数据的地址 Address of the data
size数据大小 Size of the data

Definition at line 139 of file publish.cpp.

139{ Publish(addr, size, NowTimestamp()); }
static MicrosecondTimestamp NowTimestamp()
生成默认发布时刻。Create the default publish timestamp.
Definition publish.cpp:9

◆ Publish() [4/4]

void Topic::Publish ( void * addr,
uint32_t size,
MicrosecondTimestamp timestamp )

Definition at line 141 of file publish.cpp.

142{
143 PublishRaw(addr, size, timestamp, false, false);
144}

◆ PublishFromCallback() [1/4]

template<typename Data >
void LibXR::Topic::PublishFromCallback ( Data & data,
bool in_isr )
inline

在回调函数中发布数据 Publishes data in a callback

Template Parameters
Data数据类型 Data type
Parameters
data需要发布的数据 Data to be published
in_isr是否在中断中发布数据 Whether to publish data in an interrupt

Definition at line 412 of file message.hpp.

413 {
414 CheckTopicPayload<Data>();
415 PublishFromCallback(static_cast<void*>(&data), static_cast<uint32_t>(sizeof(Data)),
416 in_isr);
417 }
void PublishFromCallback(Data &data, bool in_isr)
在回调函数中发布数据 Publishes data in a callback
Definition message.hpp:412

◆ PublishFromCallback() [2/4]

template<typename Data >
void LibXR::Topic::PublishFromCallback ( Data & data,
MicrosecondTimestamp timestamp,
bool in_isr )
inline

Definition at line 420 of file message.hpp.

421 {
422 CheckTopicPayload<Data>();
423 PublishFromCallback(static_cast<void*>(&data), static_cast<uint32_t>(sizeof(Data)),
424 timestamp, in_isr);
425 }

◆ PublishFromCallback() [3/4]

void Topic::PublishFromCallback ( void * addr,
uint32_t size,
bool in_isr )

在回调函数中以原始地址和大小发布数据 Publishes data using raw address and size in a callback

Parameters
addr数据的地址 Address of the data
size数据大小 Size of the data
in_isr是否在中断中发布数据 Whether to publish data in an interrupt
Note
仅适用于非 mutex 主题。multi_publisher 主题会在回调发布路径触发断言。 Only valid for non-mutex topics. Multi-publisher topics assert on the callback publish path.
回调发布路径不分配内存,但仍会同步分发到该主题的订阅者。 The callback publish path does not allocate, but still dispatches to the topic subscribers synchronously.

Definition at line 146 of file publish.cpp.

147{
148 PublishFromCallback(addr, size, NowTimestamp(), in_isr);
149}

◆ PublishFromCallback() [4/4]

void Topic::PublishFromCallback ( void * addr,
uint32_t size,
MicrosecondTimestamp timestamp,
bool in_isr )

Definition at line 151 of file publish.cpp.

153{
154 PublishRaw(addr, size, timestamp, true, in_isr);
155}

◆ PublishRaw()

void Topic::PublishRaw ( void * addr,
uint32_t size,
MicrosecondTimestamp timestamp,
bool from_callback,
bool in_isr )
private

Definition at line 113 of file publish.cpp.

115{
116 if (from_callback)
117 {
119 }
120 else
121 {
122 Lock(block_);
123 }
124
125 CheckPublishSize(block_, size);
126 RawData data = StorePublishedData(block_, addr, size, timestamp);
127 DispatchSubscribers(block_, timestamp, data, from_callback, in_isr);
128
129 if (from_callback)
130 {
132 }
133 else
134 {
135 Unlock(block_);
136 }
137}
可写原始数据视图 / Mutable raw data view
static void UnlockFromCallback(TopicHandle topic)
从回调中解锁主题。Unlock the topic from a callback.
Definition topic.cpp:78
static void LockFromCallback(TopicHandle topic)
从回调中锁定主题,防止其被多个订阅者同时访问。Lock the topic from a callback to prevent it from being accessed by multiple s...
Definition topic.cpp:60

◆ RegisterCallback()

void LibXR::Topic::RegisterCallback ( Callback & cb)

注册回调函数 Registers a callback function

Parameters
cb需要注册的回调函数 The callback function to register
Note
包含初始化期动态内存分配,回调订阅应长期存在。 Contains initialization-time dynamic allocation; callback subscriptions are expected to be long-lived.
回调在发布锁内运行,不应重入发布同一个主题。 The callback runs while the publish lock is held and should not re-enter publishing on the same topic.

Definition at line 113 of file topic.cpp.

114{
115 if (cb.PayloadSize() != 0)
116 {
117 if (block_->data_.check_length)
118 {
119 ASSERT(block_->data_.max_length == cb.PayloadSize());
120 }
121 else
122 {
123 ASSERT(block_->data_.max_length <= cb.PayloadSize());
124 }
125 }
126
127 auto node = new (std::align_val_t(LibXR::CACHE_LINE_SIZE))
129 block_->data_.subers.Add(*node);
130}
数据节点模板,继承自 BaseNode,用于存储具体数据类型。 Template data node that inherits from BaseNode to store specific data...
constexpr size_t CACHE_LINE_SIZE
缓存行大小 / Cache line size
Definition libxr_def.hpp:32

◆ StorePublishedData()

RawData Topic::StorePublishedData ( TopicHandle topic,
void * addr,
uint32_t size,
MicrosecondTimestamp timestamp )
staticprivate

Definition at line 27 of file publish.cpp.

29{
30 if (topic->data_.cache)
31 {
32 LibXR::Memory::FastCopy(topic->data_.data.addr_, addr, size);
33 topic->data_.data.size_ = size;
34 }
35 else
36 {
37 topic->data_.data.addr_ = addr;
38 topic->data_.data.size_ = size;
39 }
40
41 topic->data_.timestamp = timestamp;
42 return topic->data_.data;
43}

◆ Unlock()

void Topic::Unlock ( Topic::TopicHandle topic)
static

解锁主题。Unlock the topic.

Parameters
topic要解锁的主题。Topic to be unlocked.

Definition at line 48 of file topic.cpp.

49{
50 if (topic->data_.mutex)
51 {
52 topic->data_.mutex->Unlock();
53 }
54 else
55 {
56 topic->data_.busy.store(LockState::UNLOCKED, std::memory_order_release);
57 }
58}

◆ UnlockFromCallback()

void Topic::UnlockFromCallback ( Topic::TopicHandle topic)
static

从回调中解锁主题。Unlock the topic from a callback.

Parameters
topic要解锁的主题。Topic to be unlocked.

Definition at line 78 of file topic.cpp.

79{
80 if (topic->data_.mutex)
81 {
82 ASSERT(false);
83 }
84 else
85 {
86 topic->data_.busy.store(LockState::UNLOCKED, std::memory_order_release);
87 }
88}

◆ WaitTopic()

Topic::TopicHandle Topic::WaitTopic ( const char * name,
uint32_t timeout = UINT32_MAX,
Domain * domain = nullptr )
static

等待主题的创建并返回其句柄 Waits for a topic to be created and returns its handle

Parameters
name主题名称 The name of the topic
timeout等待的超时时间(默认 UINT32_MAX)Timeout duration to wait (default: UINT32_MAX)
domain主题所属的域(默认为 nullptr)The domain in which to search for the topic (default: nullptr)
Returns
TopicHandle 如果找到主题,则返回其句柄,否则返回 nullptr TopicHandle if the topic is found, otherwise returns nullptr

Definition at line 223 of file topic.cpp.

224{
225 const uint32_t start_time = Thread::GetTime();
226 TopicHandle topic = nullptr;
227 do
228 {
229 topic = Find(name, domain);
230 if (topic == nullptr)
231 {
232 if (timeout != UINT32_MAX &&
233 static_cast<uint32_t>(Thread::GetTime() - start_time) >= timeout)
234 {
235 return nullptr;
236 }
237 Thread::Sleep(1);
238 }
239 } while (topic == nullptr);
240
241 return topic;
242}
static uint32_t GetTime()
获取当前系统时间(毫秒) Gets the current system time in milliseconds
Definition thread.cpp:35
static void Sleep(uint32_t milliseconds)
让线程进入休眠状态 Puts the thread to sleep
Definition thread.cpp:15
RBTree< uint32_t >::Node< Block > * TopicHandle
主题句柄,指向存储数据的红黑树节点。Handle pointing to a red-black tree node storing data.
Definition message.hpp:135

Field Documentation

◆ block_

TopicHandle LibXR::Topic::block_ = nullptr
private

主题句柄,指向当前主题的内存块 Topic handle pointing to the memory block of the current topic

Definition at line 547 of file message.hpp.

◆ def_domain_

Domain* LibXR::Topic::def_domain_ = nullptr
inlinestaticprivate

默认的主题域,所有未指定域的主题都会归入此域 Default domain where all topics without a specified domain are assigned

Definition at line 563 of file message.hpp.

◆ domain_

RBTree<uint32_t>* LibXR::Topic::domain_ = nullptr
inlinestaticprivate

主题域的红黑树结构,存储不同的主题 Red-Black Tree structure for storing different topics in the domain

Note
初始化期懒创建;调用者应在并发发布前完成 topic/domain 创建。 Lazily created during initialization; callers should finish topic/domain creation before concurrent publishing starts.

Definition at line 557 of file message.hpp.


The documentation for this class was generated from the following files: