libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
topic.cpp
1#include "topic.hpp"
2
3#include <atomic>
4
5#include "crc.hpp"
6#include "libxr_def.hpp"
7#include "mutex.hpp"
8
9using namespace LibXR;
10
11template class LibXR::RBTree<uint32_t>;
12
14{
15 if (!domain_)
16 {
17 domain_ = new RBTree<uint32_t>([](const uint32_t& a, const uint32_t& b)
18 { return (a > b) - (a < b); });
19 }
20}
21
23{
24 if (!def_domain_)
25 {
26 def_domain_ = new Domain("libxr_def_domain");
27 }
28
29 return def_domain_;
30}
31
33{
34 if (topic->data_.mutex)
35 {
36 topic->data_.mutex->Lock();
37 }
38 else
39 {
41 if (!topic->data_.busy.compare_exchange_strong(expected, LockState::LOCKED))
42 {
43 // 非 mutex topic 禁止并发发布
44 ASSERT(false);
45 return;
46 }
47 }
48}
49
51{
52 if (topic->data_.mutex)
53 {
54 topic->data_.mutex->Unlock();
55 }
56 else
57 {
58 topic->data_.busy.store(LockState::UNLOCKED, std::memory_order_release);
59 }
60}
61
63{
64 if (topic->data_.mutex)
65 {
66 ASSERT(false);
67 }
68 else
69 {
71 if (!topic->data_.busy.compare_exchange_strong(expected, LockState::LOCKED))
72 {
73 // 回调发布路径要求外围先串行化
74 ASSERT(false);
75 return;
76 }
77 }
78}
79
81{
82 if (topic->data_.mutex)
83 {
84 ASSERT(false);
85 }
86 else
87 {
88 topic->data_.busy.store(LockState::UNLOCKED, std::memory_order_release);
89 }
90}
91
92Topic::Domain::Domain(const char* name)
93{
94 ASSERT(name != nullptr);
95
97
98 auto crc32 = CRC32::Calculate(name, strlen(name));
99
100 auto domain = domain_->Search<RBTree<uint32_t>>(crc32);
101
102 if (domain != nullptr)
103 {
104 node_ = domain;
105 return;
106 }
107
109 [](const uint32_t& a, const uint32_t& b) { return (a > b) - (a < b); });
110
111 domain_->Insert(*node_, crc32);
112}
113
115
116Topic::Topic(const char* name, TypeID::ID payload_type_id, size_t payload_size,
117 size_t payload_alignment, Domain* domain, bool multi_publisher)
118{
119 ASSERT(name != nullptr);
120 ASSERT(payload_type_id != nullptr);
121 ASSERT(payload_size != 0);
122 ASSERT(payload_alignment != 0);
123 ASSERT((payload_alignment & (payload_alignment - 1)) == 0);
124
125 if (domain == nullptr)
126 {
127 domain = EnsureDefaultDomain();
128 }
129
130 auto crc32 = CRC32::Calculate(name, strlen(name));
131
132 auto topic = domain->node_->data_.Search<Block>(crc32);
133
134 if (topic)
135 {
136 ASSERT(topic->data_.payload_type_id == payload_type_id);
137 ASSERT(topic->data_.payload_size == payload_size);
138 ASSERT(topic->data_.payload_alignment == payload_alignment);
139
140 if (multi_publisher && !topic->data_.mutex)
141 {
142 ASSERT(false);
143 }
144
145 block_ = topic;
146 }
147 else
148 {
150 block_->data_.payload_type_id = payload_type_id;
151 block_->data_.payload_size = payload_size;
152 block_->data_.payload_alignment = payload_alignment;
153 block_->data_.crc32 = crc32;
154
155 if (multi_publisher)
156 {
157 block_->data_.mutex = new Mutex();
158 block_->data_.busy.store(LockState::USE_MUTEX, std::memory_order_release);
159 }
160 else
161 {
162 block_->data_.mutex = nullptr;
163 block_->data_.busy.store(LockState::UNLOCKED, std::memory_order_release);
164 }
165
166 domain->node_->data_.Insert(*block_, crc32);
167 }
168}
169
171
172Topic::TopicHandle Topic::Find(const char* name, Domain* domain)
173{
174 ASSERT(name != nullptr);
175
176 if (domain == nullptr)
177 {
178 if (def_domain_ == nullptr)
179 {
180 return nullptr;
181 }
182 domain = def_domain_;
183 }
184
185 auto crc32 = CRC32::Calculate(name, strlen(name));
186
187 return domain->node_->data_.Search<Block>(crc32);
188}
189
190Topic::TopicHandle Topic::WaitTopic(const char* name, uint32_t timeout, Domain* domain)
191{
192 const uint32_t start_time = Thread::GetTime();
193 TopicHandle topic = nullptr;
194 do
195 {
196 topic = Find(name, domain);
197 if (topic == nullptr)
198 {
199 if (timeout != UINT32_MAX &&
200 static_cast<uint32_t>(Thread::GetTime() - start_time) >= timeout)
201 {
202 return nullptr;
203 }
204 Thread::Sleep(1);
205 }
206 } while (topic == nullptr);
207
208 return topic;
209}
210
211uint32_t Topic::GetKey() const
212{
213 if (block_)
214 {
215 return block_->key;
216 }
217 else
218 {
219 return 0;
220 }
221}
static uint32_t Calculate(const void *raw, size_t len)
计算数据的 CRC32 校验码 / Computes the CRC32 checksum for the given data
Definition crc_o3.cpp:35
互斥锁类,提供线程同步机制 (Mutex class providing thread synchronization mechanisms).
Definition mutex.hpp:18
Key key
节点键值 (Key associated with the node).
Definition rbt.hpp:40
红黑树的泛型数据节点,继承自 BaseNode (Generic data node for Red-Black Tree, inheriting from BaseNode).
Definition rbt.hpp:63
Data data_
存储的数据 (Stored data).
Definition rbt.hpp:98
红黑树实现,支持泛型键和值,并提供线程安全操作 (Red-Black Tree implementation supporting generic keys and values with thread...
Definition rbt.hpp:23
Node< Data > * Search(const Key &key)
搜索红黑树中的节点 (Search for a node in the Red-Black Tree).
Definition rbt.hpp:120
void Insert(BaseNode &node, KeyType &&key)
在树中插入新节点 (Insert a new node into the tree).
Definition rbt.hpp:235
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
topic 所属的命名域 / Naming domain that groups topics
Definition topic.hpp:207
Domain(const char *name)
构造一个 topic 域 / Construct one topic domain
Definition topic.cpp:92
RBTree< uint32_t >::Node< RBTree< uint32_t > > * node_
Definition topic.hpp:216
static Domain * def_domain_
缺省 topic 域。Default topic domain.
Definition topic.hpp:615
static void Unlock(TopicHandle topic)
在普通上下文里释放一个 topic 发布路径 / Unlock one topic publish path in normal context
Definition topic.cpp:50
static Domain * EnsureDefaultDomain()
确保默认域已创建 / Ensure the default domain exists
Definition topic.cpp:22
static void Lock(TopicHandle topic)
在普通上下文里锁住一个 topic 发布路径 / Lock one topic publish path in normal context
Definition topic.cpp:32
static void UnlockFromCallback(TopicHandle topic)
在回调或 ISR 路径里释放一个 topic 发布路径 / Unlock one topic publish path from callback or ISR context
Definition topic.cpp:80
static void LockFromCallback(TopicHandle topic)
在回调或 ISR 路径里锁住一个 topic 发布路径 / Lock one topic publish path from callback or ISR context
Definition topic.cpp:62
static TopicHandle WaitTopic(const char *name, uint32_t timeout=UINT32_MAX, Domain *domain=nullptr)
等待指定名称的 topic 出现 / Wait until a topic with the given name exists
Definition topic.cpp:190
uint32_t GetKey() const
读取 topic 键值 / Read the key value of this topic
Definition topic.cpp:211
TopicHandle block_
Definition topic.hpp:610
LockState
topic 发布路径的内部锁状态 / Internal lock state of the topic publish path
Definition topic.hpp:62
@ UNLOCKED
当前未持有发布锁。The publish path is currently unlocked.
static TopicHandle Find(const char *name, Domain *domain=nullptr)
按名称查找一个已存在 topic / Find one existing topic by name
Definition topic.cpp:172
static RBTree< uint32_t > * domain_
全局 topic 域注册表。Global registry of topic domains.
Definition topic.hpp:613
Topic()
构造一个空 topic 视图 / Construct one empty topic view
Definition topic.cpp:114
static void EnsureDomainRegistry()
确保全局域注册表已创建 / Ensure the global domain registry exists
Definition topic.cpp:13
LibXR 命名空间
Definition ch32_can.hpp:14
topic 运行时状态块 / Runtime state block of one topic
Definition topic.hpp:82