-
Notifications
You must be signed in to change notification settings - Fork 48
/
callback.hpp
123 lines (115 loc) · 3.61 KB
/
callback.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#pragma once
#include <cib/builder_meta.hpp>
#include <stdx/compiler.hpp>
#include <array>
#include <concepts>
#include <cstddef>
#include <utility>
namespace callback {
/**
* Builder for simple callbacks.
*
* Components can add their own callback function to this builder to be
* executed when the service is executed with the same function arguments.
*
* @tparam NumFuncs
* The number of functions currently registered with this builder.
*
* @tparam ArgTypes
* List of argument types that must be passed into the callback when it is
* invoked.
*
* @see callback::service
*/
template <int NumFuncs = 0, typename... ArgTypes> struct builder {
using func_ptr_t = void (*)(ArgTypes...);
std::array<func_ptr_t, NumFuncs> funcs{};
/**
* Add a function to be executed when the callback service is invoked.
*
* Do not call this function directly. The library will add functions
* to service builders based on a project's cib::config and cib::extend
* declarations.
*
* @return
* A version of this callback builder with the addition of func.
*
* @see cib::extend
* @see cib::nexus
*/
template <std::convertible_to<func_ptr_t>... Fs>
[[nodiscard]] constexpr auto add(Fs &&...fs) const {
builder<NumFuncs + sizeof...(Fs), ArgTypes...> cb;
auto i = std::size_t{};
while (i < NumFuncs) {
cb.funcs[i] = funcs[i];
++i;
}
((cb.funcs[i++] = std::forward<Fs>(fs)), ...);
return cb;
}
/**
* Build and return a function pointer to the implemented callback
* builder. Used by cib nexus to automatically build an initialized
* builder.
*
* Do not call directly.
*
* @tparam BuilderValue
* Struct that contains a "static constexpr auto value" field with the
* initialized builder.
*
* @return
* Function pointer to the implemented callback service.
*/
template <typename BuilderValue>
[[nodiscard]] CONSTEVAL static auto build() {
return run<BuilderValue>;
}
private:
/**
* Runtime implementation of a callback service.
*
* Calls each registered function in an undefined order. The order
* functions are called should not be depended upon and could
* change from one release to the next.
*
* This function will be available from nexus::builder<...> or
* cib::built<...>.
*
* @tparam BuilderValue
* A type that contains a constexpr static value field with the
* fully initialized callback builder.
*
* @param args
* The arguments to be passed to every registered function.
*
* @see cib::nexus
* @see cib::built
*/
template <typename BuilderValue> static void run(ArgTypes... args) {
constexpr auto handler_builder = BuilderValue::value;
[&]<std::size_t... Is>(std::index_sequence<Is...>) {
(handler_builder.funcs[Is](args...), ...);
}(std::make_index_sequence<NumFuncs>{});
}
};
/**
* Extend this to create named callback services.
*
* Types that extend callback_meta can be used as unique names with
* cib::exports and cib::extend.
*
* @tparam ArgTypes
* The function arguments that must be passed into the callback
* services implementation. any_t function registered with this
* callback service must also have a compatible signature.
*
* @see cib::exports
* @see cib::extend
*/
template <typename... ArgTypes>
struct service
: public cib::builder_meta<builder<0, ArgTypes...>, void (*)(ArgTypes...)> {
};
} // namespace callback