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.