libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
libxr_cb.hpp
1#pragma once
2
3#include <concepts>
4#include <cstring>
5#include <tuple>
6#include <type_traits>
7#include <utility>
8
9#include "libxr_def.hpp"
10
11namespace LibXR
12{
13
18template <typename CallableType, typename BoundArgType, typename... CallbackArgs>
19concept CallbackFunctionCompatible = requires(CallableType callable) {
20 static_cast<void (*)(bool, BoundArgType, CallbackArgs...)>(callable);
21};
22
23template <typename... Args>
25{
26 using InvokeFunType = void (*)(void*, bool, Args...);
27
28 InvokeFunType run_fun_ = nullptr;
29};
30
38template <typename ArgType, typename... Args>
39class CallbackBlock : public CallbackBlockHeader<Args...>
40{
41 public:
45 using FunctionType = void (*)(bool, ArgType, Args...);
46
54 CallbackBlock(FunctionType fun, ArgType&& arg)
55 : CallbackBlockHeader<Args...>{&InvokeThunk}, fun_(fun), arg_(std::move(arg))
56 {
57 ASSERT(fun_ != nullptr);
58 }
59
63 CallbackBlock(const CallbackBlock& other) = delete;
64 CallbackBlock& operator=(const CallbackBlock& other) = delete;
65
66 static void InvokeThunk(void* cb_block, bool in_isr, Args... args)
67 {
68 auto* cb = static_cast<CallbackBlock<ArgType, Args...>*>(cb_block);
69 cb->Invoke(in_isr, std::forward<Args>(args)...);
70 }
71
72 protected:
73 void Invoke(bool in_isr, Args... args)
74 {
75 fun_(in_isr, arg_, std::forward<Args>(args)...);
76 }
77
79 ArgType arg_;
80};
81
82template <typename ArgType, typename... Args>
83class GuardedCallbackBlock : public CallbackBlock<ArgType, Args...>
84{
85 public:
95 ArgType&& arg)
96 : CallbackBlock<ArgType, Args...>(fun, std::move(arg))
97 {
98 this->run_fun_ = &InvokeThunk;
99 }
100
101 static void InvokeThunk(void* cb_block, bool in_isr, Args... args)
102 {
103 auto* cb = static_cast<GuardedCallbackBlock<ArgType, Args...>*>(cb_block);
104
105 if (!cb->running_)
106 {
107 cb->running_ = true;
108 auto cur_args = std::tuple<std::decay_t<Args>...>{std::forward<Args>(args)...};
109 do
110 {
111 cb->pending_ = false;
112 std::apply([&](auto&... a) { cb->Invoke(in_isr, a...); }, cur_args);
113 if (cb->pending_)
114 {
115 cur_args = std::move(cb->pending_args_);
116 }
117 } while (cb->pending_);
118 cb->running_ = false;
119 return;
120 }
121
122 // 重入时只保留最新一组参数,把递归调用压平成串行重放。
123 // On reentry, keep only the latest argument pack so recursive callback chains are
124 // flattened into serialized replay.
125 cb->pending_args_ = std::tuple<std::decay_t<Args>...>{std::forward<Args>(args)...};
126 cb->pending_ = true;
127 }
128
129 private:
130 bool running_ = false;
131 bool pending_ = false;
132 std::tuple<std::decay_t<Args>...> pending_args_{};
133};
134
141template <typename... Args>
143{
144 static void FunctionDefault(void*, bool, Args...) {}
145 inline static CallbackBlockHeader<Args...> empty_cb_block_ = {&FunctionDefault};
146
147 public:
164 template <typename BoundArgType, typename CallableType>
165 requires CallbackFunctionCompatible<CallableType, BoundArgType, Args...>
166 [[nodiscard]] static Callback Create(CallableType fun, BoundArgType arg)
167 {
168 using FunctionType = typename CallbackBlock<BoundArgType, Args...>::FunctionType;
169 auto cb_block = new CallbackBlock<BoundArgType, Args...>(
170 static_cast<FunctionType>(fun), std::move(arg));
171 return Callback(cb_block);
172 }
173
188 template <typename BoundArgType, typename CallableType>
189 requires CallbackFunctionCompatible<CallableType, BoundArgType, Args...>
190 [[nodiscard]] static Callback CreateGuarded(CallableType fun, BoundArgType arg)
191 {
192 using FunctionType = typename CallbackBlock<BoundArgType, Args...>::FunctionType;
193 auto cb_block = new GuardedCallbackBlock<BoundArgType, Args...>(
194 static_cast<FunctionType>(fun), std::move(arg));
195 return Callback(cb_block);
196 }
197
201 Callback() : cb_block_(&empty_cb_block_) {}
202
203 Callback(const Callback&) = default;
204 Callback& operator=(const Callback&) = default;
205
212 Callback(Callback&& other) noexcept
213 : cb_block_(std::exchange(other.cb_block_, &empty_cb_block_))
214 {
215 }
216
224 Callback& operator=(Callback&& other) noexcept
225 {
226 if (this != &other)
227 {
228 cb_block_ = std::exchange(other.cb_block_, &empty_cb_block_);
229 }
230 return *this;
231 }
232
233 template <typename... PassArgs>
234 void Run(bool in_isr, PassArgs&&... args) const
235 {
236 cb_block_->run_fun_(cb_block_, in_isr, std::forward<PassArgs>(args)...);
237 }
238
245 bool Empty() const { return cb_block_ == &empty_cb_block_; }
246
247 private:
255 : cb_block_((cb_block != nullptr) ? cb_block : &empty_cb_block_)
256 {
257 }
258
260 &empty_cb_block_;
261};
262
263} // namespace LibXR
回调函数封装块,提供参数绑定与擦除调用入口 / Callback block with bound argument and erased invoke entry
Definition libxr_cb.hpp:40
void(*)(bool, ArgType, Args...) FunctionType
回调函数类型定义 / Callback function type definition
Definition libxr_cb.hpp:45
CallbackBlock(const CallbackBlock &other)=delete
禁用拷贝构造与拷贝赋值 / Copy construction and copy assignment are disabled
FunctionType fun_
绑定的回调函数 / Bound callback function
Definition libxr_cb.hpp:78
ArgType arg_
绑定的参数 / Bound argument
Definition libxr_cb.hpp:79
CallbackBlock(FunctionType fun, ArgType &&arg)
构造回调块,绑定回调函数与参数 / Construct a callback block with bound function and argument
Definition libxr_cb.hpp:54
通用回调包装,支持动态参数传递 / Generic callback wrapper supporting dynamic argument passing
Definition libxr_cb.hpp:143
Callback & operator=(Callback &&other) noexcept
移动赋值运算符,转移回调对象的所有权 / Move assignment operator transferring callback ownership
Definition libxr_cb.hpp:224
static Callback Create(CallableType fun, BoundArgType arg)
创建回调对象并绑定回调函数与参数 / Create a callback instance with bound function and argument
Definition libxr_cb.hpp:166
Callback(CallbackBlockHeader< Args... > *cb_block)
私有构造函数,仅用于内部创建回调实例 / Private constructor used internally to create callback instances
Definition libxr_cb.hpp:254
static Callback CreateGuarded(CallableType fun, BoundArgType arg)
创建带防重入保护的回调 / Create a guarded callback
Definition libxr_cb.hpp:190
Callback(Callback &&other) noexcept
移动构造函数,转移回调对象的所有权 / Move constructor transferring callback ownership
Definition libxr_cb.hpp:212
bool Empty() const
检查回调是否为空 / Check whether the callback is empty
Definition libxr_cb.hpp:245
CallbackBlockHeader< Args... > * cb_block_
回调块指针 / Pointer to the callback block
Definition libxr_cb.hpp:259
Callback()
默认构造函数,创建空回调对象 / Default constructor creating an empty callback
Definition libxr_cb.hpp:201
GuardedCallbackBlock(typename CallbackBlock< ArgType, Args... >::FunctionType fun, ArgType &&arg)
带防重入保护的回调块 / Callback block with reentry guard
Definition libxr_cb.hpp:94
可转换为精确回调函数指针的可调用对象
Definition libxr_cb.hpp:19
LibXR 命名空间
Definition ch32_can.hpp:14