libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
topic.cpp
1#include <atomic>
2
3#include "libxr_def.hpp"
4#include "message.hpp"
5#include "mutex.hpp"
6
7using namespace LibXR;
8
9template class LibXR::RBTree<uint32_t>;
10
11void Topic::EnsureDomainRegistry()
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}
19
20Topic::Domain* Topic::EnsureDefaultDomain()
21{
22 if (!def_domain_)
23 {
24 def_domain_ = new Domain("libxr_def_domain");
25 }
26
27 return def_domain_;
28}
29
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}
47
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}
59
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}
77
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}
89
90Topic::Domain::Domain(const char* name)
91{
92 ASSERT(name != nullptr);
93
94 EnsureDomainRegistry();
95
96 auto crc32 = CRC32::Calculate(name, strlen(name));
97
98 auto domain = domain_->Search<RBTree<uint32_t>>(crc32);
99
100 if (domain != nullptr)
101 {
102 node_ = domain;
103 return;
104 }
105
107 [](const uint32_t& a, const uint32_t& b)
108 { return static_cast<int>(a) - static_cast<int>(b); });
109
110 domain_->Insert(*node_, crc32);
111}
112
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}
131
133
134Topic::Topic(const char* name, uint32_t max_length, Domain* domain, bool multi_publisher,
135 bool cache, bool check_length)
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 {
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}
189
191
192Topic::TopicHandle Topic::Find(const char* name, Domain* domain)
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}
209
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}
222
223Topic::TopicHandle Topic::WaitTopic(const char* name, uint32_t timeout, Domain* domain)
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}
243
244uint32_t Topic::GetKey() const
245{
246 if (block_)
247 {
248 return block_->key;
249 }
250 else
251 {
252 return 0;
253 }
254}
255
256MicrosecondTimestamp Topic::GetTimestamp() const
257{
258 if (block_ == nullptr)
259 {
260 return MicrosecondTimestamp();
261 }
262 return block_->data_.timestamp;
263}
static uint32_t Calculate(const void *raw, size_t len)
计算数据的 CRC32 校验码 / Computes the CRC32 checksum for the given data
Definition crc.hpp:254
数据节点模板,继承自 BaseNode,用于存储具体数据类型。 Template data node that inherits from BaseNode to store specific data...
微秒时间戳 / Microsecond timestamp
互斥锁类,提供线程同步机制 (Mutex class providing thread synchronization mechanisms).
Definition mutex.hpp:18
Key key
节点键值 (Key associated with the node).
Definition rbt.hpp:41
红黑树的泛型数据节点,继承自 BaseNode (Generic data node for Red-Black Tree, inheriting from BaseNode).
Definition rbt.hpp:64
Data data_
存储的数据 (Stored data).
Definition rbt.hpp:99
红黑树实现,支持泛型键和值,并提供线程安全操作 (Red-Black Tree implementation supporting generic keys and values with thread...
Definition rbt.hpp:24
Node< Data > * Search(const Key &key)
搜索红黑树中的节点 (Search for a node in the Red-Black Tree).
Definition rbt.hpp:121
void Insert(BaseNode &node, KeyType &&key)
在树中插入新节点 (Insert a new node into the tree).
Definition rbt.hpp:236
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
主题域(Domain)管理器,用于组织多个主题。Domain manager for organizing multiple topics.
Definition message.hpp:199
Domain(const char *name)
构造函数,初始化或查找指定名称的主题域。Constructor initializing or looking up a domain by name.
Definition topic.cpp:90
RBTree< uint32_t >::Node< RBTree< uint32_t > > * node_
指向该域的根节点。Pointer to the root node of the domain.
Definition message.hpp:215
static Domain * def_domain_
默认的主题域,所有未指定域的主题都会归入此域 Default domain where all topics without a specified domain are assigned
Definition message.hpp:563
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 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
void EnableCache()
启用主题的缓存功能 Enables caching for the topic
Definition topic.cpp:210
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
Definition topic.cpp:223
uint32_t GetKey() const
获取主题的键值 Gets the key value of the topic
Definition topic.cpp:244
TopicHandle block_
主题句柄,指向当前主题的内存块 Topic handle pointing to the memory block of the current topic
Definition message.hpp:547
void RegisterCallback(Callback &cb)
注册回调函数 Registers a callback function
Definition topic.cpp:113
static TopicHandle Find(const char *name, Domain *domain=nullptr)
在指定域中查找主题 Finds a topic in the specified domain
Definition topic.cpp:192
static RBTree< uint32_t > * domain_
主题域的红黑树结构,存储不同的主题 Red-Black Tree structure for storing different topics in the domain
Definition message.hpp:557
Topic()
默认构造函数,创建一个空的 Topic 实例 Default constructor, creates an empty Topic instance
Definition topic.cpp:132
LibXR 命名空间
Definition ch32_can.hpp:14
constexpr size_t CACHE_LINE_SIZE
缓存行大小 / Cache line size
Definition libxr_def.hpp:32
存储主题运行状态和静态配置。Stores topic runtime state and static configuration.
Definition message.hpp:80