libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
operation.hpp
1#pragma once
2
3#include <atomic>
4#include <cstdint>
5#include <utility>
6
7#include "libxr_cb.hpp"
8#include "libxr_def.hpp"
9#include "libxr_type.hpp"
10#include "semaphore.hpp"
11
12namespace LibXR
13{
14
22template <typename Args>
24{
25 public:
27
30 enum class OperationType : uint8_t
31 {
32 CALLBACK,
33 BLOCK,
34 POLLING,
35 NONE
36 };
37
40 enum class OperationPollingStatus : uint8_t
41 {
42 READY,
43 RUNNING,
44 DONE,
45 ERROR
46 };
47
50 Operation() : data{nullptr}, type(OperationType::NONE) {}
51
63 Operation(Semaphore& sem, uint32_t timeout = UINT32_MAX)
64 : data{.sem_info = {&sem, timeout}}, type(OperationType::BLOCK)
65 {
66 }
67
74 : data{.callback = &callback}, type(OperationType::CALLBACK)
75 {
76 }
77
84 : data{.status = &status}, type(OperationType::POLLING)
85 {
86 }
87
88 Operation(const Operation& op) : data{nullptr}, type(OperationType::NONE)
89 {
90 *this = op;
91 }
92
93 Operation(Operation&& op) noexcept : data{nullptr}, type(OperationType::NONE)
94 {
95 *this = std::move(op);
96 }
97
105 {
106 if (this != &op)
107 {
108 type = op.type;
109 switch (type)
110 {
111 case OperationType::CALLBACK:
112 data.callback = op.data.callback;
113 break;
114 case OperationType::BLOCK:
115 data.sem_info.sem = op.data.sem_info.sem;
116 data.sem_info.timeout = op.data.sem_info.timeout;
117 break;
118 case OperationType::POLLING:
119 data.status = op.data.status;
120 break;
121 case OperationType::NONE:
122 data.callback = nullptr;
123 break;
124 }
125 }
126 return *this;
127 }
128
136 {
137 if (this != &op)
138 {
139 type = op.type;
140 switch (type)
141 {
142 case OperationType::CALLBACK:
143 data.callback = op.data.callback;
144 break;
145 case OperationType::BLOCK:
146 data.sem_info.sem = op.data.sem_info.sem;
147 data.sem_info.timeout = op.data.sem_info.timeout;
148 break;
149 case OperationType::POLLING:
150 data.status = op.data.status;
151 break;
152 case OperationType::NONE:
153 data.callback = nullptr;
154 break;
155 }
156 }
157 return *this;
158 }
159
166 template <typename Status>
167 void UpdateStatus(bool in_isr, Status&& status)
168 {
169 switch (type)
170 {
171 case OperationType::CALLBACK:
172 data.callback->Run(in_isr, std::forward<Status>(status));
173 break;
174 case OperationType::BLOCK:
175 // BLOCK waits are signaled by semaphore only; the owning port keeps the
176 // final ErrorCode in its block_result_ handoff state.
177 // BLOCK 只通过信号量唤醒;最终 ErrorCode 由端口侧 block_result_ 交接。
178 data.sem_info.sem->PostFromCallback(in_isr);
179 break;
180 case OperationType::POLLING:
181 *data.status = (status == ErrorCode::OK) ? OperationPollingStatus::DONE
182 : OperationPollingStatus::ERROR;
183 break;
184 case OperationType::NONE:
185 break;
186 }
187 }
188
203 {
204 if (type == OperationType::POLLING)
205 {
206 *data.status = OperationPollingStatus::RUNNING;
207 }
208 }
209
212 union
213 {
214 Callback* callback;
215 struct
216 {
217 Semaphore* sem;
218 uint32_t timeout;
219 } sem_info;
220 OperationPollingStatus* status;
221 } data;
222
226};
227
235{
236 public:
237 // Keep the waiter state 32-bit wide so STM32 builds stay within the
238 // project-wide atomic shim boundary.
239 enum class State : uint32_t
240 {
241 IDLE = 0,
242 PENDING = 1,
243 CLAIMED = 2,
244 DETACHED = 3,
245 };
246
247 void Start(Semaphore& sem)
248 {
249 sem_ = &sem;
250 result_ = ErrorCode::OK;
251 state_.store(State::PENDING, std::memory_order_release);
252 }
253
254 void Cancel() { state_.store(State::IDLE, std::memory_order_release); }
255
256 ErrorCode Wait(uint32_t timeout)
257 {
258 ASSERT(sem_ != nullptr);
259 auto wait_ans = sem_->Wait(timeout);
260 if (wait_ans == ErrorCode::OK)
261 {
262#ifdef LIBXR_DEBUG_BUILD
263 ASSERT(state_.load(std::memory_order_acquire) == State::CLAIMED);
264#endif
265 state_.store(State::IDLE, std::memory_order_release);
266 return result_;
267 }
268
269 State expected = State::PENDING;
270 if (state_.compare_exchange_strong(expected, State::DETACHED,
271 std::memory_order_acq_rel,
272 std::memory_order_acquire))
273 {
274 return ErrorCode::TIMEOUT;
275 }
276
277 ASSERT(expected == State::CLAIMED || expected == State::DETACHED ||
278 expected == State::IDLE);
279 if (expected == State::DETACHED)
280 {
281 state_.store(State::IDLE, std::memory_order_release);
282 return ErrorCode::TIMEOUT;
283 }
284 if (expected == State::IDLE)
285 {
286 return ErrorCode::TIMEOUT;
287 }
288
289 auto finish_wait_ans = sem_->Wait(UINT32_MAX);
290 UNUSED(finish_wait_ans);
291 ASSERT(finish_wait_ans == ErrorCode::OK);
292 state_.store(State::IDLE, std::memory_order_release);
293 return result_;
294 }
295
296 bool TryPost(bool in_isr, ErrorCode ec)
297 {
298 ASSERT(sem_ != nullptr);
299
300 State expected = State::PENDING;
301 if (!state_.compare_exchange_strong(expected, State::CLAIMED,
302 std::memory_order_acq_rel,
303 std::memory_order_acquire))
304 {
305 ASSERT(expected == State::DETACHED || expected == State::IDLE);
306 if (expected == State::DETACHED)
307 {
308 expected = State::DETACHED;
309 (void)state_.compare_exchange_strong(
310 expected, State::IDLE, std::memory_order_acq_rel, std::memory_order_acquire);
311 }
312 return false;
313 }
314
315 result_ = ec;
316 sem_->PostFromCallback(in_isr);
317 return true;
318 }
319
320 private:
321 Semaphore* sem_ = nullptr;
322 std::atomic<State> state_{State::IDLE};
323 ErrorCode result_ = ErrorCode::OK;
324};
325
326class ReadPort;
327class WritePort;
328
332
336
347typedef ErrorCode (*WriteFun)(WritePort& port, bool in_isr);
348
359typedef ErrorCode (*ReadFun)(ReadPort& port, bool in_isr);
360
370
376
377} // namespace LibXR
Shared BLOCK waiter handoff for synchronous driver operations.
通用回调包装,支持动态参数传递 / Generic callback wrapper supporting dynamic argument passing
Definition libxr_cb.hpp:143
只读原始数据视图 / Immutable raw data view
Defines an operation with different execution modes.
Definition operation.hpp:24
Operation & operator=(const Operation &op)
Copy assignment operator.
Operation(Semaphore &sem, uint32_t timeout=UINT32_MAX)
Constructs a blocking operation with a semaphore and timeout.
Definition operation.hpp:63
Operation & operator=(Operation &&op) noexcept
Move assignment operator.
Operation(Callback &callback)
Constructs a callback-based operation.
Definition operation.hpp:73
union LibXR::Operation::@5 data
Operation()
Default constructor, initializes with NONE type.
Definition operation.hpp:50
void UpdateStatus(bool in_isr, Status &&status)
Updates operation status based on type.
void MarkAsRunning()
标记操作为运行状态。 Marks the operation as running.
OperationType type
Operation(OperationPollingStatus &status)
Constructs a polling operation.
Definition operation.hpp:83
可写原始数据视图 / Mutable raw data view
ReadPort class for handling read operations.
Definition read_port.hpp:18
信号量类,实现线程同步机制 Semaphore class implementing thread synchronization
Definition semaphore.hpp:23
WritePort class for handling write operations.
LibXR 命名空间
Definition ch32_can.hpp:14
ErrorCode
定义错误码枚举
@ PENDING
等待中 | Pending
@ OK
操作成功 | Operation successful
Read information block structure.
RawData data
Data buffer. 数据缓冲区。
ReadOperation op
Read operation instance. 读取操作实例。
ConstRawData data
Data buffer. 数据缓冲区。
WriteOperation op
Write operation instance. 写入操作实例。