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
73 : data{.callback = &callback}, type(OperationType::CALLBACK)
74 {}
75
82 : data{.status = &status}, type(OperationType::POLLING)
83 {}
84
85 Operation(const Operation& op) : data{nullptr}, type(OperationType::NONE)
86 {
87 *this = op;
88 }
89
90 Operation(Operation&& op) noexcept : data{nullptr}, type(OperationType::NONE)
91 {
92 *this = std::move(op);
93 }
94
102 {
103 if (this != &op)
104 {
105 type = op.type;
106 switch (type)
107 {
108 case OperationType::CALLBACK:
109 data.callback = op.data.callback;
110 break;
111 case OperationType::BLOCK:
112 data.sem_info.sem = op.data.sem_info.sem;
113 data.sem_info.timeout = op.data.sem_info.timeout;
114 break;
115 case OperationType::POLLING:
116 data.status = op.data.status;
117 break;
118 case OperationType::NONE:
119 data.callback = nullptr;
120 break;
121 }
122 }
123 return *this;
124 }
125
133 {
134 if (this != &op)
135 {
136 type = op.type;
137 switch (type)
138 {
139 case OperationType::CALLBACK:
140 data.callback = op.data.callback;
141 break;
142 case OperationType::BLOCK:
143 data.sem_info.sem = op.data.sem_info.sem;
144 data.sem_info.timeout = op.data.sem_info.timeout;
145 break;
146 case OperationType::POLLING:
147 data.status = op.data.status;
148 break;
149 case OperationType::NONE:
150 data.callback = nullptr;
151 break;
152 }
153 }
154 return *this;
155 }
156
163 template <typename Status>
164 void UpdateStatus(bool in_isr, Status&& status)
165 {
166 switch (type)
167 {
168 case OperationType::CALLBACK:
169 data.callback->Run(in_isr, std::forward<Status>(status));
170 break;
171 case OperationType::BLOCK:
172 // BLOCK waits are signaled by semaphore only; the owning port keeps the
173 // final ErrorCode in its block_result_ handoff state.
174 // BLOCK 只通过信号量唤醒;最终 ErrorCode 由端口侧 block_result_ 交接。
175 data.sem_info.sem->PostFromCallback(in_isr);
176 break;
177 case OperationType::POLLING:
178 *data.status = (status == ErrorCode::OK) ? OperationPollingStatus::DONE
179 : OperationPollingStatus::ERROR;
180 break;
181 case OperationType::NONE:
182 break;
183 }
184 }
185
200 {
201 if (type == OperationType::POLLING)
202 {
203 *data.status = OperationPollingStatus::RUNNING;
204 }
205 }
206
209 union
210 {
211 Callback* callback;
212 struct
213 {
214 Semaphore* sem;
215 uint32_t timeout;
216 } sem_info;
217 OperationPollingStatus* status;
218 } data;
219
223};
224
232{
233 public:
234 // Keep the waiter state 32-bit wide so STM32 builds stay within the
235 // project-wide atomic shim boundary.
236 enum class State : uint32_t
237 {
238 IDLE = 0,
239 PENDING = 1,
240 CLAIMED = 2,
241 DETACHED = 3,
242 };
243
244 void Start(Semaphore& sem)
245 {
246 sem_ = &sem;
247 result_ = ErrorCode::OK;
248 state_.store(State::PENDING, std::memory_order_release);
249 }
250
251 void Cancel() { state_.store(State::IDLE, std::memory_order_release); }
252
253 ErrorCode Wait(uint32_t timeout)
254 {
255 ASSERT(sem_ != nullptr);
256 auto wait_ans = sem_->Wait(timeout);
257 if (wait_ans == ErrorCode::OK)
258 {
259#ifdef LIBXR_DEBUG_BUILD
260 ASSERT(state_.load(std::memory_order_acquire) == State::CLAIMED);
261#endif
262 state_.store(State::IDLE, std::memory_order_release);
263 return result_;
264 }
265
266 State expected = State::PENDING;
267 if (state_.compare_exchange_strong(expected, State::DETACHED,
268 std::memory_order_acq_rel,
269 std::memory_order_acquire))
270 {
271 return ErrorCode::TIMEOUT;
272 }
273
274 ASSERT(expected == State::CLAIMED || expected == State::DETACHED ||
275 expected == State::IDLE);
276 if (expected == State::DETACHED)
277 {
278 state_.store(State::IDLE, std::memory_order_release);
279 return ErrorCode::TIMEOUT;
280 }
281 if (expected == State::IDLE)
282 {
283 return ErrorCode::TIMEOUT;
284 }
285
286 auto finish_wait_ans = sem_->Wait(UINT32_MAX);
287 UNUSED(finish_wait_ans);
288 ASSERT(finish_wait_ans == ErrorCode::OK);
289 state_.store(State::IDLE, std::memory_order_release);
290 return result_;
291 }
292
293 bool TryPost(bool in_isr, ErrorCode ec)
294 {
295 ASSERT(sem_ != nullptr);
296
297 State expected = State::PENDING;
298 if (!state_.compare_exchange_strong(expected, State::CLAIMED,
299 std::memory_order_acq_rel,
300 std::memory_order_acquire))
301 {
302 ASSERT(expected == State::DETACHED || expected == State::IDLE);
303 if (expected == State::DETACHED)
304 {
305 expected = State::DETACHED;
306 (void)state_.compare_exchange_strong(expected, State::IDLE,
307 std::memory_order_acq_rel,
308 std::memory_order_acquire);
309 }
310 return false;
311 }
312
313 result_ = ec;
314 sem_->PostFromCallback(in_isr);
315 return true;
316 }
317
318 private:
319 Semaphore* sem_ = nullptr;
320 std::atomic<State> state_{State::IDLE};
321 ErrorCode result_ = ErrorCode::OK;
322};
323
324class ReadPort;
325class WritePort;
326
330
334
345typedef ErrorCode (*WriteFun)(WritePort& port, bool in_isr);
346
356typedef ErrorCode (*ReadFun)(ReadPort& port, bool in_isr);
357
367
373
374} // namespace LibXR
Shared BLOCK waiter handoff for synchronous driver operations.
通用回调包装,支持动态参数传递 / Generic callback wrapper supporting dynamic argument passing
Definition libxr_cb.hpp:144
只读原始数据视图 / 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:72
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:81
可写原始数据视图 / 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. 写入操作实例。