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{
21 static_cast<void (*)(bool, BoundArgType, CallbackArgs...)>(callable);
22};
23
24template <typename... Args>
26{
27 using InvokeFunType = void (*)(void*, bool, Args...);
28
29 InvokeFunType run_fun_ = nullptr;
30};
31
39template <typename ArgType, typename... Args>
40class CallbackBlock : public CallbackBlockHeader<Args...>
41{
42 public:
46 using FunctionType = void (*)(bool, ArgType, Args...);
47
55 CallbackBlock(FunctionType fun, ArgType&& arg)
56 : CallbackBlockHeader<Args...>{&InvokeThunk}, fun_(fun), arg_(std::move(arg))
57 {
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 if (!fun_)
76 {
77 return;
78 }
79 fun_(in_isr, arg_, std::forward<Args>(args)...);
80 }
81
83 ArgType arg_;
84};
85
86template <typename ArgType, typename... Args>
87class GuardedCallbackBlock : public CallbackBlock<ArgType, Args...>
88{
89 public:
94 ArgType&& arg)
95 : CallbackBlock<ArgType, Args...>(fun, std::move(arg))
96 {
97 this->run_fun_ = &InvokeThunk;
98 }
99
100 static void InvokeThunk(void* cb_block, bool in_isr, Args... args)
101 {
102 auto* cb = static_cast<GuardedCallbackBlock<ArgType, Args...>*>(cb_block);
103
104 if (!cb->running_)
105 {
106 cb->running_ = true;
107 auto cur_args = std::tuple<std::decay_t<Args>...>{std::forward<Args>(args)...};
108 do
109 {
110 cb->pending_ = false;
111 std::apply([&](auto&... a) { cb->Invoke(in_isr, a...); }, cur_args);
112 if (cb->pending_)
113 {
114 cur_args = cb->pending_args_;
115 }
116 } while (cb->pending_);
117 cb->running_ = false;
118 return;
119 }
120
121 // 重入时只保留最新一组参数,把递归调用压平成串行重放。
122 // On reentry, keep only the latest argument pack so recursive callback chains are
123 // flattened into serialized replay.
124 cb->pending_args_ = std::tuple<std::decay_t<Args>...>{std::forward<Args>(args)...};
125 cb->pending_ = true;
126 }
127
128 private:
129 bool running_ = false;
130 bool pending_ = false;
131 std::tuple<std::decay_t<Args>...> pending_args_{};
132};
133
140template <typename... Args>
142{
143 static void FunctionDefault(void*, bool, Args...) {}
144 inline static CallbackBlockHeader<Args...> empty_cb_block_ = {&FunctionDefault};
145
146 public:
157 template <typename BoundArgType, typename CallableType>
158 requires CallbackFunctionCompatible<CallableType, BoundArgType, Args...>
159 [[nodiscard]] static Callback Create(CallableType fun, BoundArgType arg)
160 {
161 using FunctionType = typename CallbackBlock<BoundArgType, Args...>::FunctionType;
162 auto cb_block =
163 new CallbackBlock<BoundArgType, Args...>(static_cast<FunctionType>(fun),
164 std::move(arg));
165 return Callback(cb_block);
166 }
167
177 template <typename BoundArgType, typename CallableType>
178 requires CallbackFunctionCompatible<CallableType, BoundArgType, Args...>
179 [[nodiscard]] static Callback CreateGuarded(CallableType fun, BoundArgType arg)
180 {
181 using FunctionType = typename CallbackBlock<BoundArgType, Args...>::FunctionType;
182 auto cb_block =
183 new GuardedCallbackBlock<BoundArgType, Args...>(static_cast<FunctionType>(fun),
184 std::move(arg));
185 return Callback(cb_block);
186 }
187
191 Callback() : cb_block_(&empty_cb_block_) {}
192
193 Callback(const Callback&) = default;
194 Callback& operator=(const Callback&) = default;
195
202 Callback(Callback&& other) noexcept
203 : cb_block_(std::exchange(other.cb_block_, &empty_cb_block_))
204 {
205 }
206
214 Callback& operator=(Callback&& other) noexcept
215 {
216 if (this != &other)
217 {
218 cb_block_ = std::exchange(other.cb_block_, &empty_cb_block_);
219 }
220 return *this;
221 }
222
223 template <typename... PassArgs>
224 void Run(bool in_isr, PassArgs&&... args) const
225 {
226 cb_block_->run_fun_(cb_block_, in_isr, std::forward<PassArgs>(args)...);
227 }
228
235 bool Empty() const { return cb_block_ == &empty_cb_block_; }
236
237 private:
245 : cb_block_((cb_block != nullptr) ? cb_block : &empty_cb_block_)
246 {
247 }
248
250 &empty_cb_block_;
251};
252
253} // namespace LibXR
回调函数封装块,提供参数绑定与擦除调用入口 / Callback block with bound argument and erased invoke entry
Definition libxr_cb.hpp:41
void(*)(bool, ArgType, Args...) FunctionType
回调函数类型定义 / Callback function type definition
Definition libxr_cb.hpp:46
CallbackBlock(const CallbackBlock &other)=delete
禁用拷贝构造与拷贝赋值 / Copy construction and copy assignment are disabled
FunctionType fun_
绑定的回调函数 / Bound callback function
Definition libxr_cb.hpp:82
ArgType arg_
绑定的参数 / Bound argument
Definition libxr_cb.hpp:83
CallbackBlock(FunctionType fun, ArgType &&arg)
构造回调块,绑定回调函数与参数 / Construct a callback block with bound function and argument
Definition libxr_cb.hpp:55
通用回调包装,支持动态参数传递 / Generic callback wrapper supporting dynamic argument passing
Definition libxr_cb.hpp:142
Callback & operator=(Callback &&other) noexcept
移动赋值运算符,转移回调对象的所有权 / Move assignment operator transferring callback ownership
Definition libxr_cb.hpp:214
static Callback Create(CallableType fun, BoundArgType arg)
创建回调对象并绑定回调函数与参数 / Create a callback instance with bound function and argument
Definition libxr_cb.hpp:159
Callback(CallbackBlockHeader< Args... > *cb_block)
私有构造函数,仅用于内部创建回调实例 / Private constructor used internally to create callback instances
Definition libxr_cb.hpp:244
static Callback CreateGuarded(CallableType fun, BoundArgType arg)
创建带防重入保护的回调 / Create a guarded callback
Definition libxr_cb.hpp:179
Callback(Callback &&other) noexcept
移动构造函数,转移回调对象的所有权 / Move constructor transferring callback ownership
Definition libxr_cb.hpp:202
bool Empty() const
检查回调是否为空 / Check whether the callback is empty
Definition libxr_cb.hpp:235
CallbackBlockHeader< Args... > * cb_block_
回调块指针 / Pointer to the callback block
Definition libxr_cb.hpp:249
Callback()
默认构造函数,创建空回调对象 / Default constructor creating an empty callback
Definition libxr_cb.hpp:191
GuardedCallbackBlock(typename CallbackBlock< ArgType, Args... >::FunctionType fun, ArgType &&arg)
带防重入保护的回调块 / Callback block with reentry guard
Definition libxr_cb.hpp:93
可转换为精确回调函数指针的可调用对象
Definition libxr_cb.hpp:19
LibXR 命名空间
Definition ch32_can.hpp:14