17 #ifndef MBED_CALLBACK_H 18 #define MBED_CALLBACK_H 21 #include <mstd_cstddef> 24 #include "platform/mbed_assert.h" 25 #include "platform/mbed_toolchain.h" 26 #include <mstd_type_traits> 27 #include <mstd_functional> 35 #undef MBED_CONF_PLATFORM_CALLBACK_NONTRIVIAL 36 #define MBED_CONF_PLATFORM_CALLBACK_NONTRIVIAL 1 52 template <
typename Signature>
61 template <
typename M,
class C>
73 template <
typename R,
typename... Args>
74 struct unqualify_fn<R(Args...)> : mstd::type_identity<R(Args...)> { };
75 template <
typename R,
typename... Args>
76 struct unqualify_fn<R(Args...) &> : mstd::type_identity<R(Args...)> { };
77 template <
typename R,
typename... Args>
78 struct unqualify_fn<R(Args...) const> : mstd::type_identity<R(Args...)> { };
79 template <
typename R,
typename... Args>
80 struct unqualify_fn<R(Args...) const &> : mstd::type_identity<R(Args...)> { };
81 template <
typename R,
typename... Args>
82 struct unqualify_fn<R(Args...) volatile> : mstd::type_identity<R(Args...)> { };
83 template <
typename R,
typename... Args>
84 struct unqualify_fn<R(Args...) volatile &> : mstd::type_identity<R(Args...)> { };
85 template <
typename R,
typename... Args>
86 struct unqualify_fn<R(Args...) const volatile> : mstd::type_identity<R(Args...)> { };
87 template <
typename R,
typename... Args>
88 struct unqualify_fn<R(Args...) const volatile &> : mstd::type_identity<R(Args...)> { };
89 #if __cplusplus >=201703 || __cpp_noexcept_function_type >= 201510 92 template <
typename R,
typename... Args>
93 struct unqualify_fn<R(Args...) noexcept> : mstd::type_identity<R(Args...)> { };
94 template <
typename R,
typename... Args>
95 struct unqualify_fn<R(Args...) & noexcept> : mstd::type_identity<R(Args...)> { };
96 template <
typename R,
typename... Args>
97 struct unqualify_fn<R(Args...) const noexcept> : mstd::type_identity<R(Args...)> { };
98 template <
typename R,
typename... Args>
99 struct unqualify_fn<R(Args...) const & noexcept> : mstd::type_identity<R(Args...)> { };
100 template <
typename R,
typename... Args>
101 struct unqualify_fn<R(Args...) volatile noexcept> : mstd::type_identity<R(Args...)> { };
102 template <
typename R,
typename... Args>
103 struct unqualify_fn<R(Args...) volatile & noexcept> : mstd::type_identity<R(Args...)> { };
104 template <
typename R,
typename... Args>
105 struct unqualify_fn<R(Args...) const volatile noexcept> : mstd::type_identity<R(Args...)> { };
106 template <
typename R,
typename... Args>
107 struct unqualify_fn<R(Args...) const volatile & noexcept> : mstd::type_identity<R(Args...)> { };
110 template <
typename T>
113 template <
typename R,
typename F,
typename... Args,
typename std::enable_if_t<!std::is_void<R>::value,
int> = 0>
114 R invoke_r(F&& f, Args&&... args)
116 return mstd::invoke(std::forward<F>(f), std::forward<Args>(args)...);
119 template <
typename R,
typename F,
typename... Args,
typename std::enable_if_t<std::is_void<R>::value,
int> = 0>
120 R invoke_r(F&& f, Args&&... args)
122 mstd::invoke(std::forward<F>(f), std::forward<Args>(args)...);
128 std::is_function<std::remove_pointer_t<F>>,
129 std::is_member_pointer<F>
139 void (_class::*_methodfunc)(int);
179 struct alignas(_model_function_object) [[gnu::may_alias]]
Store {
184 #if MBED_CONF_PLATFORM_CALLBACK_NONTRIVIAL 189 void (*dtor)(
Store &);
193 using Control =
const ops *;
196 CallbackBase(std::nullptr_t) noexcept : _ops(
nullptr) { }
200 using Control = void(*)();
203 CallbackBase(std::nullptr_t) noexcept : _call(
nullptr) { }
211 #if MBED_CONF_PLATFORM_CALLBACK_NONTRIVIAL 218 const Control &control()
const 220 #if MBED_CONF_PLATFORM_CALLBACK_NONTRIVIAL 229 #if MBED_CONF_PLATFORM_CALLBACK_NONTRIVIAL 237 void clear() noexcept
246 #if MBED_CONF_PLATFORM_CALLBACK_NONTRIVIAL 252 _ops->copy(_storage, other._storage);
258 std::swap(_storage, other._storage);
259 std::swap(_call, other._call);
267 #if MBED_CONF_PLATFORM_CALLBACK_NONTRIVIAL 269 _ops->dtor(_storage);
274 #if MBED_CONF_PLATFORM_CALLBACK_NONTRIVIAL 276 template <
typename F>
277 static void target_copy(
Store &d,
const Store &p)
279 const F &f =
reinterpret_cast<const F &
>(p);
284 template <
typename F>
285 static void target_dtor(
Store &p)
287 F &f =
reinterpret_cast<F &
>(p);
292 static void trivial_target_copy(
Store &d,
const Store &p) noexcept
294 std::memcpy(&d, &p,
sizeof d);
298 static void trivial_target_dtor(
Store &p) noexcept
310 template <
typename R,
typename... ArgTs>
313 using result_type = R;
323 #if MBED_CONF_PLATFORM_CALLBACK_NONTRIVIAL 341 #else // MBED_CONF_PLATFORM_CALLBACK_NONTRIVIAL 344 #endif // MBED_CONF_PLATFORM_CALLBACK_NONTRIVIAL 350 template<
typename Obj,
typename Method,
typename std::enable_if_t<mstd::is_invocable_r<R, Method, Obj, ArgTs...>::value,
int> = 0>
353 generate([obj, method](ArgTs... args) {
354 return detail::invoke_r<R>(method, obj, std::forward<ArgTs>(args)...);
362 template<
typename Fn,
typename BoundArg,
typename std::enable_if_t<mstd::is_invocable_r<R, Fn, BoundArg, ArgTs...>::value,
int> = 0>
365 generate([func, arg](ArgTs... args) {
366 return detail::invoke_r<R>(func, arg, std::forward<ArgTs>(args)...);
375 template <
typename F,
376 typename std::enable_if_t<
378 mstd::is_invocable_r<R, F, ArgTs...>::value,
int> = 0>
381 static_assert(std::is_copy_constructible<F>::value,
"Callback F must be CopyConstructible");
382 generate(std::move(f));
388 template <
typename F,
389 typename std::enable_if_t<
391 mstd::is_invocable_r<R, F, ArgTs...>::value,
int> = 0>
394 static_assert(std::is_copy_constructible<F>::value,
"Callback F must be CopyConstructible");
398 generate(std::move(f));
405 #if MBED_CONF_PLATFORM_CALLBACK_NONTRIVIAL 418 #if MBED_CONF_PLATFORM_CALLBACK_NONTRIVIAL 421 *
this = std::move(that);
422 that = std::move(temp);
425 CallbackBase::swap(that);
429 #if MBED_CONF_PLATFORM_CALLBACK_NONTRIVIAL 455 #else // MBED_CONF_PLATFORM_CALLBACK_NONTRIVIAL 458 #endif // MBED_CONF_PLATFORM_CALLBACK_NONTRIVIAL 468 template <
typename F,
469 typename = std::enable_if_t<
470 mstd::is_invocable_r<R, F, ArgTs...>::value &&
471 !mstd::is_same<mstd::remove_cvref_t<F>,
Callback>::value>>
477 new (
this)
Callback(std::forward<F>(f));
482 template <
typename F>
483 Callback &operator=(std::reference_wrapper<F> f) noexcept
507 auto op_call =
reinterpret_cast<call_type *
>(call_fn());
508 return op_call(
this, args...);
515 return call(args...);
520 explicit operator bool() const noexcept
525 #if MBED_CONF_PLATFORM_CALLBACK_COMPARABLE 539 if (l.control() != r.control()) {
550 return memcmp(&l._storage, &r._storage,
sizeof(
Store)) == 0;
568 #if MBED_CONF_PLATFORM_CALLBACK_COMPARABLE 599 static R
thunk(
void *func, ArgTs... args)
601 return static_cast<Callback *
>(func)->call(args...);
605 using call_type = R(
const CallbackBase *, ArgTs...);
611 template <typename F, typename = std::enable_if_t<!std::is_lvalue_reference<F>::value>>
615 static_assert(std::is_same<decltype(target_call<F>), call_type>::value,
"Call type mismatch");
617 static_assert(
sizeof(
Callback) ==
sizeof(CallbackBase),
"Callback should be same size as CallbackBase");
618 static_assert(std::is_trivially_copyable<CallbackBase>::value,
"CallbackBase expected to be TriviallyCopyable");
621 #if MBED_CONF_PLATFORM_CALLBACK_NONTRIVIAL 626 static const ops ops = {
627 reinterpret_cast<void (*)()
>(target_call<F>),
628 std::is_trivially_copy_constructible<F>::value ? trivial_target_copy : target_copy<F>,
629 std::is_trivially_destructible<F>::value ? trivial_target_dtor : target_dtor<F>,
632 #else // MBED_CONF_PLATFORM_CALLBACK_NONTRIVIAL 634 _call =
reinterpret_cast<void (*)()
>(target_call<F>);
635 static_assert(std::is_trivially_copyable<F>::value,
"F must be TriviallyCopyable. Turn on Mbed configuration option 'platform.callback-nontrivial' to use more complex function objects");
636 static_assert(std::is_trivially_copyable<Callback>::value,
"Callback expected to be TriviallyCopyable");
637 #endif // MBED_CONF_PLATFORM_CALLBACK_NONTRIVIAL 640 static_assert(
sizeof(F) <=
sizeof(
Store) &&
alignof(F) <=
alignof(
Store),
641 "Type F must not exceed the size of the Callback class");
642 new (&_storage) F(std::move(f));
644 #if MBED_CONF_PLATFORM_CALLBACK_COMPARABLE 646 if (
sizeof(F) <
sizeof(
Store)) {
647 std::memset(reinterpret_cast<char *>(&_storage) +
sizeof(F), 0,
sizeof(
Store) -
sizeof(F));
654 template <
typename F>
655 static R target_call(
const CallbackBase *p, ArgTs... args)
658 F &f =
const_cast<F &
>(
reinterpret_cast<const F &
>(p->_storage));
659 return detail::invoke_r<R>(f, std::forward<ArgTs>(args)...);
666 template <
typename R,
typename... ArgTs>
677 template <
typename R,
typename... ArgTs>
688 template <
typename R,
typename... ArgTs>
699 template <
typename R,
typename... ArgTs>
702 return Callback<R(ArgTs...)>(std::move(func));
711 template<
typename T,
typename U,
typename R,
typename... ArgTs>
714 return Callback<R(ArgTs...)>(obj, method);
717 template<
typename T,
typename U,
typename R,
typename... ArgTs>
720 return Callback<R(ArgTs...)>(obj, method);
723 template<
typename T,
typename U,
typename R,
typename... ArgTs>
724 Callback<R(ArgTs...)>
callback(
const U *obj, R(T::*method)(ArgTs...)
const) noexcept
726 return Callback<R(ArgTs...)>(obj, method);
729 template<
typename T,
typename U,
typename R,
typename... ArgTs>
730 Callback<R(ArgTs...)>
callback(
const U *obj, R(T::*method)(ArgTs...)
const &) noexcept
732 return Callback<R(ArgTs...)>(obj, method);
735 template<
typename T,
typename U,
typename R,
typename... ArgTs>
736 Callback<R(ArgTs...)>
callback(
volatile U *obj, R(T::*method)(ArgTs...)
volatile) noexcept
738 return Callback<R(ArgTs...)>(obj, method);
741 template<
typename T,
typename U,
typename R,
typename... ArgTs>
742 Callback<R(ArgTs...)>
callback(
volatile U *obj, R(T::*method)(ArgTs...)
volatile &) noexcept
744 return Callback<R(ArgTs...)>(obj, method);
747 template<
typename T,
typename U,
typename R,
typename... ArgTs>
748 Callback<R(ArgTs...)>
callback(
const volatile U *obj, R(T::*method)(ArgTs...)
const volatile) noexcept
750 return Callback<R(ArgTs...)>(obj, method);
753 template<
typename T,
typename U,
typename R,
typename... ArgTs>
754 Callback<R(ArgTs...)>
callback(
const volatile U *obj, R(T::*method)(ArgTs...)
const volatile &) noexcept
756 return Callback<R(ArgTs...)>(obj, method);
765 template <
typename T,
typename U,
typename R,
typename... ArgTs>
768 return Callback<R(ArgTs...)>(func, arg);
771 template <
typename T,
typename U,
typename R,
typename... ArgTs>
772 Callback<R(ArgTs...)>
callback(R(*func)(
const T *, ArgTs...),
const U *arg) noexcept
774 return Callback<R(ArgTs...)>(func, arg);
777 template <
typename T,
typename U,
typename R,
typename... ArgTs>
778 Callback<R(ArgTs...)>
callback(R(*func)(
volatile T *, ArgTs...),
volatile U *arg) noexcept
780 return Callback<R(ArgTs...)>(func, arg);
783 template <
typename T,
typename U,
typename R,
typename... ArgTs>
784 Callback<R(ArgTs...)>
callback(R(*func)(
const volatile T *, ArgTs...),
const volatile U *arg) noexcept
786 return Callback<R(ArgTs...)>(func, arg);
793 template <
typename F>
800 #if __cplusplus >= 201703 || __cpp_deduction_guides >= 201703 802 template <
typename R,
typename... Args>
804 template <
typename F>
806 template <
typename T,
typename U,
typename R,
typename... ArgTs>
808 template <
typename T,
typename U,
typename R,
typename... ArgTs>
810 template <
typename T,
typename U,
typename R,
typename... ArgTs>
811 Callback(
const U *obj, R(T::*method)(ArgTs...)
const) ->
Callback<R(ArgTs...)>;
812 template <
typename T,
typename U,
typename R,
typename... ArgTs>
813 Callback(
const U *obj, R(T::*method)(ArgTs...)
const &) ->
Callback<R(ArgTs...)>;
814 template <
typename T,
typename U,
typename R,
typename... ArgTs>
815 Callback(
volatile U *obj, R(T::*method)(ArgTs...)
volatile) ->
Callback<R(ArgTs...)>;
816 template <
typename T,
typename U,
typename R,
typename... ArgTs>
817 Callback(
volatile U *obj, R(T::*method)(ArgTs...)
volatile &) ->
Callback<R(ArgTs...)>;
818 template <
typename T,
typename U,
typename R,
typename... ArgTs>
819 Callback(
const volatile U *obj, R(T::*method)(ArgTs...)
const volatile) ->
Callback<R(ArgTs...)>;
820 template <
typename T,
typename U,
typename R,
typename... ArgTs>
821 Callback(
const volatile U *obj, R(T::*method)(ArgTs...)
const volatile &) ->
Callback<R(ArgTs...)>;
822 template <
typename T,
typename U,
typename R,
typename... ArgTs>
824 template <
typename T,
typename U,
typename R,
typename... ArgTs>
825 Callback(R(*func)(
const T *, ArgTs...),
const U *arg) ->
Callback<R(ArgTs...)>;
826 template <
typename T,
typename U,
typename R,
typename... ArgTs>
827 Callback(R(*func)(
volatile T *, ArgTs...),
volatile U *arg) ->
Callback<R(ArgTs...)>;
828 template <
typename T,
typename U,
typename R,
typename... ArgTs>
829 Callback(R(*func)(
const volatile T *, ArgTs...),
const volatile U *arg) ->
Callback<R(ArgTs...)>;
R call(ArgTs...args) const
Call the attached function.
Callback(std::nullptr_t) noexcept
Create an empty Callback.
static R thunk(void *func, ArgTs...args)
Static thunk for passing as C-style function.
Callback(F f)
Create a Callback with a function object.
Callback() noexcept
Create an empty Callback.
Callback(Fn func, BoundArg arg)
Create a Callback with a static function and bound pointer.
friend bool operator==(std::nullptr_t, const Callback &f) noexcept
Test for emptiness.
Callback & operator=(std::nullptr_t) noexcept
Empty a callback.
friend bool operator!=(const Callback &f, std::nullptr_t) noexcept
Test for non-emptiness.
friend bool operator!=(std::nullptr_t, const Callback &f) noexcept
Test for non-emptiness.
Callback & operator=(F &&f)
Assign a callback.
void operator!=(const SafeBool< T > &lhs, const SafeBool< U > &rhs)
Avoid conversion to bool between different classes.
void operator==(const SafeBool< T > &lhs, const SafeBool< U > &rhs)
Avoid conversion to bool between different classes.
void swap(Callback &that) noexcept
Swap a callback.
Callback(Obj obj, Method method)
Create a Callback with a member function.
R operator()(ArgTs...args) const
Call the attached function.
Callback class based on template specialization.
friend bool operator==(const Callback &f, std::nullptr_t) noexcept
Test for emptiness.