roo_threads
API Documentation for roo_threads
Loading...
Searching...
No Matches
callable.h
Go to the documentation of this file.
1#pragma once
2
3#include <functional>
4#include <memory>
5#include <utility>
6
8
9#ifdef ROO_THREADS_USE_FREERTOS
10
11namespace roo_threads {
12namespace freertos {
13
14template <size_t... Indexes>
15struct IndexTuple {
16 typedef IndexTuple<Indexes..., sizeof...(Indexes)> next;
17};
18
19template <std::size_t N>
20struct BuildIndexTuple {
21 typedef typename BuildIndexTuple<N - 1>::type::next type;
22};
23
24template <>
25struct BuildIndexTuple<0> {
26 typedef IndexTuple<> type;
27};
28
29template <typename Tuple>
30struct Invoker {
31 Tuple tuple;
32
33 template <size_t Index>
34 static std::tuple_element_t<Index, Tuple>&& DeclVal();
35
36 template <size_t... Ind>
37 auto invoke(IndexTuple<Ind...>) noexcept(
38 noexcept(std::invoke(DeclVal<Ind>()...)))
39 -> decltype(std::invoke(DeclVal<Ind>()...)) {
40 return std::invoke(std::get<Ind>(std::move(tuple))...);
41 }
42
43 using Indices = typename BuildIndexTuple<std::tuple_size<Tuple>::value>::type;
44
45 auto operator()() noexcept(
46 noexcept(std::declval<Invoker&>().invoke(Indices())))
47 -> decltype(std::declval<Invoker&>().invoke(Indices())) {
48 return invoke(Indices());
49 }
50};
51
52template <typename... Tp>
53using DecayedTuple = std::tuple<typename std::decay<Tp>::type...>;
54
55template <typename Callable, typename... Args>
56inline Invoker<DecayedTuple<Callable, Args...>> MakeInvoker(Callable&& callable,
57 Args&&... args) {
58 return {DecayedTuple<Callable, Args...>{std::forward<Callable>(callable),
59 std::forward<Args>(args)...}};
60}
61
62class VirtualCallable {
63 public:
64 virtual ~VirtualCallable() = default;
65 virtual void call() = 0;
66};
67
68template <typename Callable>
69class DynamicCallable : public VirtualCallable {
70 public:
71 DynamicCallable(Callable&& callable)
72 : callable_(std::forward<Callable>(callable)) {}
73
74 void call() override { callable_(); }
75
76 private:
77 Callable callable_;
78};
79
80template <typename Callable>
81static std::unique_ptr<VirtualCallable> MakeDynamicCallable(
82 Callable&& callable) {
83 return std::unique_ptr<VirtualCallable>{
84 new DynamicCallable<Callable>{std::forward<Callable>(callable)}};
85}
86
87// Given the callable and the arguments that should be bound to it, returns
88// an instance of the VirtualCallable that invokes that callable and calls the
89// arguments, using perfect forwarding and pass-by-reference.
90template <typename Callable, typename... Args>
91static std::unique_ptr<VirtualCallable> MakeDynamicCallableWithArgs(
92 Callable&& callable, Args&&... args) {
93 return MakeDynamicCallable(MakeInvoker(std::forward<Callable>(callable),
94 std::forward<Args>(args)...));
95}
96
97} // namespace freertos
98} // namespace roo_threads
99
100#endif // ROO_THREADS_USE_FREERTOS