libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
callback.hpp
1#pragma once
2
3#include <new>
4
5#include "../topic.hpp"
6#include "libxr_def.hpp"
7
8namespace LibXR
9{
16{
23 template <typename Function>
25
33 template <typename Return, typename... Args>
34 struct FunctionTraits<Return (*)(Args...)>
35 {
36 using ReturnType = Return;
37 static constexpr size_t ARITY = sizeof...(Args);
38
43 template <size_t Index>
44 using Arg = std::tuple_element_t<Index, std::tuple<Args...>>;
45 };
46
53 template <typename T>
55 {
56 static constexpr bool VALUE =
57 false;
58 };
59
67 template <typename Data>
69 {
70 static constexpr bool VALUE =
71 true;
72 using DataType =
73 Data;
74 };
75
81 template <typename T>
82 using RemoveCVRef = std::remove_cv_t<std::remove_reference_t<T>>;
83
89 template <typename T>
90 static constexpr bool IS_MESSAGE_VIEW = MessageViewTraits<
91 RemoveCVRef<T>>::VALUE;
94
100 template <typename T>
101 static constexpr bool IS_RAW_DATA_VIEW = std::same_as<RemoveCVRef<T>, ConstRawData> ||
102 std::same_as<RemoveCVRef<T>, RawMessageView>;
103
109 template <typename T>
110 static constexpr bool IS_TYPED_DATA =
115
121 template <typename T>
122 static constexpr bool IS_CALLBACK_PAYLOAD =
126
132 template <typename T>
133 static constexpr bool IS_MUTABLE_MESSAGE_VIEW_REF =
134 IS_MESSAGE_VIEW<T> && std::is_lvalue_reference_v<T> &&
135 !std::is_const_v<std::remove_reference_t<T>>;
136
151 {
152 using RunFun = void (*)(const BlockHeader*, bool, MicrosecondTimestamp, void*,
153 size_t);
155
156 RunFun run = nullptr;
157 TypeID::ID payload_type_id = nullptr;
159 bool accepts_raw_payload = false;
161 };
162
169 template <typename PayloadArg>
170 static TypeID::ID PayloadTypeID()
171 {
173 "LibXR::Topic::Callback does not accept MessageView<T>&; "
174 "use MessageView<T> or const MessageView<T>& instead.");
175
176 if constexpr (IS_RAW_DATA_VIEW<PayloadArg>)
177 {
178 return nullptr;
179 }
180 else if constexpr (IS_MESSAGE_VIEW<PayloadArg>)
181 {
184 }
185 else
186 {
187 static_assert(IS_TYPED_DATA<PayloadArg>,
188 "LibXR::Topic::Callback payload must be Topic::MessageView<T>, "
189 "Topic::RawMessageView, ConstRawData, T, T&, or const T&.");
191 }
192 }
193
200 template <typename PayloadArg>
201 static constexpr bool AcceptsRawPayload()
202 {
204 }
205
220 template <typename Function, typename BoundArg, typename PayloadArg>
221 static void InvokePayload(Function fun, BoundArg& arg, bool in_isr,
222 MicrosecondTimestamp timestamp, void* payload_addr,
223 size_t payload_size)
224 {
225 if constexpr (std::same_as<RemoveCVRef<PayloadArg>, ConstRawData>)
226 {
227 ConstRawData raw_payload{payload_addr, payload_size};
228 fun(in_isr, arg, raw_payload);
229 }
230 else if constexpr (std::same_as<RemoveCVRef<PayloadArg>, RawMessageView>)
231 {
232 RawMessageView raw_message{timestamp, ConstRawData{payload_addr, payload_size}};
233 fun(in_isr, arg, raw_message);
234 }
235 else if constexpr (IS_MESSAGE_VIEW<PayloadArg>)
236 {
238 using Data = typename View::DataType;
239 fun(in_isr, arg,
240 MessageView<Data>{timestamp, reinterpret_cast<Data*>(payload_addr)});
241 }
242 else
243 {
244 using Data = RemoveCVRef<PayloadArg>;
245 fun(in_isr, arg, *reinterpret_cast<Data*>(payload_addr));
246 }
247 }
248
256 template <typename Function, typename BoundArg, typename PayloadArg>
258 {
265 PayloadOnlyBlock(Function fun, BoundArg&& arg)
266 : BlockHeader{&Run, PayloadTypeID<PayloadArg>(), AcceptsRawPayload<PayloadArg>()},
267 fun_(fun),
268 arg_(std::move(arg))
269 {
270 }
271
281 static void Run(const BlockHeader* header, bool in_isr,
282 MicrosecondTimestamp timestamp, void* payload_addr,
283 size_t payload_size)
284 {
285 auto* block = static_cast<const PayloadOnlyBlock*>(header);
287 block->fun_, const_cast<BoundArg&>(block->arg_), in_isr, timestamp,
288 payload_addr, payload_size);
289 }
290
291 Function fun_;
292 BoundArg arg_;
293 };
294
303 template <typename Function, typename BoundArg, typename PayloadArg>
305 {
312 TimestampPayloadBlock(Function fun, BoundArg&& arg)
313 : BlockHeader{&Run, PayloadTypeID<PayloadArg>(), AcceptsRawPayload<PayloadArg>()},
314 fun_(fun),
315 arg_(std::move(arg))
316 {
317 }
318
328 static void Run(const BlockHeader* header, bool in_isr,
329 MicrosecondTimestamp timestamp, void* payload_addr,
330 size_t payload_size)
331 {
332 auto* block = static_cast<const TimestampPayloadBlock*>(header);
333 if constexpr (std::same_as<RemoveCVRef<PayloadArg>, ConstRawData>)
334 {
335 ConstRawData raw_payload{payload_addr, payload_size};
336 block->fun_(in_isr, block->arg_, timestamp, raw_payload);
337 }
338 else if constexpr (std::same_as<RemoveCVRef<PayloadArg>, RawMessageView>)
339 {
340 RawMessageView raw_message{timestamp, ConstRawData{payload_addr, payload_size}};
341 block->fun_(in_isr, block->arg_, timestamp, raw_message);
342 }
343 else if constexpr (IS_MESSAGE_VIEW<PayloadArg>)
344 {
346 using Data = typename View::DataType;
347 block->fun_(in_isr, block->arg_, timestamp,
348 MessageView<Data>{timestamp, reinterpret_cast<Data*>(payload_addr)});
349 }
350 else
351 {
352 using Data = RemoveCVRef<PayloadArg>;
353 block->fun_(in_isr, block->arg_, timestamp,
354 *reinterpret_cast<Data*>(payload_addr));
355 }
356 }
357
358 Function fun_;
359 BoundArg arg_;
360 };
361
370 template <typename Function, typename BoundArg, size_t Arity>
371 struct Factory
372 {
373 static_assert(Arity == 3 || Arity == 4,
374 "LibXR::Topic::Callback function must be void(bool, Arg, Payload) "
375 "or void(bool, Arg, MicrosecondTimestamp, Payload).");
376 };
377
384 template <typename Function, typename BoundArg>
385 struct Factory<Function, BoundArg, 3>
386 {
389 typename Traits::template Arg<2>;
392
400 static BlockHeader* Create(Function fun, BoundArg&& arg)
401 {
402 static_assert(std::same_as<typename Traits::ReturnType, void>);
403 static_assert(std::same_as<typename Traits::template Arg<0>, bool>);
404 static_assert(std::same_as<typename Traits::template Arg<1>, BoundArg>);
405 static_assert(IS_CALLBACK_PAYLOAD<PayloadArg>);
406 return new PayloadOnlyBlock<Function, BoundArg, PayloadArg>(fun, std::move(arg));
407 }
408 };
409
416 template <typename Function, typename BoundArg>
417 struct Factory<Function, BoundArg, 4>
418 {
421 typename Traits::template Arg<2>;
425 typename Traits::template Arg<3>;
428
436 static BlockHeader* Create(Function fun, BoundArg&& arg)
437 {
438 static_assert(std::same_as<typename Traits::ReturnType, void>);
439 static_assert(std::same_as<typename Traits::template Arg<0>, bool>);
440 static_assert(std::same_as<typename Traits::template Arg<1>, BoundArg>);
441 static_assert(std::same_as<RemoveCVRef<TimestampArg>, MicrosecondTimestamp>);
442 static_assert(IS_CALLBACK_PAYLOAD<PayloadArg>);
444 std::move(arg));
445 }
446 };
447
456 static void EmptyRun(const BlockHeader* header, bool in_isr,
457 MicrosecondTimestamp timestamp, void* payload_addr,
458 size_t payload_size)
459 {
460 UNUSED(header);
461 UNUSED(in_isr);
462 UNUSED(timestamp);
463 UNUSED(payload_addr);
464 UNUSED(payload_size);
465 }
466
468 &EmptyRun, nullptr, false};
470
471 public:
475 Callback() = default;
476
484 Callback(const Callback& other) = default;
485
494 Callback& operator=(const Callback& other) = default;
495
507 template <typename BoundArg, typename Callable>
508 [[nodiscard]] static Callback Create(Callable fun, BoundArg arg)
509 {
510 using Function = decltype(+std::declval<Callable>());
511 using Traits = FunctionTraits<Function>;
512 static_assert(Traits::ARITY == 3 || Traits::ARITY == 4,
513 "LibXR::Topic::Callback::Create expects a capture-free callable "
514 "with bool and bound-argument parameters.");
515 return Callback(
517 }
518
526 void Run(bool in_isr, MicrosecondTimestamp timestamp, void* payload_addr,
527 size_t payload_size) const
528 {
529 block_->run(block_, in_isr, timestamp, payload_addr, payload_size);
530 }
531
537 TypeID::ID PayloadTypeID() const { return block_->payload_type_id; }
538
546
547 private:
554 explicit Callback(BlockHeader* block) : block_(block ? block : &empty_block_) {}
555
558};
559
566{
573 CallbackBlock(Callback& callback, size_t topic_payload_size)
574 : cb(callback), payload_size(topic_payload_size)
575 {
577 }
578
586 void Run(bool in_isr, MicrosecondTimestamp timestamp, void* payload_addr) const
587 {
588 cb.Run(in_isr, timestamp, payload_addr, payload_size);
589 }
590
592
594 size_t payload_size = 0;
595};
596
607{
608 if (!cb.IsRawPayloadView())
609 {
610 ASSERT(block_->data_.payload_type_id == cb.PayloadTypeID());
611 }
612
613 auto node = new (std::align_val_t(LibXR::CONCURRENCY_ALIGNMENT))
615 block_->data_.subers.Add(*node);
616}
617} // namespace LibXR
只读原始数据视图 / Immutable raw data view
数据节点模板,继承自 BaseNode,用于存储具体数据类型。 Template data node that inherits from BaseNode to store specific data...
微秒时间戳 / Microsecond timestamp
Data data_
存储的数据 (Stored data).
Definition rbt.hpp:98
每次发布时直接执行函数的订阅句柄 / Subscription handle that runs a function on each publish
Definition callback.hpp:16
static constexpr bool IS_MESSAGE_VIEW
是否为带时间戳的类型化消息视图参数 / Whether one callback payload argument is a timestamped typed message view
Definition callback.hpp:90
void Run(bool in_isr, MicrosecondTimestamp timestamp, void *payload_addr, size_t payload_size) const
执行回调 / Run the callback
Definition callback.hpp:526
static void InvokePayload(Function fun, BoundArg &arg, bool in_isr, MicrosecondTimestamp timestamp, void *payload_addr, size_t payload_size)
按回调声明的参数形式,把当前消息拼成实参再调函数 / Build the actual call arguments from the current message in the form decla...
Definition callback.hpp:221
static void EmptyRun(const BlockHeader *header, bool in_isr, MicrosecondTimestamp timestamp, void *payload_addr, size_t payload_size)
空回调块的执行函数 / Execution function of the empty callback block
Definition callback.hpp:456
bool IsRawPayloadView() const
判断该回调是否按 raw payload 视图接收消息 / Tell whether this callback receives messages as a raw payload view
Definition callback.hpp:545
Callback & operator=(const Callback &other)=default
拷贝赋值回调句柄 / Copy-assign one callback handle
static constexpr bool IS_CALLBACK_PAYLOAD
是否是回调接口允许的 payload 参数写法 / Whether one payload argument form is accepted by this callback interface
Definition callback.hpp:122
Callback(const Callback &other)=default
拷贝构造回调句柄 / Copy-construct one callback handle
Callback(BlockHeader *block)
用指定执行块构造回调句柄 / Construct one callback handle from the given execution block
Definition callback.hpp:554
static constexpr bool IS_MUTABLE_MESSAGE_VIEW_REF
是否错误地使用了可变 MessageView<T>& / Whether one payload argument is an invalid mutable MessageView<T>&
Definition callback.hpp:133
static Callback Create(Callable fun, BoundArg arg)
创建一个回调订阅句柄 / Create a callback subscription handle
Definition callback.hpp:508
static BlockHeader empty_block_
Definition callback.hpp:467
Callback()=default
构造一个空回调句柄 / Construct one empty callback handle
TypeID::ID PayloadTypeID() const
读取这个回调句柄期望的 payload 类型标识 / Read the payload type ID expected by this callback handle
Definition callback.hpp:537
std::remove_cv_t< std::remove_reference_t< T > > RemoveCVRef
去掉引用和 cv 限定后的规范类型 / Canonical type after removing reference and cv qualifiers
Definition callback.hpp:82
static constexpr bool IS_RAW_DATA_VIEW
是否为只读 raw payload 视图参数 / Whether one callback payload argument is a read-only raw payload view
Definition callback.hpp:101
static constexpr bool AcceptsRawPayload()
回调 payload 参数是否是 raw 字节视图 / Whether the callback payload argument is a raw byte view
Definition callback.hpp:201
static constexpr bool IS_TYPED_DATA
是否把 payload 直接当成一个对象接收 / Whether one callback payload argument receives the payload directly as one o...
Definition callback.hpp:110
BlockHeader * block_
Definition callback.hpp:556
static TypeID::ID PayloadTypeID()
取回调 payload 参数对应的精确类型标识 / Get the exact type ID expected by one callback payload argument
Definition callback.hpp:170
@ CALLBACK
回调执行型订阅者。Callback-executing subscriber.
TopicHandle block_
Definition topic.hpp:610
void RegisterCallback(Callback &cb)
注册一个回调订阅者 / Register one callback subscriber
Definition callback.hpp:606
static ID GetID()
获取类型的唯一标识符 / Get a unique identifier for type T
topic 可承载 payload 的类型约束 / Type constraint for payloads carried by one topic
Definition topic.hpp:27
LibXR 命名空间
Definition ch32_can.hpp:14
constexpr size_t CONCURRENCY_ALIGNMENT
并发结构对齐粒度(用于降低多核伪共享) / Alignment policy used by concurrency-oriented structures
Definition libxr_def.hpp:62
回调句柄真正指向的那块数据的公共头 / Common header of the data block actually pointed to by one callback handle
Definition callback.hpp:151
void(*)(const BlockHeader *, bool, MicrosecondTimestamp, void *, size_t) RunFun
Definition callback.hpp:152
RunFun run
当前块的执行函数。Execution function of the current block.
Definition callback.hpp:156
typename Traits::template Arg< 2 > PayloadArg
Definition callback.hpp:388
static BlockHeader * Create(Function fun, BoundArg &&arg)
创建只转发负载的回调块 / Create one callback block that forwards only the payload
Definition callback.hpp:400
static BlockHeader * Create(Function fun, BoundArg &&arg)
创建同时转发时间戳和负载的回调块 / Create one callback block that forwards both timestamp and payload
Definition callback.hpp:436
typename Traits::template Arg< 3 > PayloadArg
Definition callback.hpp:424
typename Traits::template Arg< 2 > TimestampArg
Definition callback.hpp:420
看回调有几个参数,决定分配哪种回调块 / Choose which callback block to allocate from the callback parameter count
Definition callback.hpp:372
std::tuple_element_t< Index, std::tuple< Args... > > Arg
取出指定下标的参数类型 / Fetch the argument type at the given index
Definition callback.hpp:44
Return ReturnType
回调返回类型。Callback return type.
Definition callback.hpp:36
把一个无捕获回调函数拆成返回类型和参数类型 / Split one callback function without captures into its return type and paramet...
Definition callback.hpp:24
Data DataType
MessageView 对应的数据类型。Payload type behind the MessageView.
Definition callback.hpp:72
判断某个参数是否为 MessageView<T> / Tell whether one argument is MessageView<T>
Definition callback.hpp:55
static constexpr bool VALUE
默认不是 MessageView。Not a MessageView by default.
Definition callback.hpp:56
只转发负载的回调块 / Callback block that forwards only the payload
Definition callback.hpp:258
BoundArg arg_
绑定到回调中的参数副本。Stored copy of the bound argument.
Definition callback.hpp:292
Function fun_
目标回调函数。Target callback function.
Definition callback.hpp:291
PayloadOnlyBlock(Function fun, BoundArg &&arg)
构造一个只转发负载的具体回调块 / Construct one concrete callback block that forwards only the payload
Definition callback.hpp:265
static void Run(const BlockHeader *header, bool in_isr, MicrosecondTimestamp timestamp, void *payload_addr, size_t payload_size)
根据块头指针取回具体块并执行回调 / Recover the concrete block from the block header pointer and run the callback
Definition callback.hpp:281
同时转发时间戳和负载的回调块 / Callback block that forwards both timestamp and payload
Definition callback.hpp:305
BoundArg arg_
绑定到回调中的参数副本。Stored copy of the bound argument.
Definition callback.hpp:359
Function fun_
目标回调函数。Target callback function.
Definition callback.hpp:358
static void Run(const BlockHeader *header, bool in_isr, MicrosecondTimestamp timestamp, void *payload_addr, size_t payload_size)
根据块头指针取回具体块并执行带时间戳回调 / Recover the concrete block from the block header pointer and run the timestamp...
Definition callback.hpp:328
TimestampPayloadBlock(Function fun, BoundArg &&arg)
构造一个同时转发时间戳和负载的具体回调块 / Construct one concrete callback block that forwards both timestamp and payload
Definition callback.hpp:312
挂在 topic 订阅链表里的回调记录 / Callback record stored in the topic subscriber list
Definition callback.hpp:566
size_t payload_size
注册到的 topic 固定 payload 字节数。Fixed payload size of the subscribed topic.
Definition callback.hpp:594
Callback cb
订阅的回调句柄。Subscribed callback handle.
Definition callback.hpp:591
void Run(bool in_isr, MicrosecondTimestamp timestamp, void *payload_addr) const
通过注册时绑定的 topic payload size 执行回调 / Run the callback with the topic payload size bound at registration...
Definition callback.hpp:586
CallbackBlock(Callback &callback, size_t topic_payload_size)
构造一个回调订阅块 / Construct one callback subscriber block
Definition callback.hpp:573
带时间戳和 payload 指针的只读消息视图 / Read-only message view carrying a timestamp and a payload pointer
Definition topic.hpp:135
带时间戳和只读原始 payload 视图的消息 / Message carrying a timestamp and a read-only raw payload view
Definition topic.hpp:154
所有订阅块共用的公共头 / Common header shared by all subscriber blocks
Definition topic.hpp:237
SuberType type
订阅块的具体种类。Concrete kind of this subscriber block.
Definition topic.hpp:238