From c71e67f2dcf2a75c225fbecf16921949100ca6c9 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Fri, 19 Aug 2016 15:49:49 -0500 Subject: [PATCH] Updated minor functionality of the Callback class - Marked `call` and `operator()` functions as const - Moved to static_cast for internal function pointer to avoid losing compiler checked const-safety - Added test for `operator=` with non-callback types - Moved from zero-cast to value-initializer when callback is null - Added `operator==` and `operator!=` - Removed special handling of null callback - Replicated doxygen to all overloads - Added correct nops where uninitialized callbacks are called - Added assertion for null callback - Removed copy-constructor from callback constructor --- TESTS/mbed_drivers/callback/main.cpp | 120 +-- hal/api/Callback.h | 1259 +++++++++++++++++++++----- hal/api/FunctionPointer.h | 24 + hal/common/CAN.cpp | 8 + hal/common/InterruptIn.cpp | 10 +- hal/common/SerialBase.cpp | 7 + 6 files changed, 1100 insertions(+), 328 deletions(-) diff --git a/TESTS/mbed_drivers/callback/main.cpp b/TESTS/mbed_drivers/callback/main.cpp index d4f0e9af57..403968a039 100644 --- a/TESTS/mbed_drivers/callback/main.cpp +++ b/TESTS/mbed_drivers/callback/main.cpp @@ -203,20 +203,14 @@ void test_dispatch0() { Verifier::verify0((volatile Thing*)&thing, &volatile_func0); Verifier::verify0((const volatile Thing*)&thing, &const_volatile_func0); Verifier::verify0(callback(static_func0)); - Verifier::verify0(callback(&thing, &Thing::member_func0)); - Verifier::verify0(callback((const Thing*)&thing, &Thing::const_member_func0)); - Verifier::verify0(callback((volatile Thing*)&thing, &Thing::volatile_member_func0)); - Verifier::verify0(callback((const volatile Thing*)&thing, &Thing::const_volatile_member_func0)); - Verifier::verify0(callback(&thing, &bound_func0)); - Verifier::verify0(callback((const Thing*)&thing, &const_func0)); - Verifier::verify0(callback((volatile Thing*)&thing, &volatile_func0)); - Verifier::verify0(callback((const volatile Thing*)&thing, &const_volatile_func0)); - Callback callback(static_func0); - Verifier::verify0(callback); - callback.attach(&thing, &bound_func0); - Verifier::verify0(&callback, &Callback::call); - Verifier::verify0((void*)&callback, &Callback::thunk); + Callback cb(static_func0); + Verifier::verify0(cb); + cb = static_func0; + Verifier::verify0(cb); + cb.attach(&thing, &bound_func0); + Verifier::verify0(&cb, &Callback::call); + Verifier::verify0((void*)&cb, &Callback::thunk); } template @@ -232,20 +226,14 @@ void test_dispatch1() { Verifier::verify1((volatile Thing*)&thing, &volatile_func1); Verifier::verify1((const volatile Thing*)&thing, &const_volatile_func1); Verifier::verify1(callback(static_func1)); - Verifier::verify1(callback(&thing, &Thing::member_func1)); - Verifier::verify1(callback((const Thing*)&thing, &Thing::const_member_func1)); - Verifier::verify1(callback((volatile Thing*)&thing, &Thing::volatile_member_func1)); - Verifier::verify1(callback((const volatile Thing*)&thing, &Thing::const_volatile_member_func1)); - Verifier::verify1(callback(&thing, &bound_func1)); - Verifier::verify1(callback((const Thing*)&thing, &const_func1)); - Verifier::verify1(callback((volatile Thing*)&thing, &volatile_func1)); - Verifier::verify1(callback((const volatile Thing*)&thing, &const_volatile_func1)); - Callback callback(static_func1); - Verifier::verify1(callback); - callback.attach(&thing, &bound_func1); - Verifier::verify1(&callback, &Callback::call); - Verifier::verify1((void*)&callback, &Callback::thunk); + Callback cb(static_func1); + Verifier::verify1(cb); + cb = static_func1; + Verifier::verify1(cb); + cb.attach(&thing, &bound_func1); + Verifier::verify1(&cb, &Callback::call); + Verifier::verify1((void*)&cb, &Callback::thunk); } template @@ -261,20 +249,14 @@ void test_dispatch2() { Verifier::verify2((volatile Thing*)&thing, &volatile_func2); Verifier::verify2((const volatile Thing*)&thing, &const_volatile_func2); Verifier::verify2(callback(static_func2)); - Verifier::verify2(callback(&thing, &Thing::member_func2)); - Verifier::verify2(callback((const Thing*)&thing, &Thing::const_member_func2)); - Verifier::verify2(callback((volatile Thing*)&thing, &Thing::volatile_member_func2)); - Verifier::verify2(callback((const volatile Thing*)&thing, &Thing::const_volatile_member_func2)); - Verifier::verify2(callback(&thing, &bound_func2)); - Verifier::verify2(callback((const Thing*)&thing, &const_func2)); - Verifier::verify2(callback((volatile Thing*)&thing, &volatile_func2)); - Verifier::verify2(callback((const volatile Thing*)&thing, &const_volatile_func2)); - Callback callback(static_func2); - Verifier::verify2(callback); - callback.attach(&thing, &bound_func2); - Verifier::verify2(&callback, &Callback::call); - Verifier::verify2((void*)&callback, &Callback::thunk); + Callback cb(static_func2); + Verifier::verify2(cb); + cb = static_func2; + Verifier::verify2(cb); + cb.attach(&thing, &bound_func2); + Verifier::verify2(&cb, &Callback::call); + Verifier::verify2((void*)&cb, &Callback::thunk); } template @@ -290,20 +272,14 @@ void test_dispatch3() { Verifier::verify3((volatile Thing*)&thing, &volatile_func3); Verifier::verify3((const volatile Thing*)&thing, &const_volatile_func3); Verifier::verify3(callback(static_func3)); - Verifier::verify3(callback(&thing, &Thing::member_func3)); - Verifier::verify3(callback((const Thing*)&thing, &Thing::const_member_func3)); - Verifier::verify3(callback((volatile Thing*)&thing, &Thing::volatile_member_func3)); - Verifier::verify3(callback((const volatile Thing*)&thing, &Thing::const_volatile_member_func3)); - Verifier::verify3(callback(&thing, &bound_func3)); - Verifier::verify3(callback((const Thing*)&thing, &const_func3)); - Verifier::verify3(callback((volatile Thing*)&thing, &volatile_func3)); - Verifier::verify3(callback((const volatile Thing*)&thing, &const_volatile_func3)); - Callback callback(static_func3); - Verifier::verify3(callback); - callback.attach(&thing, &bound_func3); - Verifier::verify3(&callback, &Callback::call); - Verifier::verify3((void*)&callback, &Callback::thunk); + Callback cb(static_func3); + Verifier::verify3(cb); + cb = static_func3; + Verifier::verify3(cb); + cb.attach(&thing, &bound_func3); + Verifier::verify3(&cb, &Callback::call); + Verifier::verify3((void*)&cb, &Callback::thunk); } template @@ -319,20 +295,14 @@ void test_dispatch4() { Verifier::verify4((volatile Thing*)&thing, &volatile_func4); Verifier::verify4((const volatile Thing*)&thing, &const_volatile_func4); Verifier::verify4(callback(static_func4)); - Verifier::verify4(callback(&thing, &Thing::member_func4)); - Verifier::verify4(callback((const Thing*)&thing, &Thing::const_member_func4)); - Verifier::verify4(callback((volatile Thing*)&thing, &Thing::volatile_member_func4)); - Verifier::verify4(callback((const volatile Thing*)&thing, &Thing::const_volatile_member_func4)); - Verifier::verify4(callback(&thing, &bound_func4)); - Verifier::verify4(callback((const Thing*)&thing, &const_func4)); - Verifier::verify4(callback((volatile Thing*)&thing, &volatile_func4)); - Verifier::verify4(callback((const volatile Thing*)&thing, &const_volatile_func4)); - Callback callback(static_func4); - Verifier::verify4(callback); - callback.attach(&thing, &bound_func4); - Verifier::verify4(&callback, &Callback::call); - Verifier::verify4((void*)&callback, &Callback::thunk); + Callback cb(static_func4); + Verifier::verify4(cb); + cb = static_func4; + Verifier::verify4(cb); + cb.attach(&thing, &bound_func4); + Verifier::verify4(&cb, &Callback::call); + Verifier::verify4((void*)&cb, &Callback::thunk); } template @@ -348,20 +318,14 @@ void test_dispatch5() { Verifier::verify5((volatile Thing*)&thing, &volatile_func5); Verifier::verify5((const volatile Thing*)&thing, &const_volatile_func5); Verifier::verify5(callback(static_func5)); - Verifier::verify5(callback(&thing, &Thing::member_func5)); - Verifier::verify5(callback((const Thing*)&thing, &Thing::const_member_func5)); - Verifier::verify5(callback((volatile Thing*)&thing, &Thing::volatile_member_func5)); - Verifier::verify5(callback((const volatile Thing*)&thing, &Thing::const_volatile_member_func5)); - Verifier::verify5(callback(&thing, &bound_func5)); - Verifier::verify5(callback((const Thing*)&thing, &const_func5)); - Verifier::verify5(callback((volatile Thing*)&thing, &volatile_func5)); - Verifier::verify5(callback((const volatile Thing*)&thing, &const_volatile_func5)); - Callback callback(static_func5); - Verifier::verify5(callback); - callback.attach(&thing, &bound_func5); - Verifier::verify5(&callback, &Callback::call); - Verifier::verify5((void*)&callback, &Callback::thunk); + Callback cb(static_func5); + Verifier::verify5(cb); + cb = static_func5; + Verifier::verify5(cb); + cb.attach(&thing, &bound_func5); + Verifier::verify5(&cb, &Callback::call); + Verifier::verify5((void*)&cb, &Callback::thunk); } template diff --git a/hal/api/Callback.h b/hal/api/Callback.h index 8a415bb6c4..fa78438655 100644 --- a/hal/api/Callback.h +++ b/hal/api/Callback.h @@ -18,6 +18,7 @@ #include #include +#include "mbed_assert.h" namespace mbed { @@ -29,7 +30,9 @@ namespace mbed { template class Callback; -/** Templated function class +/** Callback class based on template specialization + * + * @Note Synchronization level: Not protected */ template class Callback { @@ -41,13 +44,6 @@ public: attach(func); } - /** Create a Callback with another Callback - * @param func Callback to attach - */ - Callback(const Callback &func) { - attach(func); - } - /** Create a Callback with a static function and bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach @@ -57,16 +53,28 @@ public: attach(obj, func); } + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ template Callback(const T *obj, R (*func)(const T*)) { attach(obj, func); } + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ template Callback(volatile T *obj, R (*func)(volatile T*)) { attach(obj, func); } + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ template Callback(const volatile T *obj, R (*func)(const volatile T*)) { attach(obj, func); @@ -81,16 +89,28 @@ public: attach(obj, func); } + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ template Callback(const T *obj, R (T::*func)() const) { attach(obj, func); } + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ template Callback(volatile T *obj, R (T::*func)() volatile) { attach(obj, func); } + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ template Callback(const volatile T *obj, R (T::*func)() const volatile) { attach(obj, func); @@ -101,13 +121,15 @@ public: */ void attach(R (*func)()) { struct local { - static R _thunk(void*, void *func) { - return (*(R (**)())func)( + static R _thunk(void*, const void *func) { + return (*static_cast(func))( ); } }; + memset(&_func, 0, sizeof _func); memcpy(&_func, &func, sizeof func); + _obj = 0; _thunk = func ? &local::_thunk : 0; } @@ -115,8 +137,9 @@ public: * @param func The Callback to attach */ void attach(const Callback &func) { + memset(&_func, 0, sizeof _func); + memcpy(&_func, &func._func, sizeof func); _obj = func._obj; - memcpy(&_func, &func._func, sizeof _func); _thunk = func._thunk; } @@ -127,56 +150,72 @@ public: template void attach(T *obj, R (*func)(T*)) { struct local { - static R _thunk(void *obj, void *func) { - return (*(R (**)(T*))func)( + static R _thunk(void *obj, const void *func) { + return (*static_cast(func))( (T*)obj); } }; - _obj = (void*)obj; + memset(&_func, 0, sizeof _func); memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; _thunk = &local::_thunk; } + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ template void attach(const T *obj, R (*func)(const T*)) { struct local { - static R _thunk(void *obj, void *func) { - return (*(R (**)(const T*))func)( + static R _thunk(void *obj, const void *func) { + return (*static_cast(func))( (const T*)obj); } }; - _obj = (void*)obj; + memset(&_func, 0, sizeof _func); memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; _thunk = &local::_thunk; } + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ template void attach(volatile T *obj, R (*func)(volatile T*)) { struct local { - static R _thunk(void *obj, void *func) { - return (*(R (**)(volatile T*))func)( + static R _thunk(void *obj, const void *func) { + return (*static_cast(func))( (volatile T*)obj); } }; - _obj = (void*)obj; + memset(&_func, 0, sizeof _func); memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; _thunk = &local::_thunk; } + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ template void attach(const volatile T *obj, R (*func)(const volatile T*)) { struct local { - static R _thunk(void *obj, void *func) { - return (*(R (**)(const volatile T*))func)( + static R _thunk(void *obj, const void *func) { + return (*static_cast(func))( (const volatile T*)obj); } }; - _obj = (void*)obj; + memset(&_func, 0, sizeof _func); memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; _thunk = &local::_thunk; } @@ -187,71 +226,89 @@ public: template void attach(T *obj, R (T::*func)()) { struct local { - static R _thunk(void *obj, void *func) { - return (((T*)obj)->*(*(R (T::**)())func))( + static R _thunk(void *obj, const void *func) { + return (((T*)obj)->* + (*static_cast(func)))( ); } }; - _obj = (void*)obj; + memset(&_func, 0, sizeof _func); memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; _thunk = &local::_thunk; } + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ template void attach(const T *obj, R (T::*func)() const) { struct local { - static R _thunk(void *obj, void *func) { - return (((const T*)obj)->*(*(R (T::**)() const)func))( + static R _thunk(void *obj, const void *func) { + return (((const T*)obj)->* + (*static_cast(func)))( ); } }; - _obj = (void*)obj; + memset(&_func, 0, sizeof _func); memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; _thunk = &local::_thunk; } + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ template void attach(volatile T *obj, R (T::*func)() volatile) { struct local { - static R _thunk(void *obj, void *func) { - return (((volatile T*)obj)->*(*(R (T::**)() volatile)func))( + static R _thunk(void *obj, const void *func) { + return (((volatile T*)obj)->* + (*static_cast(func)))( ); } }; - _obj = (void*)obj; + memset(&_func, 0, sizeof _func); memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; _thunk = &local::_thunk; } + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ template void attach(const volatile T *obj, R (T::*func)() const volatile) { struct local { - static R _thunk(void *obj, void *func) { - return (((const volatile T*)obj)->*(*(R (T::**)() const volatile)func))( + static R _thunk(void *obj, const void *func) { + return (((const volatile T*)obj)->* + (*static_cast(func)))( ); } }; - _obj = (void*)obj; + memset(&_func, 0, sizeof _func); memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; _thunk = &local::_thunk; } /** Call the attached function */ - R call() { - if (!_thunk) { - return (R)0; - } + R call() const { + MBED_ASSERT(_thunk); return _thunk(_obj, &_func); } /** Call the attached function */ - R operator()() { + R operator()() const { return call(); } @@ -261,6 +318,18 @@ public: return _thunk; } + /** Test for equality + */ + friend bool operator==(const Callback &l, const Callback &r) { + return memcmp(&l, &r, sizeof(Callback)) == 0; + } + + /** Test for inequality + */ + friend bool operator!=(const Callback &l, const Callback &r) { + return !(l == r); + } + /** Static thunk for passing as C-style function * @param func Callback to call passed as void pointer */ @@ -283,10 +352,12 @@ private: void *_obj; // Thunk registered on attach to dispatch calls - R (*_thunk)(void*, void*); + R (*_thunk)(void*, const void*); }; -/** Templated function class +/** Callback class based on template specialization + * + * @Note Synchronization level: Not protected */ template class Callback { @@ -298,13 +369,6 @@ public: attach(func); } - /** Create a Callback with another Callback - * @param func Callback to attach - */ - Callback(const Callback &func) { - attach(func); - } - /** Create a Callback with a static function and bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach @@ -314,16 +378,28 @@ public: attach(obj, func); } + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ template Callback(const T *obj, R (*func)(const T*, A0)) { attach(obj, func); } + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ template Callback(volatile T *obj, R (*func)(volatile T*, A0)) { attach(obj, func); } + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ template Callback(const volatile T *obj, R (*func)(const volatile T*, A0)) { attach(obj, func); @@ -338,16 +414,28 @@ public: attach(obj, func); } + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ template Callback(const T *obj, R (T::*func)(A0) const) { attach(obj, func); } + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ template Callback(volatile T *obj, R (T::*func)(A0) volatile) { attach(obj, func); } + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ template Callback(const volatile T *obj, R (T::*func)(A0) const volatile) { attach(obj, func); @@ -358,13 +446,15 @@ public: */ void attach(R (*func)(A0)) { struct local { - static R _thunk(void*, void *func, A0 a0) { - return (*(R (**)(A0))func)( + static R _thunk(void*, const void *func, A0 a0) { + return (*static_cast(func))( a0); } }; + memset(&_func, 0, sizeof _func); memcpy(&_func, &func, sizeof func); + _obj = 0; _thunk = func ? &local::_thunk : 0; } @@ -372,8 +462,9 @@ public: * @param func The Callback to attach */ void attach(const Callback &func) { + memset(&_func, 0, sizeof _func); + memcpy(&_func, &func._func, sizeof func); _obj = func._obj; - memcpy(&_func, &func._func, sizeof _func); _thunk = func._thunk; } @@ -384,56 +475,72 @@ public: template void attach(T *obj, R (*func)(T*, A0)) { struct local { - static R _thunk(void *obj, void *func, A0 a0) { - return (*(R (**)(T*, A0))func)( + static R _thunk(void *obj, const void *func, A0 a0) { + return (*static_cast(func))( (T*)obj, a0); } }; - _obj = (void*)obj; + memset(&_func, 0, sizeof _func); memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; _thunk = &local::_thunk; } + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ template void attach(const T *obj, R (*func)(const T*, A0)) { struct local { - static R _thunk(void *obj, void *func, A0 a0) { - return (*(R (**)(const T*, A0))func)( + static R _thunk(void *obj, const void *func, A0 a0) { + return (*static_cast(func))( (const T*)obj, a0); } }; - _obj = (void*)obj; + memset(&_func, 0, sizeof _func); memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; _thunk = &local::_thunk; } + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ template void attach(volatile T *obj, R (*func)(volatile T*, A0)) { struct local { - static R _thunk(void *obj, void *func, A0 a0) { - return (*(R (**)(volatile T*, A0))func)( + static R _thunk(void *obj, const void *func, A0 a0) { + return (*static_cast(func))( (volatile T*)obj, a0); } }; - _obj = (void*)obj; + memset(&_func, 0, sizeof _func); memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; _thunk = &local::_thunk; } + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ template void attach(const volatile T *obj, R (*func)(const volatile T*, A0)) { struct local { - static R _thunk(void *obj, void *func, A0 a0) { - return (*(R (**)(const volatile T*, A0))func)( + static R _thunk(void *obj, const void *func, A0 a0) { + return (*static_cast(func))( (const volatile T*)obj, a0); } }; - _obj = (void*)obj; + memset(&_func, 0, sizeof _func); memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; _thunk = &local::_thunk; } @@ -444,71 +551,89 @@ public: template void attach(T *obj, R (T::*func)(A0)) { struct local { - static R _thunk(void *obj, void *func, A0 a0) { - return (((T*)obj)->*(*(R (T::**)(A0))func))( + static R _thunk(void *obj, const void *func, A0 a0) { + return (((T*)obj)->* + (*static_cast(func)))( a0); } }; - _obj = (void*)obj; + memset(&_func, 0, sizeof _func); memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; _thunk = &local::_thunk; } + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ template void attach(const T *obj, R (T::*func)(A0) const) { struct local { - static R _thunk(void *obj, void *func, A0 a0) { - return (((const T*)obj)->*(*(R (T::**)(A0) const)func))( + static R _thunk(void *obj, const void *func, A0 a0) { + return (((const T*)obj)->* + (*static_cast(func)))( a0); } }; - _obj = (void*)obj; + memset(&_func, 0, sizeof _func); memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; _thunk = &local::_thunk; } + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ template void attach(volatile T *obj, R (T::*func)(A0) volatile) { struct local { - static R _thunk(void *obj, void *func, A0 a0) { - return (((volatile T*)obj)->*(*(R (T::**)(A0) volatile)func))( + static R _thunk(void *obj, const void *func, A0 a0) { + return (((volatile T*)obj)->* + (*static_cast(func)))( a0); } }; - _obj = (void*)obj; + memset(&_func, 0, sizeof _func); memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; _thunk = &local::_thunk; } + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ template void attach(const volatile T *obj, R (T::*func)(A0) const volatile) { struct local { - static R _thunk(void *obj, void *func, A0 a0) { - return (((const volatile T*)obj)->*(*(R (T::**)(A0) const volatile)func))( + static R _thunk(void *obj, const void *func, A0 a0) { + return (((const volatile T*)obj)->* + (*static_cast(func)))( a0); } }; - _obj = (void*)obj; + memset(&_func, 0, sizeof _func); memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; _thunk = &local::_thunk; } /** Call the attached function */ - R call(A0 a0) { - if (!_thunk) { - return (R)0; - } + R call(A0 a0) const { + MBED_ASSERT(_thunk); return _thunk(_obj, &_func, a0); } /** Call the attached function */ - R operator()(A0 a0) { + R operator()(A0 a0) const { return call(a0); } @@ -518,6 +643,18 @@ public: return _thunk; } + /** Test for equality + */ + friend bool operator==(const Callback &l, const Callback &r) { + return memcmp(&l, &r, sizeof(Callback)) == 0; + } + + /** Test for inequality + */ + friend bool operator!=(const Callback &l, const Callback &r) { + return !(l == r); + } + /** Static thunk for passing as C-style function * @param func Callback to call passed as void pointer */ @@ -540,10 +677,12 @@ private: void *_obj; // Thunk registered on attach to dispatch calls - R (*_thunk)(void*, void*, A0); + R (*_thunk)(void*, const void*, A0); }; -/** Templated function class +/** Callback class based on template specialization + * + * @Note Synchronization level: Not protected */ template class Callback { @@ -555,13 +694,6 @@ public: attach(func); } - /** Create a Callback with another Callback - * @param func Callback to attach - */ - Callback(const Callback &func) { - attach(func); - } - /** Create a Callback with a static function and bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach @@ -571,16 +703,28 @@ public: attach(obj, func); } + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ template Callback(const T *obj, R (*func)(const T*, A0, A1)) { attach(obj, func); } + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ template Callback(volatile T *obj, R (*func)(volatile T*, A0, A1)) { attach(obj, func); } + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ template Callback(const volatile T *obj, R (*func)(const volatile T*, A0, A1)) { attach(obj, func); @@ -595,16 +739,28 @@ public: attach(obj, func); } + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ template Callback(const T *obj, R (T::*func)(A0, A1) const) { attach(obj, func); } + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ template Callback(volatile T *obj, R (T::*func)(A0, A1) volatile) { attach(obj, func); } + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ template Callback(const volatile T *obj, R (T::*func)(A0, A1) const volatile) { attach(obj, func); @@ -615,13 +771,15 @@ public: */ void attach(R (*func)(A0, A1)) { struct local { - static R _thunk(void*, void *func, A0 a0, A1 a1) { - return (*(R (**)(A0, A1))func)( + static R _thunk(void*, const void *func, A0 a0, A1 a1) { + return (*static_cast(func))( a0, a1); } }; + memset(&_func, 0, sizeof _func); memcpy(&_func, &func, sizeof func); + _obj = 0; _thunk = func ? &local::_thunk : 0; } @@ -629,8 +787,9 @@ public: * @param func The Callback to attach */ void attach(const Callback &func) { + memset(&_func, 0, sizeof _func); + memcpy(&_func, &func._func, sizeof func); _obj = func._obj; - memcpy(&_func, &func._func, sizeof _func); _thunk = func._thunk; } @@ -641,56 +800,72 @@ public: template void attach(T *obj, R (*func)(T*, A0, A1)) { struct local { - static R _thunk(void *obj, void *func, A0 a0, A1 a1) { - return (*(R (**)(T*, A0, A1))func)( + static R _thunk(void *obj, const void *func, A0 a0, A1 a1) { + return (*static_cast(func))( (T*)obj, a0, a1); } }; - _obj = (void*)obj; + memset(&_func, 0, sizeof _func); memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; _thunk = &local::_thunk; } + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ template void attach(const T *obj, R (*func)(const T*, A0, A1)) { struct local { - static R _thunk(void *obj, void *func, A0 a0, A1 a1) { - return (*(R (**)(const T*, A0, A1))func)( + static R _thunk(void *obj, const void *func, A0 a0, A1 a1) { + return (*static_cast(func))( (const T*)obj, a0, a1); } }; - _obj = (void*)obj; + memset(&_func, 0, sizeof _func); memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; _thunk = &local::_thunk; } + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ template void attach(volatile T *obj, R (*func)(volatile T*, A0, A1)) { struct local { - static R _thunk(void *obj, void *func, A0 a0, A1 a1) { - return (*(R (**)(volatile T*, A0, A1))func)( + static R _thunk(void *obj, const void *func, A0 a0, A1 a1) { + return (*static_cast(func))( (volatile T*)obj, a0, a1); } }; - _obj = (void*)obj; + memset(&_func, 0, sizeof _func); memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; _thunk = &local::_thunk; } + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ template void attach(const volatile T *obj, R (*func)(const volatile T*, A0, A1)) { struct local { - static R _thunk(void *obj, void *func, A0 a0, A1 a1) { - return (*(R (**)(const volatile T*, A0, A1))func)( + static R _thunk(void *obj, const void *func, A0 a0, A1 a1) { + return (*static_cast(func))( (const volatile T*)obj, a0, a1); } }; - _obj = (void*)obj; + memset(&_func, 0, sizeof _func); memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; _thunk = &local::_thunk; } @@ -701,71 +876,89 @@ public: template void attach(T *obj, R (T::*func)(A0, A1)) { struct local { - static R _thunk(void *obj, void *func, A0 a0, A1 a1) { - return (((T*)obj)->*(*(R (T::**)(A0, A1))func))( + static R _thunk(void *obj, const void *func, A0 a0, A1 a1) { + return (((T*)obj)->* + (*static_cast(func)))( a0, a1); } }; - _obj = (void*)obj; + memset(&_func, 0, sizeof _func); memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; _thunk = &local::_thunk; } + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ template void attach(const T *obj, R (T::*func)(A0, A1) const) { struct local { - static R _thunk(void *obj, void *func, A0 a0, A1 a1) { - return (((const T*)obj)->*(*(R (T::**)(A0, A1) const)func))( + static R _thunk(void *obj, const void *func, A0 a0, A1 a1) { + return (((const T*)obj)->* + (*static_cast(func)))( a0, a1); } }; - _obj = (void*)obj; + memset(&_func, 0, sizeof _func); memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; _thunk = &local::_thunk; } + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ template void attach(volatile T *obj, R (T::*func)(A0, A1) volatile) { struct local { - static R _thunk(void *obj, void *func, A0 a0, A1 a1) { - return (((volatile T*)obj)->*(*(R (T::**)(A0, A1) volatile)func))( + static R _thunk(void *obj, const void *func, A0 a0, A1 a1) { + return (((volatile T*)obj)->* + (*static_cast(func)))( a0, a1); } }; - _obj = (void*)obj; + memset(&_func, 0, sizeof _func); memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; _thunk = &local::_thunk; } + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ template void attach(const volatile T *obj, R (T::*func)(A0, A1) const volatile) { struct local { - static R _thunk(void *obj, void *func, A0 a0, A1 a1) { - return (((const volatile T*)obj)->*(*(R (T::**)(A0, A1) const volatile)func))( + static R _thunk(void *obj, const void *func, A0 a0, A1 a1) { + return (((const volatile T*)obj)->* + (*static_cast(func)))( a0, a1); } }; - _obj = (void*)obj; + memset(&_func, 0, sizeof _func); memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; _thunk = &local::_thunk; } /** Call the attached function */ - R call(A0 a0, A1 a1) { - if (!_thunk) { - return (R)0; - } + R call(A0 a0, A1 a1) const { + MBED_ASSERT(_thunk); return _thunk(_obj, &_func, a0, a1); } /** Call the attached function */ - R operator()(A0 a0, A1 a1) { + R operator()(A0 a0, A1 a1) const { return call(a0, a1); } @@ -775,6 +968,18 @@ public: return _thunk; } + /** Test for equality + */ + friend bool operator==(const Callback &l, const Callback &r) { + return memcmp(&l, &r, sizeof(Callback)) == 0; + } + + /** Test for inequality + */ + friend bool operator!=(const Callback &l, const Callback &r) { + return !(l == r); + } + /** Static thunk for passing as C-style function * @param func Callback to call passed as void pointer */ @@ -797,10 +1002,12 @@ private: void *_obj; // Thunk registered on attach to dispatch calls - R (*_thunk)(void*, void*, A0, A1); + R (*_thunk)(void*, const void*, A0, A1); }; -/** Templated function class +/** Callback class based on template specialization + * + * @Note Synchronization level: Not protected */ template class Callback { @@ -812,13 +1019,6 @@ public: attach(func); } - /** Create a Callback with another Callback - * @param func Callback to attach - */ - Callback(const Callback &func) { - attach(func); - } - /** Create a Callback with a static function and bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach @@ -828,16 +1028,28 @@ public: attach(obj, func); } + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ template Callback(const T *obj, R (*func)(const T*, A0, A1, A2)) { attach(obj, func); } + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ template Callback(volatile T *obj, R (*func)(volatile T*, A0, A1, A2)) { attach(obj, func); } + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ template Callback(const volatile T *obj, R (*func)(const volatile T*, A0, A1, A2)) { attach(obj, func); @@ -852,16 +1064,28 @@ public: attach(obj, func); } + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ template Callback(const T *obj, R (T::*func)(A0, A1, A2) const) { attach(obj, func); } + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ template Callback(volatile T *obj, R (T::*func)(A0, A1, A2) volatile) { attach(obj, func); } + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ template Callback(const volatile T *obj, R (T::*func)(A0, A1, A2) const volatile) { attach(obj, func); @@ -872,13 +1096,15 @@ public: */ void attach(R (*func)(A0, A1, A2)) { struct local { - static R _thunk(void*, void *func, A0 a0, A1 a1, A2 a2) { - return (*(R (**)(A0, A1, A2))func)( + static R _thunk(void*, const void *func, A0 a0, A1 a1, A2 a2) { + return (*static_cast(func))( a0, a1, a2); } }; + memset(&_func, 0, sizeof _func); memcpy(&_func, &func, sizeof func); + _obj = 0; _thunk = func ? &local::_thunk : 0; } @@ -886,8 +1112,9 @@ public: * @param func The Callback to attach */ void attach(const Callback &func) { + memset(&_func, 0, sizeof _func); + memcpy(&_func, &func._func, sizeof func); _obj = func._obj; - memcpy(&_func, &func._func, sizeof _func); _thunk = func._thunk; } @@ -898,56 +1125,72 @@ public: template void attach(T *obj, R (*func)(T*, A0, A1, A2)) { struct local { - static R _thunk(void *obj, void *func, A0 a0, A1 a1, A2 a2) { - return (*(R (**)(T*, A0, A1, A2))func)( + static R _thunk(void *obj, const void *func, A0 a0, A1 a1, A2 a2) { + return (*static_cast(func))( (T*)obj, a0, a1, a2); } }; - _obj = (void*)obj; + memset(&_func, 0, sizeof _func); memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; _thunk = &local::_thunk; } + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ template void attach(const T *obj, R (*func)(const T*, A0, A1, A2)) { struct local { - static R _thunk(void *obj, void *func, A0 a0, A1 a1, A2 a2) { - return (*(R (**)(const T*, A0, A1, A2))func)( + static R _thunk(void *obj, const void *func, A0 a0, A1 a1, A2 a2) { + return (*static_cast(func))( (const T*)obj, a0, a1, a2); } }; - _obj = (void*)obj; + memset(&_func, 0, sizeof _func); memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; _thunk = &local::_thunk; } + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ template void attach(volatile T *obj, R (*func)(volatile T*, A0, A1, A2)) { struct local { - static R _thunk(void *obj, void *func, A0 a0, A1 a1, A2 a2) { - return (*(R (**)(volatile T*, A0, A1, A2))func)( + static R _thunk(void *obj, const void *func, A0 a0, A1 a1, A2 a2) { + return (*static_cast(func))( (volatile T*)obj, a0, a1, a2); } }; - _obj = (void*)obj; + memset(&_func, 0, sizeof _func); memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; _thunk = &local::_thunk; } + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ template void attach(const volatile T *obj, R (*func)(const volatile T*, A0, A1, A2)) { struct local { - static R _thunk(void *obj, void *func, A0 a0, A1 a1, A2 a2) { - return (*(R (**)(const volatile T*, A0, A1, A2))func)( + static R _thunk(void *obj, const void *func, A0 a0, A1 a1, A2 a2) { + return (*static_cast(func))( (const volatile T*)obj, a0, a1, a2); } }; - _obj = (void*)obj; + memset(&_func, 0, sizeof _func); memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; _thunk = &local::_thunk; } @@ -958,71 +1201,89 @@ public: template void attach(T *obj, R (T::*func)(A0, A1, A2)) { struct local { - static R _thunk(void *obj, void *func, A0 a0, A1 a1, A2 a2) { - return (((T*)obj)->*(*(R (T::**)(A0, A1, A2))func))( + static R _thunk(void *obj, const void *func, A0 a0, A1 a1, A2 a2) { + return (((T*)obj)->* + (*static_cast(func)))( a0, a1, a2); } }; - _obj = (void*)obj; + memset(&_func, 0, sizeof _func); memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; _thunk = &local::_thunk; } + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ template void attach(const T *obj, R (T::*func)(A0, A1, A2) const) { struct local { - static R _thunk(void *obj, void *func, A0 a0, A1 a1, A2 a2) { - return (((const T*)obj)->*(*(R (T::**)(A0, A1, A2) const)func))( + static R _thunk(void *obj, const void *func, A0 a0, A1 a1, A2 a2) { + return (((const T*)obj)->* + (*static_cast(func)))( a0, a1, a2); } }; - _obj = (void*)obj; + memset(&_func, 0, sizeof _func); memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; _thunk = &local::_thunk; } + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ template void attach(volatile T *obj, R (T::*func)(A0, A1, A2) volatile) { struct local { - static R _thunk(void *obj, void *func, A0 a0, A1 a1, A2 a2) { - return (((volatile T*)obj)->*(*(R (T::**)(A0, A1, A2) volatile)func))( + static R _thunk(void *obj, const void *func, A0 a0, A1 a1, A2 a2) { + return (((volatile T*)obj)->* + (*static_cast(func)))( a0, a1, a2); } }; - _obj = (void*)obj; + memset(&_func, 0, sizeof _func); memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; _thunk = &local::_thunk; } + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ template void attach(const volatile T *obj, R (T::*func)(A0, A1, A2) const volatile) { struct local { - static R _thunk(void *obj, void *func, A0 a0, A1 a1, A2 a2) { - return (((const volatile T*)obj)->*(*(R (T::**)(A0, A1, A2) const volatile)func))( + static R _thunk(void *obj, const void *func, A0 a0, A1 a1, A2 a2) { + return (((const volatile T*)obj)->* + (*static_cast(func)))( a0, a1, a2); } }; - _obj = (void*)obj; + memset(&_func, 0, sizeof _func); memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; _thunk = &local::_thunk; } /** Call the attached function */ - R call(A0 a0, A1 a1, A2 a2) { - if (!_thunk) { - return (R)0; - } + R call(A0 a0, A1 a1, A2 a2) const { + MBED_ASSERT(_thunk); return _thunk(_obj, &_func, a0, a1, a2); } /** Call the attached function */ - R operator()(A0 a0, A1 a1, A2 a2) { + R operator()(A0 a0, A1 a1, A2 a2) const { return call(a0, a1, a2); } @@ -1032,6 +1293,18 @@ public: return _thunk; } + /** Test for equality + */ + friend bool operator==(const Callback &l, const Callback &r) { + return memcmp(&l, &r, sizeof(Callback)) == 0; + } + + /** Test for inequality + */ + friend bool operator!=(const Callback &l, const Callback &r) { + return !(l == r); + } + /** Static thunk for passing as C-style function * @param func Callback to call passed as void pointer */ @@ -1054,10 +1327,12 @@ private: void *_obj; // Thunk registered on attach to dispatch calls - R (*_thunk)(void*, void*, A0, A1, A2); + R (*_thunk)(void*, const void*, A0, A1, A2); }; -/** Templated function class +/** Callback class based on template specialization + * + * @Note Synchronization level: Not protected */ template class Callback { @@ -1069,13 +1344,6 @@ public: attach(func); } - /** Create a Callback with another Callback - * @param func Callback to attach - */ - Callback(const Callback &func) { - attach(func); - } - /** Create a Callback with a static function and bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach @@ -1085,16 +1353,28 @@ public: attach(obj, func); } + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ template Callback(const T *obj, R (*func)(const T*, A0, A1, A2, A3)) { attach(obj, func); } + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ template Callback(volatile T *obj, R (*func)(volatile T*, A0, A1, A2, A3)) { attach(obj, func); } + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ template Callback(const volatile T *obj, R (*func)(const volatile T*, A0, A1, A2, A3)) { attach(obj, func); @@ -1109,16 +1389,28 @@ public: attach(obj, func); } + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ template Callback(const T *obj, R (T::*func)(A0, A1, A2, A3) const) { attach(obj, func); } + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ template Callback(volatile T *obj, R (T::*func)(A0, A1, A2, A3) volatile) { attach(obj, func); } + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ template Callback(const volatile T *obj, R (T::*func)(A0, A1, A2, A3) const volatile) { attach(obj, func); @@ -1129,13 +1421,15 @@ public: */ void attach(R (*func)(A0, A1, A2, A3)) { struct local { - static R _thunk(void*, void *func, A0 a0, A1 a1, A2 a2, A3 a3) { - return (*(R (**)(A0, A1, A2, A3))func)( + static R _thunk(void*, const void *func, A0 a0, A1 a1, A2 a2, A3 a3) { + return (*static_cast(func))( a0, a1, a2, a3); } }; + memset(&_func, 0, sizeof _func); memcpy(&_func, &func, sizeof func); + _obj = 0; _thunk = func ? &local::_thunk : 0; } @@ -1143,8 +1437,9 @@ public: * @param func The Callback to attach */ void attach(const Callback &func) { + memset(&_func, 0, sizeof _func); + memcpy(&_func, &func._func, sizeof func); _obj = func._obj; - memcpy(&_func, &func._func, sizeof _func); _thunk = func._thunk; } @@ -1155,56 +1450,72 @@ public: template void attach(T *obj, R (*func)(T*, A0, A1, A2, A3)) { struct local { - static R _thunk(void *obj, void *func, A0 a0, A1 a1, A2 a2, A3 a3) { - return (*(R (**)(T*, A0, A1, A2, A3))func)( + static R _thunk(void *obj, const void *func, A0 a0, A1 a1, A2 a2, A3 a3) { + return (*static_cast(func))( (T*)obj, a0, a1, a2, a3); } }; - _obj = (void*)obj; + memset(&_func, 0, sizeof _func); memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; _thunk = &local::_thunk; } + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ template void attach(const T *obj, R (*func)(const T*, A0, A1, A2, A3)) { struct local { - static R _thunk(void *obj, void *func, A0 a0, A1 a1, A2 a2, A3 a3) { - return (*(R (**)(const T*, A0, A1, A2, A3))func)( + static R _thunk(void *obj, const void *func, A0 a0, A1 a1, A2 a2, A3 a3) { + return (*static_cast(func))( (const T*)obj, a0, a1, a2, a3); } }; - _obj = (void*)obj; + memset(&_func, 0, sizeof _func); memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; _thunk = &local::_thunk; } + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ template void attach(volatile T *obj, R (*func)(volatile T*, A0, A1, A2, A3)) { struct local { - static R _thunk(void *obj, void *func, A0 a0, A1 a1, A2 a2, A3 a3) { - return (*(R (**)(volatile T*, A0, A1, A2, A3))func)( + static R _thunk(void *obj, const void *func, A0 a0, A1 a1, A2 a2, A3 a3) { + return (*static_cast(func))( (volatile T*)obj, a0, a1, a2, a3); } }; - _obj = (void*)obj; + memset(&_func, 0, sizeof _func); memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; _thunk = &local::_thunk; } + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ template void attach(const volatile T *obj, R (*func)(const volatile T*, A0, A1, A2, A3)) { struct local { - static R _thunk(void *obj, void *func, A0 a0, A1 a1, A2 a2, A3 a3) { - return (*(R (**)(const volatile T*, A0, A1, A2, A3))func)( + static R _thunk(void *obj, const void *func, A0 a0, A1 a1, A2 a2, A3 a3) { + return (*static_cast(func))( (const volatile T*)obj, a0, a1, a2, a3); } }; - _obj = (void*)obj; + memset(&_func, 0, sizeof _func); memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; _thunk = &local::_thunk; } @@ -1215,71 +1526,89 @@ public: template void attach(T *obj, R (T::*func)(A0, A1, A2, A3)) { struct local { - static R _thunk(void *obj, void *func, A0 a0, A1 a1, A2 a2, A3 a3) { - return (((T*)obj)->*(*(R (T::**)(A0, A1, A2, A3))func))( + static R _thunk(void *obj, const void *func, A0 a0, A1 a1, A2 a2, A3 a3) { + return (((T*)obj)->* + (*static_cast(func)))( a0, a1, a2, a3); } }; - _obj = (void*)obj; + memset(&_func, 0, sizeof _func); memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; _thunk = &local::_thunk; } + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ template void attach(const T *obj, R (T::*func)(A0, A1, A2, A3) const) { struct local { - static R _thunk(void *obj, void *func, A0 a0, A1 a1, A2 a2, A3 a3) { - return (((const T*)obj)->*(*(R (T::**)(A0, A1, A2, A3) const)func))( + static R _thunk(void *obj, const void *func, A0 a0, A1 a1, A2 a2, A3 a3) { + return (((const T*)obj)->* + (*static_cast(func)))( a0, a1, a2, a3); } }; - _obj = (void*)obj; + memset(&_func, 0, sizeof _func); memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; _thunk = &local::_thunk; } + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ template void attach(volatile T *obj, R (T::*func)(A0, A1, A2, A3) volatile) { struct local { - static R _thunk(void *obj, void *func, A0 a0, A1 a1, A2 a2, A3 a3) { - return (((volatile T*)obj)->*(*(R (T::**)(A0, A1, A2, A3) volatile)func))( + static R _thunk(void *obj, const void *func, A0 a0, A1 a1, A2 a2, A3 a3) { + return (((volatile T*)obj)->* + (*static_cast(func)))( a0, a1, a2, a3); } }; - _obj = (void*)obj; + memset(&_func, 0, sizeof _func); memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; _thunk = &local::_thunk; } + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ template void attach(const volatile T *obj, R (T::*func)(A0, A1, A2, A3) const volatile) { struct local { - static R _thunk(void *obj, void *func, A0 a0, A1 a1, A2 a2, A3 a3) { - return (((const volatile T*)obj)->*(*(R (T::**)(A0, A1, A2, A3) const volatile)func))( + static R _thunk(void *obj, const void *func, A0 a0, A1 a1, A2 a2, A3 a3) { + return (((const volatile T*)obj)->* + (*static_cast(func)))( a0, a1, a2, a3); } }; - _obj = (void*)obj; + memset(&_func, 0, sizeof _func); memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; _thunk = &local::_thunk; } /** Call the attached function */ - R call(A0 a0, A1 a1, A2 a2, A3 a3) { - if (!_thunk) { - return (R)0; - } + R call(A0 a0, A1 a1, A2 a2, A3 a3) const { + MBED_ASSERT(_thunk); return _thunk(_obj, &_func, a0, a1, a2, a3); } /** Call the attached function */ - R operator()(A0 a0, A1 a1, A2 a2, A3 a3) { + R operator()(A0 a0, A1 a1, A2 a2, A3 a3) const { return call(a0, a1, a2, a3); } @@ -1289,6 +1618,18 @@ public: return _thunk; } + /** Test for equality + */ + friend bool operator==(const Callback &l, const Callback &r) { + return memcmp(&l, &r, sizeof(Callback)) == 0; + } + + /** Test for inequality + */ + friend bool operator!=(const Callback &l, const Callback &r) { + return !(l == r); + } + /** Static thunk for passing as C-style function * @param func Callback to call passed as void pointer */ @@ -1311,10 +1652,12 @@ private: void *_obj; // Thunk registered on attach to dispatch calls - R (*_thunk)(void*, void*, A0, A1, A2, A3); + R (*_thunk)(void*, const void*, A0, A1, A2, A3); }; -/** Templated function class +/** Callback class based on template specialization + * + * @Note Synchronization level: Not protected */ template class Callback { @@ -1326,13 +1669,6 @@ public: attach(func); } - /** Create a Callback with another Callback - * @param func Callback to attach - */ - Callback(const Callback &func) { - attach(func); - } - /** Create a Callback with a static function and bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach @@ -1342,16 +1678,28 @@ public: attach(obj, func); } + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ template Callback(const T *obj, R (*func)(const T*, A0, A1, A2, A3, A4)) { attach(obj, func); } + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ template Callback(volatile T *obj, R (*func)(volatile T*, A0, A1, A2, A3, A4)) { attach(obj, func); } + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ template Callback(const volatile T *obj, R (*func)(const volatile T*, A0, A1, A2, A3, A4)) { attach(obj, func); @@ -1366,16 +1714,28 @@ public: attach(obj, func); } + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ template Callback(const T *obj, R (T::*func)(A0, A1, A2, A3, A4) const) { attach(obj, func); } + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ template Callback(volatile T *obj, R (T::*func)(A0, A1, A2, A3, A4) volatile) { attach(obj, func); } + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ template Callback(const volatile T *obj, R (T::*func)(A0, A1, A2, A3, A4) const volatile) { attach(obj, func); @@ -1386,13 +1746,15 @@ public: */ void attach(R (*func)(A0, A1, A2, A3, A4)) { struct local { - static R _thunk(void*, void *func, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) { - return (*(R (**)(A0, A1, A2, A3, A4))func)( + static R _thunk(void*, const void *func, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) { + return (*static_cast(func))( a0, a1, a2, a3, a4); } }; + memset(&_func, 0, sizeof _func); memcpy(&_func, &func, sizeof func); + _obj = 0; _thunk = func ? &local::_thunk : 0; } @@ -1400,8 +1762,9 @@ public: * @param func The Callback to attach */ void attach(const Callback &func) { + memset(&_func, 0, sizeof _func); + memcpy(&_func, &func._func, sizeof func); _obj = func._obj; - memcpy(&_func, &func._func, sizeof _func); _thunk = func._thunk; } @@ -1412,56 +1775,72 @@ public: template void attach(T *obj, R (*func)(T*, A0, A1, A2, A3, A4)) { struct local { - static R _thunk(void *obj, void *func, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) { - return (*(R (**)(T*, A0, A1, A2, A3, A4))func)( + static R _thunk(void *obj, const void *func, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) { + return (*static_cast(func))( (T*)obj, a0, a1, a2, a3, a4); } }; - _obj = (void*)obj; + memset(&_func, 0, sizeof _func); memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; _thunk = &local::_thunk; } + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ template void attach(const T *obj, R (*func)(const T*, A0, A1, A2, A3, A4)) { struct local { - static R _thunk(void *obj, void *func, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) { - return (*(R (**)(const T*, A0, A1, A2, A3, A4))func)( + static R _thunk(void *obj, const void *func, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) { + return (*static_cast(func))( (const T*)obj, a0, a1, a2, a3, a4); } }; - _obj = (void*)obj; + memset(&_func, 0, sizeof _func); memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; _thunk = &local::_thunk; } + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ template void attach(volatile T *obj, R (*func)(volatile T*, A0, A1, A2, A3, A4)) { struct local { - static R _thunk(void *obj, void *func, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) { - return (*(R (**)(volatile T*, A0, A1, A2, A3, A4))func)( + static R _thunk(void *obj, const void *func, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) { + return (*static_cast(func))( (volatile T*)obj, a0, a1, a2, a3, a4); } }; - _obj = (void*)obj; + memset(&_func, 0, sizeof _func); memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; _thunk = &local::_thunk; } + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ template void attach(const volatile T *obj, R (*func)(const volatile T*, A0, A1, A2, A3, A4)) { struct local { - static R _thunk(void *obj, void *func, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) { - return (*(R (**)(const volatile T*, A0, A1, A2, A3, A4))func)( + static R _thunk(void *obj, const void *func, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) { + return (*static_cast(func))( (const volatile T*)obj, a0, a1, a2, a3, a4); } }; - _obj = (void*)obj; + memset(&_func, 0, sizeof _func); memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; _thunk = &local::_thunk; } @@ -1472,71 +1851,89 @@ public: template void attach(T *obj, R (T::*func)(A0, A1, A2, A3, A4)) { struct local { - static R _thunk(void *obj, void *func, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) { - return (((T*)obj)->*(*(R (T::**)(A0, A1, A2, A3, A4))func))( + static R _thunk(void *obj, const void *func, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) { + return (((T*)obj)->* + (*static_cast(func)))( a0, a1, a2, a3, a4); } }; - _obj = (void*)obj; + memset(&_func, 0, sizeof _func); memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; _thunk = &local::_thunk; } + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ template void attach(const T *obj, R (T::*func)(A0, A1, A2, A3, A4) const) { struct local { - static R _thunk(void *obj, void *func, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) { - return (((const T*)obj)->*(*(R (T::**)(A0, A1, A2, A3, A4) const)func))( + static R _thunk(void *obj, const void *func, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) { + return (((const T*)obj)->* + (*static_cast(func)))( a0, a1, a2, a3, a4); } }; - _obj = (void*)obj; + memset(&_func, 0, sizeof _func); memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; _thunk = &local::_thunk; } + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ template void attach(volatile T *obj, R (T::*func)(A0, A1, A2, A3, A4) volatile) { struct local { - static R _thunk(void *obj, void *func, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) { - return (((volatile T*)obj)->*(*(R (T::**)(A0, A1, A2, A3, A4) volatile)func))( + static R _thunk(void *obj, const void *func, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) { + return (((volatile T*)obj)->* + (*static_cast(func)))( a0, a1, a2, a3, a4); } }; - _obj = (void*)obj; + memset(&_func, 0, sizeof _func); memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; _thunk = &local::_thunk; } + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ template void attach(const volatile T *obj, R (T::*func)(A0, A1, A2, A3, A4) const volatile) { struct local { - static R _thunk(void *obj, void *func, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) { - return (((const volatile T*)obj)->*(*(R (T::**)(A0, A1, A2, A3, A4) const volatile)func))( + static R _thunk(void *obj, const void *func, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) { + return (((const volatile T*)obj)->* + (*static_cast(func)))( a0, a1, a2, a3, a4); } }; - _obj = (void*)obj; + memset(&_func, 0, sizeof _func); memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; _thunk = &local::_thunk; } /** Call the attached function */ - R call(A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) { - if (!_thunk) { - return (R)0; - } + R call(A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) const { + MBED_ASSERT(_thunk); return _thunk(_obj, &_func, a0, a1, a2, a3, a4); } /** Call the attached function */ - R operator()(A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) { + R operator()(A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) const { return call(a0, a1, a2, a3, a4); } @@ -1546,6 +1943,18 @@ public: return _thunk; } + /** Test for equality + */ + friend bool operator==(const Callback &l, const Callback &r) { + return memcmp(&l, &r, sizeof(Callback)) == 0; + } + + /** Test for inequality + */ + friend bool operator!=(const Callback &l, const Callback &r) { + return !(l == r); + } + /** Static thunk for passing as C-style function * @param func Callback to call passed as void pointer */ @@ -1568,307 +1977,661 @@ private: void *_obj; // Thunk registered on attach to dispatch calls - R (*_thunk)(void*, void*, A0, A1, A2, A3, A4); + R (*_thunk)(void*, const void*, A0, A1, A2, A3, A4); }; +// Internally used event type typedef Callback event_callback_t; /** Create a callback class with type infered from the arguments * - * @param obj Optional pointer to object to bind to function * @param func Static function to attach - * @return Callback with type infered from arguments + * @return Callback with infered type */ template Callback callback(R (*func)() = 0) { return Callback(func); } +/** Create a callback class with type infered from the arguments + * + * @param func Static function to attach + * @return Callback with infered type + */ template Callback callback(const Callback &func) { return Callback(func); } + +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + */ template Callback callback(T *obj, R (*func)(T*)) { return Callback(obj, func); } +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + */ template Callback callback(const T *obj, R (*func)(const T*)) { return Callback(obj, func); } +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + */ template Callback callback(volatile T *obj, R (*func)(volatile T*)) { return Callback(obj, func); } +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + */ template Callback callback(const volatile T *obj, R (*func)(const volatile T*)) { return Callback(obj, func); } +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + */ template Callback callback(T *obj, R (T::*func)()) { return Callback(obj, func); } +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + */ template Callback callback(const T *obj, R (T::*func)() const) { return Callback(obj, func); } +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + */ template Callback callback(volatile T *obj, R (T::*func)() volatile) { return Callback(obj, func); } +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + */ template Callback callback(const volatile T *obj, R (T::*func)() const volatile) { return Callback(obj, func); } + +/** Create a callback class with type infered from the arguments + * + * @param func Static function to attach + * @return Callback with infered type + */ template Callback callback(R (*func)(A0) = 0) { return Callback(func); } +/** Create a callback class with type infered from the arguments + * + * @param func Static function to attach + * @return Callback with infered type + */ template Callback callback(const Callback &func) { return Callback(func); } + +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + */ template Callback callback(T *obj, R (*func)(T*, A0)) { return Callback(obj, func); } +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + */ template Callback callback(const T *obj, R (*func)(const T*, A0)) { return Callback(obj, func); } +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + */ template Callback callback(volatile T *obj, R (*func)(volatile T*, A0)) { return Callback(obj, func); } +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + */ template Callback callback(const volatile T *obj, R (*func)(const volatile T*, A0)) { return Callback(obj, func); } +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + */ template Callback callback(T *obj, R (T::*func)(A0)) { return Callback(obj, func); } +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + */ template Callback callback(const T *obj, R (T::*func)(A0) const) { return Callback(obj, func); } +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + */ template Callback callback(volatile T *obj, R (T::*func)(A0) volatile) { return Callback(obj, func); } +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + */ template Callback callback(const volatile T *obj, R (T::*func)(A0) const volatile) { return Callback(obj, func); } + +/** Create a callback class with type infered from the arguments + * + * @param func Static function to attach + * @return Callback with infered type + */ template Callback callback(R (*func)(A0, A1) = 0) { return Callback(func); } +/** Create a callback class with type infered from the arguments + * + * @param func Static function to attach + * @return Callback with infered type + */ template Callback callback(const Callback &func) { return Callback(func); } + +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + */ template Callback callback(T *obj, R (*func)(T*, A0, A1)) { return Callback(obj, func); } +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + */ template Callback callback(const T *obj, R (*func)(const T*, A0, A1)) { return Callback(obj, func); } +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + */ template Callback callback(volatile T *obj, R (*func)(volatile T*, A0, A1)) { return Callback(obj, func); } +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + */ template Callback callback(const volatile T *obj, R (*func)(const volatile T*, A0, A1)) { return Callback(obj, func); } +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + */ template Callback callback(T *obj, R (T::*func)(A0, A1)) { return Callback(obj, func); } +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + */ template Callback callback(const T *obj, R (T::*func)(A0, A1) const) { return Callback(obj, func); } +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + */ template Callback callback(volatile T *obj, R (T::*func)(A0, A1) volatile) { return Callback(obj, func); } +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + */ template Callback callback(const volatile T *obj, R (T::*func)(A0, A1) const volatile) { return Callback(obj, func); } + +/** Create a callback class with type infered from the arguments + * + * @param func Static function to attach + * @return Callback with infered type + */ template Callback callback(R (*func)(A0, A1, A2) = 0) { return Callback(func); } +/** Create a callback class with type infered from the arguments + * + * @param func Static function to attach + * @return Callback with infered type + */ template Callback callback(const Callback &func) { return Callback(func); } + +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + */ template Callback callback(T *obj, R (*func)(T*, A0, A1, A2)) { return Callback(obj, func); } +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + */ template Callback callback(const T *obj, R (*func)(const T*, A0, A1, A2)) { return Callback(obj, func); } +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + */ template Callback callback(volatile T *obj, R (*func)(volatile T*, A0, A1, A2)) { return Callback(obj, func); } +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + */ template Callback callback(const volatile T *obj, R (*func)(const volatile T*, A0, A1, A2)) { return Callback(obj, func); } +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + */ template Callback callback(T *obj, R (T::*func)(A0, A1, A2)) { return Callback(obj, func); } +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + */ template Callback callback(const T *obj, R (T::*func)(A0, A1, A2) const) { return Callback(obj, func); } +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + */ template Callback callback(volatile T *obj, R (T::*func)(A0, A1, A2) volatile) { return Callback(obj, func); } +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + */ template Callback callback(const volatile T *obj, R (T::*func)(A0, A1, A2) const volatile) { return Callback(obj, func); } + +/** Create a callback class with type infered from the arguments + * + * @param func Static function to attach + * @return Callback with infered type + */ template Callback callback(R (*func)(A0, A1, A2, A3) = 0) { return Callback(func); } +/** Create a callback class with type infered from the arguments + * + * @param func Static function to attach + * @return Callback with infered type + */ template Callback callback(const Callback &func) { return Callback(func); } + +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + */ template Callback callback(T *obj, R (*func)(T*, A0, A1, A2, A3)) { return Callback(obj, func); } +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + */ template Callback callback(const T *obj, R (*func)(const T*, A0, A1, A2, A3)) { return Callback(obj, func); } +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + */ template Callback callback(volatile T *obj, R (*func)(volatile T*, A0, A1, A2, A3)) { return Callback(obj, func); } +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + */ template Callback callback(const volatile T *obj, R (*func)(const volatile T*, A0, A1, A2, A3)) { return Callback(obj, func); } +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + */ template Callback callback(T *obj, R (T::*func)(A0, A1, A2, A3)) { return Callback(obj, func); } +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + */ template Callback callback(const T *obj, R (T::*func)(A0, A1, A2, A3) const) { return Callback(obj, func); } +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + */ template Callback callback(volatile T *obj, R (T::*func)(A0, A1, A2, A3) volatile) { return Callback(obj, func); } +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + */ template Callback callback(const volatile T *obj, R (T::*func)(A0, A1, A2, A3) const volatile) { return Callback(obj, func); } + +/** Create a callback class with type infered from the arguments + * + * @param func Static function to attach + * @return Callback with infered type + */ template Callback callback(R (*func)(A0, A1, A2, A3, A4) = 0) { return Callback(func); } +/** Create a callback class with type infered from the arguments + * + * @param func Static function to attach + * @return Callback with infered type + */ template Callback callback(const Callback &func) { return Callback(func); } + +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + */ template Callback callback(T *obj, R (*func)(T*, A0, A1, A2, A3, A4)) { return Callback(obj, func); } +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + */ template Callback callback(const T *obj, R (*func)(const T*, A0, A1, A2, A3, A4)) { return Callback(obj, func); } +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + */ template Callback callback(volatile T *obj, R (*func)(volatile T*, A0, A1, A2, A3, A4)) { return Callback(obj, func); } +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + */ template Callback callback(const volatile T *obj, R (*func)(const volatile T*, A0, A1, A2, A3, A4)) { return Callback(obj, func); } +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + */ template Callback callback(T *obj, R (T::*func)(A0, A1, A2, A3, A4)) { return Callback(obj, func); } +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + */ template Callback callback(const T *obj, R (T::*func)(A0, A1, A2, A3, A4) const) { return Callback(obj, func); } +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + */ template Callback callback(volatile T *obj, R (T::*func)(A0, A1, A2, A3, A4) volatile) { return Callback(obj, func); } +/** Create a callback class with type infered from the arguments + * + * @param obj Optional pointer to object to bind to function + * @param func Static function to attach + * @return Callback with infered type + */ template Callback callback(const volatile T *obj, R (T::*func)(A0, A1, A2, A3, A4) const volatile) { return Callback(obj, func); diff --git a/hal/api/FunctionPointer.h b/hal/api/FunctionPointer.h index 1626e3e483..af51a8c929 100644 --- a/hal/api/FunctionPointer.h +++ b/hal/api/FunctionPointer.h @@ -43,6 +43,18 @@ public: R (*get_function())(A1) { return *reinterpret_cast(this); } + + R call(A1 a1) const { + if (!Callback::operator bool()) { + return (R)0; + } + + return Callback::call(a1); + } + + R operator()(A1 a1) const { + return Callback::call(a1); + } }; template @@ -62,6 +74,18 @@ public: R (*get_function())() { return *reinterpret_cast(this); } + + R call() const { + if (!Callback::operator bool()) { + return (R)0; + } + + return Callback::call(); + } + + R operator()() const { + return Callback::call(); + } }; typedef FunctionPointerArg1 FunctionPointer; diff --git a/hal/common/CAN.cpp b/hal/common/CAN.cpp index 780a106b73..84355b0230 100644 --- a/hal/common/CAN.cpp +++ b/hal/common/CAN.cpp @@ -21,8 +21,15 @@ namespace mbed { +static void donothing() {} + CAN::CAN(PinName rd, PinName td) : _can(), _irq() { // No lock needed in constructor + + for (int i = 0; i < sizeof _irq / sizeof _irq[0]; i++) { + _irq[i].attach(donothing); + } + can_init(&_can, rd, td); can_irq_init(&_can, (&CAN::_irq_handler), (uint32_t)this); } @@ -100,6 +107,7 @@ void CAN::attach(Callback func, IrqType type) { _irq[(CanIrqType)type].attach(func); can_irq_set(&_can, (CanIrqType)type, 1); } else { + _irq[(CanIrqType)type].attach(donothing); can_irq_set(&_can, (CanIrqType)type, 0); } unlock(); diff --git a/hal/common/InterruptIn.cpp b/hal/common/InterruptIn.cpp index 0e5bde9bc2..d3986e8893 100644 --- a/hal/common/InterruptIn.cpp +++ b/hal/common/InterruptIn.cpp @@ -19,11 +19,17 @@ namespace mbed { +static void donothing() {} + InterruptIn::InterruptIn(PinName pin) : gpio(), gpio_irq(), _rise(), _fall() { // No lock needed in the constructor + + _rise.attach(donothing); + _fall.attach(donothing); + gpio_irq_init(&gpio_irq, pin, (&InterruptIn::_irq_handler), (uint32_t)this); gpio_init_in(&gpio, pin); } @@ -50,7 +56,7 @@ void InterruptIn::rise(Callback func) { _rise.attach(func); gpio_irq_set(&gpio_irq, IRQ_RISE, 1); } else { - _rise.attach(NULL); + _rise.attach(donothing); gpio_irq_set(&gpio_irq, IRQ_RISE, 0); } core_util_critical_section_exit(); @@ -62,7 +68,7 @@ void InterruptIn::fall(Callback func) { _fall.attach(func); gpio_irq_set(&gpio_irq, IRQ_FALL, 1); } else { - _fall.attach(NULL); + _fall.attach(donothing); gpio_irq_set(&gpio_irq, IRQ_FALL, 0); } core_util_critical_section_exit(); diff --git a/hal/common/SerialBase.cpp b/hal/common/SerialBase.cpp index 891c450975..d75e479418 100644 --- a/hal/common/SerialBase.cpp +++ b/hal/common/SerialBase.cpp @@ -21,6 +21,8 @@ namespace mbed { +static void donothing() {}; + SerialBase::SerialBase(PinName tx, PinName rx) : #if DEVICE_SERIAL_ASYNCH _thunk_irq(this), _tx_usage(DMA_USAGE_NEVER), @@ -29,6 +31,10 @@ SerialBase::SerialBase(PinName tx, PinName rx) : _serial(), _baud(9600) { // No lock needed in the constructor + for (int i = 0; i < sizeof _irq / sizeof _irq[0]; i++) { + _irq[i].attach(donothing); + } + serial_init(&_serial, tx, rx); serial_irq_handler(&_serial, SerialBase::_irq_handler, (uint32_t)this); } @@ -69,6 +75,7 @@ void SerialBase::attach(Callback func, IrqType type) { _irq[type].attach(func); serial_irq_set(&_serial, (SerialIrq)type, 1); } else { + _irq[type].attach(donothing); serial_irq_set(&_serial, (SerialIrq)type, 0); } core_util_critical_section_exit();