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
52template <
typename Signature>
61template <
typename M,
class C>
73template <
typename R,
typename... Args>
74struct unqualify_fn<R(Args...)> : mstd::type_identity<R(Args...)> { };
75template <
typename R,
typename... Args>
76struct unqualify_fn<R(Args...) &> : mstd::type_identity<R(Args...)> { };
77template <
typename R,
typename... Args>
78struct unqualify_fn<R(Args...) const> : mstd::type_identity<R(Args...)> { };
79template <
typename R,
typename... Args>
80struct unqualify_fn<R(Args...) const &> : mstd::type_identity<R(Args...)> { };
81template <
typename R,
typename... Args>
82struct unqualify_fn<R(Args...) volatile> : mstd::type_identity<R(Args...)> { };
83template <
typename R,
typename... Args>
84struct unqualify_fn<R(Args...) volatile &> : mstd::type_identity<R(Args...)> { };
85template <
typename R,
typename... Args>
86struct unqualify_fn<R(Args...) const volatile> : mstd::type_identity<R(Args...)> { };
87template <
typename R,
typename... Args>
88struct unqualify_fn<R(Args...) const volatile &> : mstd::type_identity<R(Args...)> { };
89#if __cplusplus >=201703 || __cpp_noexcept_function_type >= 201510
92template <
typename R,
typename... Args>
93struct unqualify_fn<R(Args...) noexcept> : mstd::type_identity<R(Args...)> { };
94template <
typename R,
typename... Args>
95struct unqualify_fn<R(Args...) &
noexcept> : mstd::type_identity<R(Args...)> { };
96template <
typename R,
typename... Args>
97struct unqualify_fn<R(Args...) const noexcept> : mstd::type_identity<R(Args...)> { };
98template <
typename R,
typename... Args>
99struct unqualify_fn<R(Args...) const &
noexcept> : mstd::type_identity<R(Args...)> { };
100template <
typename R,
typename... Args>
101struct unqualify_fn<R(Args...) volatile noexcept> : mstd::type_identity<R(Args...)> { };
102template <
typename R,
typename... Args>
103struct unqualify_fn<R(Args...) volatile &
noexcept> : mstd::type_identity<R(Args...)> { };
104template <
typename R,
typename... Args>
105struct unqualify_fn<R(Args...) const volatile noexcept> : mstd::type_identity<R(Args...)> { };
106template <
typename R,
typename... Args>
107struct unqualify_fn<R(Args...) const volatile &
noexcept> : mstd::type_identity<R(Args...)> { };
113template <
typename R,
typename F,
typename... Args,
typename std::enable_if_t<!std::is_void<R>::value,
int> = 0>
114R invoke_r(F&& f, Args&&... args)
116 return mstd::invoke(std::forward<F>(f), std::forward<Args>(args)...);
119template <
typename R,
typename F,
typename... Args,
typename std::enable_if_t<std::is_void<R>::value,
int> = 0>
120R 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) { }
207 CallbackBase() =
default;
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
248 void copy(
const CallbackBase &other)
252 _ops->copy(_storage, other._storage);
256 void swap(CallbackBase &other)
noexcept
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
310template <
typename R,
typename... ArgTs>
313 using result_type = R;
323#if MBED_CONF_PLATFORM_CALLBACK_NONTRIVIAL
335 Callback(Callback &&other) : CallbackBase()
342 Callback(
const Callback &other) =
default;
343 Callback(Callback &&other) =
default;
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
446 Callback &operator=(Callback &&that)
456 Callback &operator=(
const Callback &that) =
default;
457 Callback &operator=(Callback &&that) =
default;
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>,
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");
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)...);
664using event_callback_t = Callback<void(
int)>;
666template <
typename R,
typename... ArgTs>
667void swap(Callback<R(ArgTs...)> &lhs, Callback<R(ArgTs...)> &rhs)
noexcept
677template <
typename R,
typename... ArgTs>
688template <
typename R,
typename... ArgTs>
699template <
typename R,
typename... ArgTs>
702 return Callback<R(ArgTs...)>(std::move(func));
711template<
typename T,
typename U,
typename R,
typename... ArgTs>
714 return Callback<R(ArgTs...)>(obj, method);
717template<
typename T,
typename U,
typename R,
typename... ArgTs>
718Callback<R(ArgTs...)>
callback(U *obj, R(T::*method)(ArgTs...) &) noexcept
720 return Callback<R(ArgTs...)>(obj, method);
723template<
typename T,
typename U,
typename R,
typename... ArgTs>
724Callback<R(ArgTs...)>
callback(
const U *obj, R(T::*method)(ArgTs...)
const) noexcept
726 return Callback<R(ArgTs...)>(obj, method);
729template<
typename T,
typename U,
typename R,
typename... ArgTs>
730Callback<R(ArgTs...)>
callback(
const U *obj, R(T::*method)(ArgTs...)
const &) noexcept
732 return Callback<R(ArgTs...)>(obj, method);
735template<
typename T,
typename U,
typename R,
typename... ArgTs>
736Callback<R(ArgTs...)>
callback(
volatile U *obj, R(T::*method)(ArgTs...)
volatile) noexcept
738 return Callback<R(ArgTs...)>(obj, method);
741template<
typename T,
typename U,
typename R,
typename... ArgTs>
742Callback<R(ArgTs...)>
callback(
volatile U *obj, R(T::*method)(ArgTs...)
volatile &) noexcept
744 return Callback<R(ArgTs...)>(obj, method);
747template<
typename T,
typename U,
typename R,
typename... ArgTs>
748Callback<R(ArgTs...)>
callback(
const volatile U *obj, R(T::*method)(ArgTs...)
const volatile) noexcept
750 return Callback<R(ArgTs...)>(obj, method);
753template<
typename T,
typename U,
typename R,
typename... ArgTs>
754Callback<R(ArgTs...)>
callback(
const volatile U *obj, R(T::*method)(ArgTs...)
const volatile &) noexcept
756 return Callback<R(ArgTs...)>(obj, method);
765template <
typename T,
typename U,
typename R,
typename... ArgTs>
768 return Callback<R(ArgTs...)>(func, arg);
771template <
typename T,
typename U,
typename R,
typename... ArgTs>
772Callback<R(ArgTs...)>
callback(R(*func)(
const T *, ArgTs...),
const U *arg)
noexcept
774 return Callback<R(ArgTs...)>(func, arg);
777template <
typename T,
typename U,
typename R,
typename... ArgTs>
778Callback<R(ArgTs...)>
callback(R(*func)(
volatile T *, ArgTs...),
volatile U *arg)
noexcept
780 return Callback<R(ArgTs...)>(func, arg);
783template <
typename T,
typename U,
typename R,
typename... ArgTs>
784Callback<R(ArgTs...)>
callback(R(*func)(
const volatile T *, ArgTs...),
const volatile U *arg)
noexcept
786 return Callback<R(ArgTs...)>(func, arg);
794Callback<detail::unqualify_fn_t<detail::member_type_t<
decltype(&mstd::remove_cvref_t<F>::operator())>>>
797 return Callback<detail::unqualify_fn_t<detail::member_type_t<
decltype(&mstd::remove_cvref_t<F>::operator())>>>(std::forward<F>(f));
800#if __cplusplus >= 201703 || __cpp_deduction_guides >= 201703
802template <
typename R,
typename... Args>
803Callback(R(*)(Args...)) -> Callback<R(Args...)>;
805Callback(F) -> Callback<detail::unqualify_fn_t<detail::member_type_t<
decltype(&F::operator())>>>;
806template <
typename T,
typename U,
typename R,
typename... ArgTs>
807Callback(U *obj, R(T::*method)(ArgTs...)) -> Callback<R(ArgTs...)>;
808template <
typename T,
typename U,
typename R,
typename... ArgTs>
809Callback(U *obj, R(T::*method)(ArgTs...) &) -> Callback<R(ArgTs...)>;
810template <
typename T,
typename U,
typename R,
typename... ArgTs>
811Callback(
const U *obj, R(T::*method)(ArgTs...)
const) -> Callback<R(ArgTs...)>;
812template <
typename T,
typename U,
typename R,
typename... ArgTs>
813Callback(
const U *obj, R(T::*method)(ArgTs...)
const &) -> Callback<R(ArgTs...)>;
814template <
typename T,
typename U,
typename R,
typename... ArgTs>
815Callback(
volatile U *obj, R(T::*method)(ArgTs...)
volatile) -> Callback<R(ArgTs...)>;
816template <
typename T,
typename U,
typename R,
typename... ArgTs>
817Callback(
volatile U *obj, R(T::*method)(ArgTs...)
volatile &) -> Callback<R(ArgTs...)>;
818template <
typename T,
typename U,
typename R,
typename... ArgTs>
819Callback(
const volatile U *obj, R(T::*method)(ArgTs...)
const volatile) -> Callback<R(ArgTs...)>;
820template <
typename T,
typename U,
typename R,
typename... ArgTs>
821Callback(
const volatile U *obj, R(T::*method)(ArgTs...)
const volatile &) -> Callback<R(ArgTs...)>;
822template <
typename T,
typename U,
typename R,
typename... ArgTs>
823Callback(R(*func)(T *, ArgTs...), U *arg) -> Callback<R(ArgTs...)>;
824template <
typename T,
typename U,
typename R,
typename... ArgTs>
825Callback(R(*func)(
const T *, ArgTs...),
const U *arg) -> Callback<R(ArgTs...)>;
826template <
typename T,
typename U,
typename R,
typename... ArgTs>
827Callback(R(*func)(
volatile T *, ArgTs...),
volatile U *arg) -> Callback<R(ArgTs...)>;
828template <
typename T,
typename U,
typename R,
typename... ArgTs>
829Callback(R(*func)(
const volatile T *, ArgTs...),
const volatile U *arg) -> Callback<R(ArgTs...)>;
Callback(Fn func, BoundArg arg)
Create a Callback with a static function and bound pointer.
void swap(Callback &that) noexcept
Swap a callback.
Callback(std::nullptr_t) noexcept
Create an empty Callback.
friend bool operator==(const Callback &f, std::nullptr_t) noexcept
Test for emptiness.
R call(ArgTs... args) const
Call the attached function.
Callback & operator=(F &&f)
Assign a callback.
~Callback()=default
Destroy a callback.
Callback & operator=(std::nullptr_t) noexcept
Empty a callback.
friend bool operator!=(std::nullptr_t, const Callback &f) noexcept
Test for non-emptiness.
Callback() noexcept
Create an empty Callback.
friend bool operator==(std::nullptr_t, const Callback &f) noexcept
Test for emptiness.
Callback(Obj obj, Method method)
Create a Callback with a member function.
R operator()(ArgTs... args) const
Call the attached function.
Callback(F f)
Create a Callback with a function object.
friend bool operator!=(const Callback &f, std::nullptr_t) noexcept
Test for non-emptiness.
static R thunk(void *func, ArgTs... args)
Static thunk for passing as C-style function.
Callback class based on template specialization.
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.