From 45d25ed4938610d8d0f6fe1a40c7f51df62dc39e Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Thu, 18 Aug 2016 13:28:57 -0500 Subject: [PATCH 1/5] Added support for cv-qualifiers in Callback class Additionally, the following changes were don to avoid combinatorial explosion in function overloads as a result of adding cv-qualifiers: - Added convenience function for inferred type - Deprecated callback overloads qhere cv-qualifiers are not scalable Supported overloads: callback(void (*f)(A...)); callback(const Callback &); callback(T *t, void (*f)(T*, A...)); callback(const T *t, void (*f)(const T*, A...)); callback(volatile T *t, void (*f)(volatile T*, A...)); callback(const volatile T *t, void (*f)(const volatile T*, A...)); callback(T *t, void (T::*f)(A...)); callback(const T *t, void (T::*f)(A...) const); callback(volatile T *t, void (T::*f)(A...) volatile); callback(const volatile T *t, void (T::*f)(A...) const volatile); --- TESTS/mbed_drivers/callback/main.cpp | 419 ++++--- features/net/network-socket/Socket.h | 10 +- hal/api/CallChain.h | 19 +- hal/api/Callback.h | 1619 +++++++++++++++++++++----- hal/api/InterruptIn.h | 17 +- hal/api/SerialBase.h | 17 +- hal/api/Ticker.h | 15 +- rtos/rtos/RtosTimer.h | 10 +- rtos/rtos/Thread.h | 14 +- 9 files changed, 1652 insertions(+), 488 deletions(-) diff --git a/TESTS/mbed_drivers/callback/main.cpp b/TESTS/mbed_drivers/callback/main.cpp index 4e169a5a6c7..d4f0e9af57b 100644 --- a/TESTS/mbed_drivers/callback/main.cpp +++ b/TESTS/mbed_drivers/callback/main.cpp @@ -8,17 +8,17 @@ using namespace utest::v1; // static functions template -T static_func5(T a0, T a1, T a2, T a3, T a4) { return a0 | a1 | a2 | a3 | a4; } +T static_func0() { return 0; } template -T static_func4(T a0, T a1, T a2, T a3) { return a0 | a1 | a2 | a3; } +T static_func1(T a0) { return 0 | a0; } template -T static_func3(T a0, T a1, T a2) { return a0 | a1 | a2; } +T static_func2(T a0, T a1) { return 0 | a0 | a1; } template -T static_func2(T a0, T a1) { return a0 | a1; } +T static_func3(T a0, T a1, T a2) { return 0 | a0 | a1 | a2; } template -T static_func1(T a0) { return a0; } +T static_func4(T a0, T a1, T a2, T a3) { return 0 | a0 | a1 | a2 | a3; } template -T static_func0() { return 0; } +T static_func5(T a0, T a1, T a2, T a3, T a4) { return 0 | a0 | a1 | a2 | a3 | a4; } // class functions template @@ -26,198 +26,226 @@ struct Thing { T t; Thing() : t(0x80) {} - T member_func5(T a0, T a1, T a2, T a3, T a4) { return t | a0 | a1 | a2 | a3 | a4; } - T member_func4(T a0, T a1, T a2, T a3) { return t | a0 | a1 | a2 | a3; } - T member_func3(T a0, T a1, T a2) { return t | a0 | a1 | a2; } - T member_func2(T a0, T a1) { return t | a0 | a1; } - T member_func1(T a0) { return t | a0; } T member_func0() { return t; } + T member_func1(T a0) { return t | a0; } + T member_func2(T a0, T a1) { return t | a0 | a1; } + T member_func3(T a0, T a1, T a2) { return t | a0 | a1 | a2; } + T member_func4(T a0, T a1, T a2, T a3) { return t | a0 | a1 | a2 | a3; } + T member_func5(T a0, T a1, T a2, T a3, T a4) { return t | a0 | a1 | a2 | a3 | a4; } + + T const_member_func0() const { return t; } + T const_member_func1(T a0) const { return t | a0; } + T const_member_func2(T a0, T a1) const { return t | a0 | a1; } + T const_member_func3(T a0, T a1, T a2) const { return t | a0 | a1 | a2; } + T const_member_func4(T a0, T a1, T a2, T a3) const { return t | a0 | a1 | a2 | a3; } + T const_member_func5(T a0, T a1, T a2, T a3, T a4) const { return t | a0 | a1 | a2 | a3 | a4; } + + T volatile_member_func0() volatile { return t; } + T volatile_member_func1(T a0) volatile { return t | a0; } + T volatile_member_func2(T a0, T a1) volatile { return t | a0 | a1; } + T volatile_member_func3(T a0, T a1, T a2) volatile { return t | a0 | a1 | a2; } + T volatile_member_func4(T a0, T a1, T a2, T a3) volatile { return t | a0 | a1 | a2 | a3; } + T volatile_member_func5(T a0, T a1, T a2, T a3, T a4) volatile { return t | a0 | a1 | a2 | a3 | a4; } + + T const_volatile_member_func0() const volatile { return t; } + T const_volatile_member_func1(T a0) const volatile { return t | a0; } + T const_volatile_member_func2(T a0, T a1) const volatile { return t | a0 | a1; } + T const_volatile_member_func3(T a0, T a1, T a2) const volatile { return t | a0 | a1 | a2; } + T const_volatile_member_func4(T a0, T a1, T a2, T a3) const volatile { return t | a0 | a1 | a2 | a3; } + T const_volatile_member_func5(T a0, T a1, T a2, T a3, T a4) const volatile { return t | a0 | a1 | a2 | a3 | a4; } }; // bound functions template -T bound_func5(Thing *t, T a0, T a1, T a2, T a3, T a4) { return t->t | a0 | a1 | a2 | a3 | a4; } -template -T bound_func4(Thing *t, T a0, T a1, T a2, T a3) { return t->t | a0 | a1 | a2 | a3; } +T bound_func0(Thing *t) { return t->t; } template -T bound_func3(Thing *t, T a0, T a1, T a2) { return t->t | a0 | a1 | a2; } +T bound_func1(Thing *t, T a0) { return t->t | a0; } template T bound_func2(Thing *t, T a0, T a1) { return t->t | a0 | a1; } template -T bound_func1(Thing *t, T a0) { return t->t | a0; } +T bound_func3(Thing *t, T a0, T a1, T a2) { return t->t | a0 | a1 | a2; } template -T bound_func0(Thing *t) { return t->t; } +T bound_func4(Thing *t, T a0, T a1, T a2, T a3) { return t->t | a0 | a1 | a2 | a3; } +template +T bound_func5(Thing *t, T a0, T a1, T a2, T a3, T a4) { return t->t | a0 | a1 | a2 | a3 | a4; } // const bound functions template -T const_func5(const Thing *t, T a0, T a1, T a2, T a3, T a4) { return t->t | a0 | a1 | a2 | a3 | a4; } -template -T const_func4(const Thing *t, T a0, T a1, T a2, T a3) { return t->t | a0 | a1 | a2 | a3; } +T const_func0(const Thing *t) { return t->t; } template -T const_func3(const Thing *t, T a0, T a1, T a2) { return t->t | a0 | a1 | a2; } +T const_func1(const Thing *t, T a0) { return t->t | a0; } template T const_func2(const Thing *t, T a0, T a1) { return t->t | a0 | a1; } template -T const_func1(const Thing *t, T a0) { return t->t | a0; } +T const_func3(const Thing *t, T a0, T a1, T a2) { return t->t | a0 | a1 | a2; } template -T const_func0(const Thing *t) { return t->t; } +T const_func4(const Thing *t, T a0, T a1, T a2, T a3) { return t->t | a0 | a1 | a2 | a3; } +template +T const_func5(const Thing *t, T a0, T a1, T a2, T a3, T a4) { return t->t | a0 | a1 | a2 | a3 | a4; } // volatile bound functions template -T volatile_func5(volatile Thing *t, T a0, T a1, T a2, T a3, T a4) { return t->t | a0 | a1 | a2 | a3 | a4; } -template -T volatile_func4(volatile Thing *t, T a0, T a1, T a2, T a3) { return t->t | a0 | a1 | a2 | a3; } +T volatile_func0(volatile Thing *t) { return t->t; } template -T volatile_func3(volatile Thing *t, T a0, T a1, T a2) { return t->t | a0 | a1 | a2; } +T volatile_func1(volatile Thing *t, T a0) { return t->t | a0; } template T volatile_func2(volatile Thing *t, T a0, T a1) { return t->t | a0 | a1; } template -T volatile_func1(volatile Thing *t, T a0) { return t->t | a0; } +T volatile_func3(volatile Thing *t, T a0, T a1, T a2) { return t->t | a0 | a1 | a2; } template -T volatile_func0(volatile Thing *t) { return t->t; } - -// const volatil bound functions +T volatile_func4(volatile Thing *t, T a0, T a1, T a2, T a3) { return t->t | a0 | a1 | a2 | a3; } template -T const_volatile_func5(const volatile Thing *t, T a0, T a1, T a2, T a3, T a4) { return t->t | a0 | a1 | a2 | a3 | a4; } +T volatile_func5(volatile Thing *t, T a0, T a1, T a2, T a3, T a4) { return t->t | a0 | a1 | a2 | a3 | a4; } + +// const volatile bound functions template -T const_volatile_func4(const volatile Thing *t, T a0, T a1, T a2, T a3) { return t->t | a0 | a1 | a2 | a3; } +T const_volatile_func0(const volatile Thing *t) { return t->t; } template -T const_volatile_func3(const volatile Thing *t, T a0, T a1, T a2) { return t->t | a0 | a1 | a2; } +T const_volatile_func1(const volatile Thing *t, T a0) { return t->t | a0; } template T const_volatile_func2(const volatile Thing *t, T a0, T a1) { return t->t | a0 | a1; } template -T const_volatile_func1(const volatile Thing *t, T a0) { return t->t | a0; } +T const_volatile_func3(const volatile Thing *t, T a0, T a1, T a2) { return t->t | a0 | a1 | a2; } template -T const_volatile_func0(const volatile Thing *t) { return t->t; } +T const_volatile_func4(const volatile Thing *t, T a0, T a1, T a2, T a3) { return t->t | a0 | a1 | a2 | a3; } +template +T const_volatile_func5(const volatile Thing *t, T a0, T a1, T a2, T a3, T a4) { return t->t | a0 | a1 | a2 | a3 | a4; } // function call and result verification template struct Verifier { - static void verify5(Callback func) { - T result = func(0x01, 0x02, 0x04, 0x08, 0x10); - TEST_ASSERT_EQUAL(result, 0x1f); + static void verify0(Callback func) { + T result = func(); + TEST_ASSERT_EQUAL(result, 0x00); } template - static void verify5(O *obj, M method) { - Callback func(obj, method); - T result = func(0x01, 0x02, 0x04, 0x08, 0x10); - TEST_ASSERT_EQUAL(result, 0x9f); + static void verify0(O *obj, M method) { + Callback func(obj, method); + T result = func(); + TEST_ASSERT_EQUAL(result, 0x80); } - static void verify4(Callback func) { - T result = func(0x01, 0x02, 0x04, 0x08); - TEST_ASSERT_EQUAL(result, 0x0f); + static void verify1(Callback func) { + T result = func((1 << 0)); + TEST_ASSERT_EQUAL(result, 0x00 | (1 << 0)); } template - static void verify4(O *obj, M method) { - Callback func(obj, method); - T result = func(0x01, 0x02, 0x04, 0x08); - TEST_ASSERT_EQUAL(result, 0x8f); + static void verify1(O *obj, M method) { + Callback func(obj, method); + T result = func((1 << 0)); + TEST_ASSERT_EQUAL(result, 0x80 | (1 << 0)); } - static void verify3(Callback func) { - T result = func(0x01, 0x02, 0x04); - TEST_ASSERT_EQUAL(result, 0x07); + static void verify2(Callback func) { + T result = func((1 << 0), (1 << 1)); + TEST_ASSERT_EQUAL(result, 0x00 | (1 << 0) | (1 << 1)); } template - static void verify3(O *obj, M method) { - Callback func(obj, method); - T result = func(0x01, 0x02, 0x04); - TEST_ASSERT_EQUAL(result, 0x87); + static void verify2(O *obj, M method) { + Callback func(obj, method); + T result = func((1 << 0), (1 << 1)); + TEST_ASSERT_EQUAL(result, 0x80 | (1 << 0) | (1 << 1)); } - static void verify2(Callback func) { - T result = func(0x01, 0x02); - TEST_ASSERT_EQUAL(result, 0x03); + static void verify3(Callback func) { + T result = func((1 << 0), (1 << 1), (1 << 2)); + TEST_ASSERT_EQUAL(result, 0x00 | (1 << 0) | (1 << 1) | (1 << 2)); } template - static void verify2(O *obj, M method) { - Callback func(obj, method); - T result = func(0x01, 0x02); - TEST_ASSERT_EQUAL(result, 0x83); + static void verify3(O *obj, M method) { + Callback func(obj, method); + T result = func((1 << 0), (1 << 1), (1 << 2)); + TEST_ASSERT_EQUAL(result, 0x80 | (1 << 0) | (1 << 1) | (1 << 2)); } - static void verify1(Callback func) { - T result = func(0x01); - TEST_ASSERT_EQUAL(result, 0x01); + static void verify4(Callback func) { + T result = func((1 << 0), (1 << 1), (1 << 2), (1 << 3)); + TEST_ASSERT_EQUAL(result, 0x00 | (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3)); } template - static void verify1(O *obj, M method) { - Callback func(obj, method); - T result = func(0x01); - TEST_ASSERT_EQUAL(result, 0x81); + static void verify4(O *obj, M method) { + Callback func(obj, method); + T result = func((1 << 0), (1 << 1), (1 << 2), (1 << 3)); + TEST_ASSERT_EQUAL(result, 0x80 | (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3)); } - static void verify0(Callback func) { - T result = func(); - TEST_ASSERT_EQUAL(result, 0x00); + static void verify5(Callback func) { + T result = func((1 << 0), (1 << 1), (1 << 2), (1 << 3), (1 << 4)); + TEST_ASSERT_EQUAL(result, 0x00 | (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4)); } template - static void verify0(O *obj, M method) { - Callback func(obj, method); - T result = func(); - TEST_ASSERT_EQUAL(result, 0x80); + static void verify5(O *obj, M method) { + Callback func(obj, method); + T result = func((1 << 0), (1 << 1), (1 << 2), (1 << 3), (1 << 4)); + TEST_ASSERT_EQUAL(result, 0x80 | (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4)); } }; // test dispatch template -void test_dispatch5() { - Thing thing; - Verifier::verify5(static_func5); - Verifier::verify5(&thing, &Thing::member_func5); - Verifier::verify5(&thing, &bound_func5); - Verifier::verify5((const Thing*)&thing, &const_func5); - Verifier::verify5((volatile Thing*)&thing, &volatile_func5); - Verifier::verify5((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); -} - -template -void test_dispatch4() { +void test_dispatch0() { Thing thing; - Verifier::verify4(static_func4); - Verifier::verify4(&thing, &Thing::member_func4); - Verifier::verify4(&thing, &bound_func4); - Verifier::verify4((const Thing*)&thing, &const_func4); - Verifier::verify4((volatile Thing*)&thing, &volatile_func4); - Verifier::verify4((const volatile Thing*)&thing, &const_volatile_func4); + Verifier::verify0(static_func0); + Verifier::verify0(&thing, &Thing::member_func0); + Verifier::verify0((const Thing*)&thing, &Thing::const_member_func0); + Verifier::verify0((volatile Thing*)&thing, &Thing::volatile_member_func0); + Verifier::verify0((const volatile Thing*)&thing, &Thing::const_volatile_member_func0); + Verifier::verify0(&thing, &bound_func0); + Verifier::verify0((const Thing*)&thing, &const_func0); + 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_func4); - Verifier::verify4(callback); - callback.attach(&thing, &bound_func4); - Verifier::verify4(&callback, &Callback::call); - Verifier::verify4((void*)&callback, &Callback::thunk); + Callback callback(static_func0); + Verifier::verify0(callback); + callback.attach(&thing, &bound_func0); + Verifier::verify0(&callback, &Callback::call); + Verifier::verify0((void*)&callback, &Callback::thunk); } template -void test_dispatch3() { +void test_dispatch1() { Thing thing; - Verifier::verify3(static_func3); - Verifier::verify3(&thing, &Thing::member_func3); - Verifier::verify3(&thing, &bound_func3); - Verifier::verify3((const Thing*)&thing, &const_func3); - Verifier::verify3((volatile Thing*)&thing, &volatile_func3); - Verifier::verify3((const volatile Thing*)&thing, &const_volatile_func3); + Verifier::verify1(static_func1); + Verifier::verify1(&thing, &Thing::member_func1); + Verifier::verify1((const Thing*)&thing, &Thing::const_member_func1); + Verifier::verify1((volatile Thing*)&thing, &Thing::volatile_member_func1); + Verifier::verify1((const volatile Thing*)&thing, &Thing::const_volatile_member_func1); + Verifier::verify1(&thing, &bound_func1); + Verifier::verify1((const Thing*)&thing, &const_func1); + 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_func3); - Verifier::verify3(callback); - callback.attach(&thing, &bound_func3); - Verifier::verify3(&callback, &Callback::call); - Verifier::verify3((void*)&callback, &Callback::thunk); + Callback callback(static_func1); + Verifier::verify1(callback); + callback.attach(&thing, &bound_func1); + Verifier::verify1(&callback, &Callback::call); + Verifier::verify1((void*)&callback, &Callback::thunk); } template @@ -225,50 +253,115 @@ void test_dispatch2() { Thing thing; Verifier::verify2(static_func2); Verifier::verify2(&thing, &Thing::member_func2); + Verifier::verify2((const Thing*)&thing, &Thing::const_member_func2); + Verifier::verify2((volatile Thing*)&thing, &Thing::volatile_member_func2); + Verifier::verify2((const volatile Thing*)&thing, &Thing::const_volatile_member_func2); Verifier::verify2(&thing, &bound_func2); Verifier::verify2((const Thing*)&thing, &const_func2); Verifier::verify2((volatile Thing*)&thing, &volatile_func2); Verifier::verify2((const volatile Thing*)&thing, &const_volatile_func2); - - Callback callback(static_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); + Verifier::verify2(&callback, &Callback::call); + Verifier::verify2((void*)&callback, &Callback::thunk); } template -void test_dispatch1() { +void test_dispatch3() { Thing thing; - Verifier::verify1(static_func1); - Verifier::verify1(&thing, &Thing::member_func1); - Verifier::verify1(&thing, &bound_func1); - Verifier::verify1((const Thing*)&thing, &const_func1); - Verifier::verify1((volatile Thing*)&thing, &volatile_func1); - Verifier::verify1((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); + Verifier::verify3(static_func3); + Verifier::verify3(&thing, &Thing::member_func3); + Verifier::verify3((const Thing*)&thing, &Thing::const_member_func3); + Verifier::verify3((volatile Thing*)&thing, &Thing::volatile_member_func3); + Verifier::verify3((const volatile Thing*)&thing, &Thing::const_volatile_member_func3); + Verifier::verify3(&thing, &bound_func3); + Verifier::verify3((const Thing*)&thing, &const_func3); + 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); } template -void test_dispatch0() { +void test_dispatch4() { Thing thing; - Verifier::verify0(static_func0); - Verifier::verify0(&thing, &Thing::member_func0); - Verifier::verify0(&thing, &bound_func0); - Verifier::verify0((const Thing*)&thing, &const_func0); - Verifier::verify0((volatile Thing*)&thing, &volatile_func0); - Verifier::verify0((const volatile Thing*)&thing, &const_volatile_func0); + Verifier::verify4(static_func4); + Verifier::verify4(&thing, &Thing::member_func4); + Verifier::verify4((const Thing*)&thing, &Thing::const_member_func4); + Verifier::verify4((volatile Thing*)&thing, &Thing::volatile_member_func4); + Verifier::verify4((const volatile Thing*)&thing, &Thing::const_volatile_member_func4); + Verifier::verify4(&thing, &bound_func4); + Verifier::verify4((const Thing*)&thing, &const_func4); + 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 callback(static_func0); - Verifier::verify0(callback); - callback.attach(&thing, &bound_func0); - Verifier::verify0(&callback, &Callback::call); - Verifier::verify0((void*)&callback, &Callback::thunk); +template +void test_dispatch5() { + Thing thing; + Verifier::verify5(static_func5); + Verifier::verify5(&thing, &Thing::member_func5); + Verifier::verify5((const Thing*)&thing, &Thing::const_member_func5); + Verifier::verify5((volatile Thing*)&thing, &Thing::volatile_member_func5); + Verifier::verify5((const volatile Thing*)&thing, &Thing::const_volatile_member_func5); + Verifier::verify5(&thing, &bound_func5); + Verifier::verify5((const Thing*)&thing, &const_func5); + 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); } template @@ -295,26 +388,26 @@ utest::v1::status_t test_setup(const size_t number_of_cases) { } Case cases[] = { - Case("Testing callbacks with 5 ints", test_dispatch5), - Case("Testing callbacks with 4 ints", test_dispatch4), - Case("Testing callbacks with 3 ints", test_dispatch3), - Case("Testing callbacks with 2 ints", test_dispatch2), - Case("Testing callbacks with 1 ints", test_dispatch1), Case("Testing callbacks with 0 ints", test_dispatch0), + Case("Testing callbacks with 1 ints", test_dispatch1), + Case("Testing callbacks with 2 ints", test_dispatch2), + Case("Testing callbacks with 3 ints", test_dispatch3), + Case("Testing callbacks with 4 ints", test_dispatch4), + Case("Testing callbacks with 5 ints", test_dispatch5), - Case("Testing callbacks with 5 uchars", test_dispatch5), - Case("Testing callbacks with 4 uchars", test_dispatch4), - Case("Testing callbacks with 3 uchars", test_dispatch3), - Case("Testing callbacks with 2 uchars", test_dispatch2), - Case("Testing callbacks with 1 uchars", test_dispatch1), Case("Testing callbacks with 0 uchars", test_dispatch0), + Case("Testing callbacks with 1 uchars", test_dispatch1), + Case("Testing callbacks with 2 uchars", test_dispatch2), + Case("Testing callbacks with 3 uchars", test_dispatch3), + Case("Testing callbacks with 4 uchars", test_dispatch4), + Case("Testing callbacks with 5 uchars", test_dispatch5), - Case("Testing callbacks with 5 uint64s", test_dispatch5), - Case("Testing callbacks with 4 uint64s", test_dispatch4), - Case("Testing callbacks with 3 uint64s", test_dispatch3), - Case("Testing callbacks with 2 uint64s", test_dispatch2), - Case("Testing callbacks with 1 uint64s", test_dispatch1), Case("Testing callbacks with 0 uint64s", test_dispatch0), + Case("Testing callbacks with 1 uint64s", test_dispatch1), + Case("Testing callbacks with 2 uint64s", test_dispatch2), + Case("Testing callbacks with 3 uint64s", test_dispatch3), + Case("Testing callbacks with 4 uint64s", test_dispatch4), + Case("Testing callbacks with 5 uint64s", test_dispatch5), Case("Testing FunctionPointerArg1 compatibility", test_fparg1), Case("Testing FunctionPointer compatibility", test_fparg0), diff --git a/features/net/network-socket/Socket.h b/features/net/network-socket/Socket.h index c481930440f..39a89a529f4 100644 --- a/features/net/network-socket/Socket.h +++ b/features/net/network-socket/Socket.h @@ -21,6 +21,7 @@ #include "network-socket/NetworkStack.h" #include "rtos/Mutex.h" #include "Callback.h" +#include "toolchain.h" /** Abstract socket class @@ -168,10 +169,17 @@ class Socket { * * @param obj Pointer to object to call method on * @param method Method to call on state change + * + * @deprecated + * The attach function does not support cv-qualifiers. Replaced by + * attach(callback(obj, method)). */ template + MBED_DEPRECATED_SINCE("mbed-os-5.1", + "The attach function does not support cv-qualifiers. Replaced by " + "attach(callback(obj, method)).") void attach(T *obj, M method) { - attach(mbed::Callback(obj, method)); + attach(mbed::callback(obj, method)); } protected: diff --git a/hal/api/CallChain.h b/hal/api/CallChain.h index 473ff12a144..7b0b20edc56 100644 --- a/hal/api/CallChain.h +++ b/hal/api/CallChain.h @@ -17,6 +17,7 @@ #define MBED_CALLCHAIN_H #include "Callback.h" +#include "toolchain.h" #include namespace mbed { @@ -87,10 +88,17 @@ class CallChain { * * @returns * The function object created for 'obj' and 'method' + * + * @deprecated + * The add function does not support cv-qualifiers. Replaced by + * add(callback(obj, method)). */ template + MBED_DEPRECATED_SINCE("mbed-os-5.1", + "The add function does not support cv-qualifiers. Replaced by " + "add(callback(obj, method)).") pFunctionPointer_t add(T *obj, M method) { - return add(Callback(obj, method)); + return add(callback(obj, method)); } /** Add a function at the beginning of the chain @@ -109,10 +117,17 @@ class CallChain { * * @returns * The function object created for 'tptr' and 'mptr' + * + * @deprecated + * The add_front function does not support cv-qualifiers. Replaced by + * add_front(callback(obj, method)). */ template + MBED_DEPRECATED_SINCE("mbed-os-5.1", + "The add_front function does not support cv-qualifiers. Replaced by " + "add_front(callback(obj, method)).") pFunctionPointer_t add_front(T *obj, M method) { - return add_front(Callback(obj, method)); + return add_front(callback(obj, method)); } /** Get the number of functions in the chain diff --git a/hal/api/Callback.h b/hal/api/Callback.h index 8ffd70164c4..8a415bb6c4b 100644 --- a/hal/api/Callback.h +++ b/hal/api/Callback.h @@ -31,13 +31,20 @@ class Callback; /** Templated function class */ -template -class Callback { +template +class Callback { public: /** Create a Callback with a static function * @param func Static function to attach */ - Callback(R (*func)(A0, A1, A2, A3, A4) = 0) { + Callback(R (*func)() = 0) { + attach(func); + } + + /** Create a Callback with another Callback + * @param func Callback to attach + */ + Callback(const Callback &func) { attach(func); } @@ -46,7 +53,22 @@ class Callback { * @param func Static function to attach */ template - Callback(T *obj, R (*func)(T*, A0, A1, A2, A3, A4)) { + Callback(T *obj, R (*func)(T*)) { + attach(obj, func); + } + + template + Callback(const T *obj, R (*func)(const T*)) { + attach(obj, func); + } + + template + Callback(volatile T *obj, R (*func)(volatile T*)) { + attach(obj, func); + } + + template + Callback(const volatile T *obj, R (*func)(const volatile T*)) { attach(obj, func); } @@ -55,23 +77,47 @@ class Callback { * @param func Member function to attach */ template - Callback(T *obj, R (T::*func)(A0, A1, A2, A3, A4)) { + Callback(T *obj, R (T::*func)()) { attach(obj, func); } - /** Create a Callback with another Callback - * @param func Callback to attach - */ - Callback(const Callback &func) { - attach(func); + template + Callback(const T *obj, R (T::*func)() const) { + attach(obj, func); + } + + template + Callback(volatile T *obj, R (T::*func)() volatile) { + attach(obj, func); + } + + template + Callback(const volatile T *obj, R (T::*func)() const volatile) { + attach(obj, func); } /** Attach a static function * @param func Static function to attach */ - void attach(R (*func)(A0, A1, A2, A3, A4)) { + void attach(R (*func)()) { + struct local { + static R _thunk(void*, void *func) { + return (*(R (**)())func)( + ); + } + }; + memcpy(&_func, &func, sizeof func); - _thunk = func ? &Callback::_staticthunk : 0; + _thunk = func ? &local::_thunk : 0; + } + + /** Attach a Callback + * @param func The Callback to attach + */ + void attach(const Callback &func) { + _obj = func._obj; + memcpy(&_func, &func._func, sizeof _func); + _thunk = func._thunk; } /** Attach a static function with a bound pointer @@ -79,10 +125,59 @@ class Callback { * @param func Static function to attach */ template - void attach(T *obj, R (*func)(T*, A0, A1, A2, A3, A4)) { + void attach(T *obj, R (*func)(T*)) { + struct local { + static R _thunk(void *obj, void *func) { + return (*(R (**)(T*))func)( + (T*)obj); + } + }; + + _obj = (void*)obj; + memcpy(&_func, &func, sizeof func); + _thunk = &local::_thunk; + } + + template + void attach(const T *obj, R (*func)(const T*)) { + struct local { + static R _thunk(void *obj, void *func) { + return (*(R (**)(const T*))func)( + (const T*)obj); + } + }; + + _obj = (void*)obj; + memcpy(&_func, &func, sizeof func); + _thunk = &local::_thunk; + } + + template + void attach(volatile T *obj, R (*func)(volatile T*)) { + struct local { + static R _thunk(void *obj, void *func) { + return (*(R (**)(volatile T*))func)( + (volatile T*)obj); + } + }; + + _obj = (void*)obj; + memcpy(&_func, &func, sizeof func); + _thunk = &local::_thunk; + } + + 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)( + (const volatile T*)obj); + } + }; + _obj = (void*)obj; memcpy(&_func, &func, sizeof func); - _thunk = &Callback::_boundthunk; + _thunk = &local::_thunk; } /** Attach a member function @@ -90,34 +185,74 @@ class Callback { * @param func Member function to attach */ template - void attach(T *obj, R (T::*func)(A0, A1, A2, A3, A4)) { - _obj = static_cast(obj); + void attach(T *obj, R (T::*func)()) { + struct local { + static R _thunk(void *obj, void *func) { + return (((T*)obj)->*(*(R (T::**)())func))( + ); + } + }; + + _obj = (void*)obj; memcpy(&_func, &func, sizeof func); - _thunk = &Callback::_methodthunk; + _thunk = &local::_thunk; } - /** Attach a Callback - * @param func The Callback to attach - */ - void attach(const Callback &func) { - _obj = func._obj; - memcpy(&_func, &func._func, sizeof _func); - _thunk = func._thunk; + 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))( + ); + } + }; + + _obj = (void*)obj; + memcpy(&_func, &func, sizeof func); + _thunk = &local::_thunk; + } + + 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))( + ); + } + }; + + _obj = (void*)obj; + memcpy(&_func, &func, sizeof func); + _thunk = &local::_thunk; + } + + 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))( + ); + } + }; + + _obj = (void*)obj; + memcpy(&_func, &func, sizeof func); + _thunk = &local::_thunk; } /** Call the attached function */ - R call(A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) { + R call() { if (!_thunk) { return (R)0; } - return _thunk(_obj, &_func, a0, a1, a2, a3, a4); + return _thunk(_obj, &_func); } /** Call the attached function */ - R operator()(A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) { - return call(a0, a1, a2, a3, a4); + R operator()() { + return call(); } /** Test if function has been attached @@ -129,31 +264,12 @@ class Callback { /** Static thunk for passing as C-style function * @param func Callback to call passed as void pointer */ - static R thunk(void *func, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) { - return static_cast*>(func) - ->call(a0, a1, a2, a3, a4); + static R thunk(void *func) { + return static_cast*>(func)->call( + ); } private: - // Internal thunks for various function types - static R _staticthunk(void*, void *func, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) { - return (*reinterpret_cast(func)) - (a0, a1, a2, a3, a4); - } - - template - static R _boundthunk(void *obj, void *func, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) { - return (*reinterpret_cast(func)) - (static_cast(obj), a0, a1, a2, a3, a4); - } - - template - static R _methodthunk(void *obj, void *func, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) { - return (static_cast(obj)->* - (*reinterpret_cast(func))) - (a0, a1, a2, a3, a4); - } - // Stored as pointer to function and pointer to optional object // Function pointer is stored as union of possible function types // to garuntee proper size and alignment @@ -167,18 +283,25 @@ class Callback { void *_obj; // Thunk registered on attach to dispatch calls - R (*_thunk)(void*, void*, A0, A1, A2, A3, A4); + R (*_thunk)(void*, void*); }; /** Templated function class */ -template -class Callback { +template +class Callback { public: /** Create a Callback with a static function * @param func Static function to attach */ - Callback(R (*func)(A0, A1, A2, A3) = 0) { + Callback(R (*func)(A0) = 0) { + attach(func); + } + + /** Create a Callback with another Callback + * @param func Callback to attach + */ + Callback(const Callback &func) { attach(func); } @@ -187,7 +310,22 @@ class Callback { * @param func Static function to attach */ template - Callback(T *obj, R (*func)(T*, A0, A1, A2, A3)) { + Callback(T *obj, R (*func)(T*, A0)) { + attach(obj, func); + } + + template + Callback(const T *obj, R (*func)(const T*, A0)) { + attach(obj, func); + } + + template + Callback(volatile T *obj, R (*func)(volatile T*, A0)) { + attach(obj, func); + } + + template + Callback(const volatile T *obj, R (*func)(const volatile T*, A0)) { attach(obj, func); } @@ -196,23 +334,47 @@ class Callback { * @param func Member function to attach */ template - Callback(T *obj, R (T::*func)(A0, A1, A2, A3)) { + Callback(T *obj, R (T::*func)(A0)) { attach(obj, func); } - /** Create a Callback with another Callback - * @param func Callback to attach - */ - Callback(const Callback &func) { - attach(func); + template + Callback(const T *obj, R (T::*func)(A0) const) { + attach(obj, func); + } + + template + Callback(volatile T *obj, R (T::*func)(A0) volatile) { + attach(obj, func); + } + + template + Callback(const volatile T *obj, R (T::*func)(A0) const volatile) { + attach(obj, func); } /** Attach a static function * @param func Static function to attach */ - void attach(R (*func)(A0, A1, A2, A3)) { + void attach(R (*func)(A0)) { + struct local { + static R _thunk(void*, void *func, A0 a0) { + return (*(R (**)(A0))func)( + a0); + } + }; + memcpy(&_func, &func, sizeof func); - _thunk = func ? &Callback::_staticthunk : 0; + _thunk = func ? &local::_thunk : 0; + } + + /** Attach a Callback + * @param func The Callback to attach + */ + void attach(const Callback &func) { + _obj = func._obj; + memcpy(&_func, &func._func, sizeof _func); + _thunk = func._thunk; } /** Attach a static function with a bound pointer @@ -220,10 +382,59 @@ class Callback { * @param func Static function to attach */ template - void attach(T *obj, R (*func)(T*, A0, A1, A2, A3)) { + void attach(T *obj, R (*func)(T*, A0)) { + struct local { + static R _thunk(void *obj, void *func, A0 a0) { + return (*(R (**)(T*, A0))func)( + (T*)obj, a0); + } + }; + + _obj = (void*)obj; + memcpy(&_func, &func, sizeof func); + _thunk = &local::_thunk; + } + + 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)( + (const T*)obj, a0); + } + }; + + _obj = (void*)obj; + memcpy(&_func, &func, sizeof func); + _thunk = &local::_thunk; + } + + 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)( + (volatile T*)obj, a0); + } + }; + + _obj = (void*)obj; + memcpy(&_func, &func, sizeof func); + _thunk = &local::_thunk; + } + + 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)( + (const volatile T*)obj, a0); + } + }; + _obj = (void*)obj; memcpy(&_func, &func, sizeof func); - _thunk = &Callback::_boundthunk; + _thunk = &local::_thunk; } /** Attach a member function @@ -231,34 +442,74 @@ class Callback { * @param func Member function to attach */ template - void attach(T *obj, R (T::*func)(A0, A1, A2, A3)) { - _obj = static_cast(obj); + 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))( + a0); + } + }; + + _obj = (void*)obj; memcpy(&_func, &func, sizeof func); - _thunk = &Callback::_methodthunk; + _thunk = &local::_thunk; } - /** Attach a Callback - * @param func The Callback to attach - */ - void attach(const Callback &func) { - _obj = func._obj; - memcpy(&_func, &func._func, sizeof _func); - _thunk = func._thunk; + 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))( + a0); + } + }; + + _obj = (void*)obj; + memcpy(&_func, &func, sizeof func); + _thunk = &local::_thunk; + } + + 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))( + a0); + } + }; + + _obj = (void*)obj; + memcpy(&_func, &func, sizeof func); + _thunk = &local::_thunk; + } + + 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))( + a0); + } + }; + + _obj = (void*)obj; + memcpy(&_func, &func, sizeof func); + _thunk = &local::_thunk; } /** Call the attached function */ - R call(A0 a0, A1 a1, A2 a2, A3 a3) { + R call(A0 a0) { if (!_thunk) { return (R)0; } - return _thunk(_obj, &_func, a0, a1, a2, a3); + return _thunk(_obj, &_func, a0); } /** Call the attached function */ - R operator()(A0 a0, A1 a1, A2 a2, A3 a3) { - return call(a0, a1, a2, a3); + R operator()(A0 a0) { + return call(a0); } /** Test if function has been attached @@ -270,31 +521,12 @@ class Callback { /** Static thunk for passing as C-style function * @param func Callback to call passed as void pointer */ - static R thunk(void *func, A0 a0, A1 a1, A2 a2, A3 a3) { - return static_cast*>(func) - ->call(a0, a1, a2, a3); + static R thunk(void *func, A0 a0) { + return static_cast*>(func)->call( + a0); } private: - // Internal thunks for various function types - static R _staticthunk(void*, void *func, A0 a0, A1 a1, A2 a2, A3 a3) { - return (*reinterpret_cast(func)) - (a0, a1, a2, a3); - } - - template - static R _boundthunk(void *obj, void *func, A0 a0, A1 a1, A2 a2, A3 a3) { - return (*reinterpret_cast(func)) - (static_cast(obj), a0, a1, a2, a3); - } - - template - static R _methodthunk(void *obj, void *func, A0 a0, A1 a1, A2 a2, A3 a3) { - return (static_cast(obj)->* - (*reinterpret_cast(func))) - (a0, a1, a2, a3); - } - // Stored as pointer to function and pointer to optional object // Function pointer is stored as union of possible function types // to garuntee proper size and alignment @@ -308,27 +540,49 @@ class Callback { void *_obj; // Thunk registered on attach to dispatch calls - R (*_thunk)(void*, void*, A0, A1, A2, A3); + R (*_thunk)(void*, void*, A0); }; /** Templated function class */ -template -class Callback { +template +class Callback { public: /** Create a Callback with a static function * @param func Static function to attach */ - Callback(R (*func)(A0, A1, A2) = 0) { + Callback(R (*func)(A0, A1) = 0) { 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 + /** Create a Callback with another Callback + * @param func Callback to attach */ - template - Callback(T *obj, R (*func)(T*, A0, A1, A2)) { + 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 + */ + template + Callback(T *obj, R (*func)(T*, A0, A1)) { + attach(obj, func); + } + + template + Callback(const T *obj, R (*func)(const T*, A0, A1)) { + attach(obj, func); + } + + template + Callback(volatile T *obj, R (*func)(volatile T*, A0, A1)) { + attach(obj, func); + } + + template + Callback(const volatile T *obj, R (*func)(const volatile T*, A0, A1)) { attach(obj, func); } @@ -337,23 +591,47 @@ class Callback { * @param func Member function to attach */ template - Callback(T *obj, R (T::*func)(A0, A1, A2)) { + Callback(T *obj, R (T::*func)(A0, A1)) { attach(obj, func); } - /** Create a Callback with another Callback - * @param func Callback to attach - */ - Callback(const Callback &func) { - attach(func); + template + Callback(const T *obj, R (T::*func)(A0, A1) const) { + attach(obj, func); + } + + template + Callback(volatile T *obj, R (T::*func)(A0, A1) volatile) { + attach(obj, func); + } + + template + Callback(const volatile T *obj, R (T::*func)(A0, A1) const volatile) { + attach(obj, func); } /** Attach a static function * @param func Static function to attach */ - void attach(R (*func)(A0, A1, A2)) { + void attach(R (*func)(A0, A1)) { + struct local { + static R _thunk(void*, void *func, A0 a0, A1 a1) { + return (*(R (**)(A0, A1))func)( + a0, a1); + } + }; + memcpy(&_func, &func, sizeof func); - _thunk = func ? &Callback::_staticthunk : 0; + _thunk = func ? &local::_thunk : 0; + } + + /** Attach a Callback + * @param func The Callback to attach + */ + void attach(const Callback &func) { + _obj = func._obj; + memcpy(&_func, &func._func, sizeof _func); + _thunk = func._thunk; } /** Attach a static function with a bound pointer @@ -361,10 +639,59 @@ class Callback { * @param func Static function to attach */ template - void attach(T *obj, R (*func)(T*, A0, A1, A2)) { + 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)( + (T*)obj, a0, a1); + } + }; + + _obj = (void*)obj; + memcpy(&_func, &func, sizeof func); + _thunk = &local::_thunk; + } + + 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)( + (const T*)obj, a0, a1); + } + }; + + _obj = (void*)obj; + memcpy(&_func, &func, sizeof func); + _thunk = &local::_thunk; + } + + 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)( + (volatile T*)obj, a0, a1); + } + }; + + _obj = (void*)obj; + memcpy(&_func, &func, sizeof func); + _thunk = &local::_thunk; + } + + 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)( + (const volatile T*)obj, a0, a1); + } + }; + _obj = (void*)obj; memcpy(&_func, &func, sizeof func); - _thunk = &Callback::_boundthunk; + _thunk = &local::_thunk; } /** Attach a member function @@ -372,34 +699,74 @@ class Callback { * @param func Member function to attach */ template - void attach(T *obj, R (T::*func)(A0, A1, A2)) { - _obj = static_cast(obj); + 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))( + a0, a1); + } + }; + + _obj = (void*)obj; memcpy(&_func, &func, sizeof func); - _thunk = &Callback::_methodthunk; + _thunk = &local::_thunk; } - /** Attach a Callback - * @param func The Callback to attach - */ - void attach(const Callback &func) { - _obj = func._obj; - memcpy(&_func, &func._func, sizeof _func); - _thunk = func._thunk; + 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))( + a0, a1); + } + }; + + _obj = (void*)obj; + memcpy(&_func, &func, sizeof func); + _thunk = &local::_thunk; + } + + 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))( + a0, a1); + } + }; + + _obj = (void*)obj; + memcpy(&_func, &func, sizeof func); + _thunk = &local::_thunk; + } + + 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))( + a0, a1); + } + }; + + _obj = (void*)obj; + memcpy(&_func, &func, sizeof func); + _thunk = &local::_thunk; } /** Call the attached function */ - R call(A0 a0, A1 a1, A2 a2) { + R call(A0 a0, A1 a1) { if (!_thunk) { return (R)0; } - return _thunk(_obj, &_func, a0, a1, a2); + return _thunk(_obj, &_func, a0, a1); } /** Call the attached function */ - R operator()(A0 a0, A1 a1, A2 a2) { - return call(a0, a1, a2); + R operator()(A0 a0, A1 a1) { + return call(a0, a1); } /** Test if function has been attached @@ -411,31 +778,12 @@ class Callback { /** Static thunk for passing as C-style function * @param func Callback to call passed as void pointer */ - static R thunk(void *func, A0 a0, A1 a1, A2 a2) { - return static_cast*>(func) - ->call(a0, a1, a2); + static R thunk(void *func, A0 a0, A1 a1) { + return static_cast*>(func)->call( + a0, a1); } private: - // Internal thunks for various function types - static R _staticthunk(void*, void *func, A0 a0, A1 a1, A2 a2) { - return (*reinterpret_cast(func)) - (a0, a1, a2); - } - - template - static R _boundthunk(void *obj, void *func, A0 a0, A1 a1, A2 a2) { - return (*reinterpret_cast(func)) - (static_cast(obj), a0, a1, a2); - } - - template - static R _methodthunk(void *obj, void *func, A0 a0, A1 a1, A2 a2) { - return (static_cast(obj)->* - (*reinterpret_cast(func))) - (a0, a1, a2); - } - // Stored as pointer to function and pointer to optional object // Function pointer is stored as union of possible function types // to garuntee proper size and alignment @@ -449,18 +797,25 @@ class Callback { void *_obj; // Thunk registered on attach to dispatch calls - R (*_thunk)(void*, void*, A0, A1, A2); + R (*_thunk)(void*, void*, A0, A1); }; /** Templated function class */ -template -class Callback { +template +class Callback { public: /** Create a Callback with a static function * @param func Static function to attach */ - Callback(R (*func)(A0, A1) = 0) { + Callback(R (*func)(A0, A1, A2) = 0) { + attach(func); + } + + /** Create a Callback with another Callback + * @param func Callback to attach + */ + Callback(const Callback &func) { attach(func); } @@ -469,7 +824,22 @@ class Callback { * @param func Static function to attach */ template - Callback(T *obj, R (*func)(T*, A0, A1)) { + Callback(T *obj, R (*func)(T*, A0, A1, A2)) { + attach(obj, func); + } + + template + Callback(const T *obj, R (*func)(const T*, A0, A1, A2)) { + attach(obj, func); + } + + template + Callback(volatile T *obj, R (*func)(volatile T*, A0, A1, A2)) { + attach(obj, func); + } + + template + Callback(const volatile T *obj, R (*func)(const volatile T*, A0, A1, A2)) { attach(obj, func); } @@ -478,23 +848,47 @@ class Callback { * @param func Member function to attach */ template - Callback(T *obj, R (T::*func)(A0, A1)) { + Callback(T *obj, R (T::*func)(A0, A1, A2)) { attach(obj, func); } - /** Create a Callback with another Callback - * @param func Callback to attach - */ - Callback(const Callback &func) { - attach(func); + template + Callback(const T *obj, R (T::*func)(A0, A1, A2) const) { + attach(obj, func); + } + + template + Callback(volatile T *obj, R (T::*func)(A0, A1, A2) volatile) { + attach(obj, func); + } + + template + Callback(const volatile T *obj, R (T::*func)(A0, A1, A2) const volatile) { + attach(obj, func); } /** Attach a static function * @param func Static function to attach */ - void attach(R (*func)(A0, A1)) { + 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)( + a0, a1, a2); + } + }; + memcpy(&_func, &func, sizeof func); - _thunk = func ? &Callback::_staticthunk : 0; + _thunk = func ? &local::_thunk : 0; + } + + /** Attach a Callback + * @param func The Callback to attach + */ + void attach(const Callback &func) { + _obj = func._obj; + memcpy(&_func, &func._func, sizeof _func); + _thunk = func._thunk; } /** Attach a static function with a bound pointer @@ -502,10 +896,59 @@ class Callback { * @param func Static function to attach */ template - void attach(T *obj, R (*func)(T*, A0, A1)) { + 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)( + (T*)obj, a0, a1, a2); + } + }; + + _obj = (void*)obj; + memcpy(&_func, &func, sizeof func); + _thunk = &local::_thunk; + } + + 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)( + (const T*)obj, a0, a1, a2); + } + }; + + _obj = (void*)obj; + memcpy(&_func, &func, sizeof func); + _thunk = &local::_thunk; + } + + 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)( + (volatile T*)obj, a0, a1, a2); + } + }; + + _obj = (void*)obj; + memcpy(&_func, &func, sizeof func); + _thunk = &local::_thunk; + } + + 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)( + (const volatile T*)obj, a0, a1, a2); + } + }; + _obj = (void*)obj; memcpy(&_func, &func, sizeof func); - _thunk = &Callback::_boundthunk; + _thunk = &local::_thunk; } /** Attach a member function @@ -513,34 +956,74 @@ class Callback { * @param func Member function to attach */ template - void attach(T *obj, R (T::*func)(A0, A1)) { - _obj = static_cast(obj); + 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))( + a0, a1, a2); + } + }; + + _obj = (void*)obj; memcpy(&_func, &func, sizeof func); - _thunk = &Callback::_methodthunk; + _thunk = &local::_thunk; } - /** Attach a Callback - * @param func The Callback to attach - */ - void attach(const Callback &func) { - _obj = func._obj; - memcpy(&_func, &func._func, sizeof _func); - _thunk = func._thunk; + 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))( + a0, a1, a2); + } + }; + + _obj = (void*)obj; + memcpy(&_func, &func, sizeof func); + _thunk = &local::_thunk; + } + + 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))( + a0, a1, a2); + } + }; + + _obj = (void*)obj; + memcpy(&_func, &func, sizeof func); + _thunk = &local::_thunk; + } + + 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))( + a0, a1, a2); + } + }; + + _obj = (void*)obj; + memcpy(&_func, &func, sizeof func); + _thunk = &local::_thunk; } /** Call the attached function */ - R call(A0 a0, A1 a1) { + R call(A0 a0, A1 a1, A2 a2) { if (!_thunk) { return (R)0; } - return _thunk(_obj, &_func, a0, a1); + return _thunk(_obj, &_func, a0, a1, a2); } /** Call the attached function */ - R operator()(A0 a0, A1 a1) { - return call(a0, a1); + R operator()(A0 a0, A1 a1, A2 a2) { + return call(a0, a1, a2); } /** Test if function has been attached @@ -552,31 +1035,12 @@ class Callback { /** Static thunk for passing as C-style function * @param func Callback to call passed as void pointer */ - static R thunk(void *func, A0 a0, A1 a1) { - return static_cast*>(func) - ->call(a0, a1); + static R thunk(void *func, A0 a0, A1 a1, A2 a2) { + return static_cast*>(func)->call( + a0, a1, a2); } private: - // Internal thunks for various function types - static R _staticthunk(void*, void *func, A0 a0, A1 a1) { - return (*reinterpret_cast(func)) - (a0, a1); - } - - template - static R _boundthunk(void *obj, void *func, A0 a0, A1 a1) { - return (*reinterpret_cast(func)) - (static_cast(obj), a0, a1); - } - - template - static R _methodthunk(void *obj, void *func, A0 a0, A1 a1) { - return (static_cast(obj)->* - (*reinterpret_cast(func))) - (a0, a1); - } - // Stored as pointer to function and pointer to optional object // Function pointer is stored as union of possible function types // to garuntee proper size and alignment @@ -590,18 +1054,25 @@ class Callback { void *_obj; // Thunk registered on attach to dispatch calls - R (*_thunk)(void*, void*, A0, A1); + R (*_thunk)(void*, void*, A0, A1, A2); }; /** Templated function class */ -template -class Callback { +template +class Callback { public: /** Create a Callback with a static function * @param func Static function to attach */ - Callback(R (*func)(A0) = 0) { + Callback(R (*func)(A0, A1, A2, A3) = 0) { + attach(func); + } + + /** Create a Callback with another Callback + * @param func Callback to attach + */ + Callback(const Callback &func) { attach(func); } @@ -610,7 +1081,22 @@ class Callback { * @param func Static function to attach */ template - Callback(T *obj, R (*func)(T*, A0)) { + Callback(T *obj, R (*func)(T*, A0, A1, A2, A3)) { + attach(obj, func); + } + + template + Callback(const T *obj, R (*func)(const T*, A0, A1, A2, A3)) { + attach(obj, func); + } + + template + Callback(volatile T *obj, R (*func)(volatile T*, A0, A1, A2, A3)) { + attach(obj, func); + } + + template + Callback(const volatile T *obj, R (*func)(const volatile T*, A0, A1, A2, A3)) { attach(obj, func); } @@ -619,23 +1105,47 @@ class Callback { * @param func Member function to attach */ template - Callback(T *obj, R (T::*func)(A0)) { + Callback(T *obj, R (T::*func)(A0, A1, A2, A3)) { attach(obj, func); } - /** Create a Callback with another Callback - * @param func Callback to attach - */ - Callback(const Callback &func) { - attach(func); + template + Callback(const T *obj, R (T::*func)(A0, A1, A2, A3) const) { + attach(obj, func); + } + + template + Callback(volatile T *obj, R (T::*func)(A0, A1, A2, A3) volatile) { + attach(obj, func); + } + + template + Callback(const volatile T *obj, R (T::*func)(A0, A1, A2, A3) const volatile) { + attach(obj, func); } /** Attach a static function * @param func Static function to attach */ - void attach(R (*func)(A0)) { + 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)( + a0, a1, a2, a3); + } + }; + memcpy(&_func, &func, sizeof func); - _thunk = func ? &Callback::_staticthunk : 0; + _thunk = func ? &local::_thunk : 0; + } + + /** Attach a Callback + * @param func The Callback to attach + */ + void attach(const Callback &func) { + _obj = func._obj; + memcpy(&_func, &func._func, sizeof _func); + _thunk = func._thunk; } /** Attach a static function with a bound pointer @@ -643,10 +1153,59 @@ class Callback { * @param func Static function to attach */ template - void attach(T *obj, R (*func)(T*, A0)) { + 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)( + (T*)obj, a0, a1, a2, a3); + } + }; + + _obj = (void*)obj; + memcpy(&_func, &func, sizeof func); + _thunk = &local::_thunk; + } + + 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)( + (const T*)obj, a0, a1, a2, a3); + } + }; + + _obj = (void*)obj; + memcpy(&_func, &func, sizeof func); + _thunk = &local::_thunk; + } + + 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)( + (volatile T*)obj, a0, a1, a2, a3); + } + }; + _obj = (void*)obj; memcpy(&_func, &func, sizeof func); - _thunk = &Callback::_boundthunk; + _thunk = &local::_thunk; + } + + 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)( + (const volatile T*)obj, a0, a1, a2, a3); + } + }; + + _obj = (void*)obj; + memcpy(&_func, &func, sizeof func); + _thunk = &local::_thunk; } /** Attach a member function @@ -654,34 +1213,74 @@ class Callback { * @param func Member function to attach */ template - void attach(T *obj, R (T::*func)(A0)) { - _obj = static_cast(obj); + 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))( + a0, a1, a2, a3); + } + }; + + _obj = (void*)obj; memcpy(&_func, &func, sizeof func); - _thunk = &Callback::_methodthunk; + _thunk = &local::_thunk; } - /** Attach a Callback - * @param func The Callback to attach - */ - void attach(const Callback &func) { - _obj = func._obj; - memcpy(&_func, &func._func, sizeof _func); - _thunk = func._thunk; + 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))( + a0, a1, a2, a3); + } + }; + + _obj = (void*)obj; + memcpy(&_func, &func, sizeof func); + _thunk = &local::_thunk; + } + + 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))( + a0, a1, a2, a3); + } + }; + + _obj = (void*)obj; + memcpy(&_func, &func, sizeof func); + _thunk = &local::_thunk; + } + + 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))( + a0, a1, a2, a3); + } + }; + + _obj = (void*)obj; + memcpy(&_func, &func, sizeof func); + _thunk = &local::_thunk; } /** Call the attached function */ - R call(A0 a0) { + R call(A0 a0, A1 a1, A2 a2, A3 a3) { if (!_thunk) { return (R)0; } - return _thunk(_obj, &_func, a0); + return _thunk(_obj, &_func, a0, a1, a2, a3); } /** Call the attached function */ - R operator()(A0 a0) { - return call(a0); + R operator()(A0 a0, A1 a1, A2 a2, A3 a3) { + return call(a0, a1, a2, a3); } /** Test if function has been attached @@ -693,31 +1292,12 @@ class Callback { /** Static thunk for passing as C-style function * @param func Callback to call passed as void pointer */ - static R thunk(void *func, A0 a0) { - return static_cast*>(func) - ->call(a0); + static R thunk(void *func, A0 a0, A1 a1, A2 a2, A3 a3) { + return static_cast*>(func)->call( + a0, a1, a2, a3); } private: - // Internal thunks for various function types - static R _staticthunk(void*, void *func, A0 a0) { - return (*reinterpret_cast(func)) - (a0); - } - - template - static R _boundthunk(void *obj, void *func, A0 a0) { - return (*reinterpret_cast(func)) - (static_cast(obj), a0); - } - - template - static R _methodthunk(void *obj, void *func, A0 a0) { - return (static_cast(obj)->* - (*reinterpret_cast(func))) - (a0); - } - // Stored as pointer to function and pointer to optional object // Function pointer is stored as union of possible function types // to garuntee proper size and alignment @@ -731,18 +1311,25 @@ class Callback { void *_obj; // Thunk registered on attach to dispatch calls - R (*_thunk)(void*, void*, A0); + R (*_thunk)(void*, void*, A0, A1, A2, A3); }; /** Templated function class */ -template -class Callback { +template +class Callback { public: /** Create a Callback with a static function * @param func Static function to attach */ - Callback(R (*func)() = 0) { + Callback(R (*func)(A0, A1, A2, A3, A4) = 0) { + attach(func); + } + + /** Create a Callback with another Callback + * @param func Callback to attach + */ + Callback(const Callback &func) { attach(func); } @@ -751,7 +1338,22 @@ class Callback { * @param func Static function to attach */ template - Callback(T *obj, R (*func)(T*)) { + Callback(T *obj, R (*func)(T*, A0, A1, A2, A3, A4)) { + attach(obj, func); + } + + template + Callback(const T *obj, R (*func)(const T*, A0, A1, A2, A3, A4)) { + attach(obj, func); + } + + template + Callback(volatile T *obj, R (*func)(volatile T*, A0, A1, A2, A3, A4)) { + attach(obj, func); + } + + template + Callback(const volatile T *obj, R (*func)(const volatile T*, A0, A1, A2, A3, A4)) { attach(obj, func); } @@ -760,23 +1362,47 @@ class Callback { * @param func Member function to attach */ template - Callback(T *obj, R (T::*func)()) { + Callback(T *obj, R (T::*func)(A0, A1, A2, A3, A4)) { attach(obj, func); } - /** Create a Callback with another Callback - * @param func Callback to attach - */ - Callback(const Callback &func) { - attach(func); + template + Callback(const T *obj, R (T::*func)(A0, A1, A2, A3, A4) const) { + attach(obj, func); + } + + template + Callback(volatile T *obj, R (T::*func)(A0, A1, A2, A3, A4) volatile) { + attach(obj, func); + } + + template + Callback(const volatile T *obj, R (T::*func)(A0, A1, A2, A3, A4) const volatile) { + attach(obj, func); } /** Attach a static function * @param func Static function to attach */ - void attach(R (*func)()) { + 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)( + a0, a1, a2, a3, a4); + } + }; + memcpy(&_func, &func, sizeof func); - _thunk = func ? &Callback::_staticthunk : 0; + _thunk = func ? &local::_thunk : 0; + } + + /** Attach a Callback + * @param func The Callback to attach + */ + void attach(const Callback &func) { + _obj = func._obj; + memcpy(&_func, &func._func, sizeof _func); + _thunk = func._thunk; } /** Attach a static function with a bound pointer @@ -784,10 +1410,59 @@ class Callback { * @param func Static function to attach */ template - void attach(T *obj, R (*func)(T*)) { + 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)( + (T*)obj, a0, a1, a2, a3, a4); + } + }; + + _obj = (void*)obj; + memcpy(&_func, &func, sizeof func); + _thunk = &local::_thunk; + } + + 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)( + (const T*)obj, a0, a1, a2, a3, a4); + } + }; + + _obj = (void*)obj; + memcpy(&_func, &func, sizeof func); + _thunk = &local::_thunk; + } + + 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)( + (volatile T*)obj, a0, a1, a2, a3, a4); + } + }; + + _obj = (void*)obj; + memcpy(&_func, &func, sizeof func); + _thunk = &local::_thunk; + } + + 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)( + (const volatile T*)obj, a0, a1, a2, a3, a4); + } + }; + _obj = (void*)obj; memcpy(&_func, &func, sizeof func); - _thunk = &Callback::_boundthunk; + _thunk = &local::_thunk; } /** Attach a member function @@ -795,34 +1470,74 @@ class Callback { * @param func Member function to attach */ template - void attach(T *obj, R (T::*func)()) { - _obj = static_cast(obj); + 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))( + a0, a1, a2, a3, a4); + } + }; + + _obj = (void*)obj; memcpy(&_func, &func, sizeof func); - _thunk = &Callback::_methodthunk; + _thunk = &local::_thunk; } - /** Attach a Callback - * @param func The Callback to attach - */ - void attach(const Callback &func) { - _obj = func._obj; - memcpy(&_func, &func._func, sizeof _func); - _thunk = func._thunk; + 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))( + a0, a1, a2, a3, a4); + } + }; + + _obj = (void*)obj; + memcpy(&_func, &func, sizeof func); + _thunk = &local::_thunk; + } + + 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))( + a0, a1, a2, a3, a4); + } + }; + + _obj = (void*)obj; + memcpy(&_func, &func, sizeof func); + _thunk = &local::_thunk; + } + + 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))( + a0, a1, a2, a3, a4); + } + }; + + _obj = (void*)obj; + memcpy(&_func, &func, sizeof func); + _thunk = &local::_thunk; } /** Call the attached function */ - R call() { + R call(A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) { if (!_thunk) { return (R)0; } - return _thunk(_obj, &_func); + return _thunk(_obj, &_func, a0, a1, a2, a3, a4); } /** Call the attached function */ - R operator()() { - return call(); + R operator()(A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) { + return call(a0, a1, a2, a3, a4); } /** Test if function has been attached @@ -834,31 +1549,12 @@ class Callback { /** Static thunk for passing as C-style function * @param func Callback to call passed as void pointer */ - static R thunk(void *func) { - return static_cast*>(func) - ->call(); + static R thunk(void *func, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) { + return static_cast*>(func)->call( + a0, a1, a2, a3, a4); } private: - // Internal thunks for various function types - static R _staticthunk(void*, void *func) { - return (*reinterpret_cast(func)) - (); - } - - template - static R _boundthunk(void *obj, void *func) { - return (*reinterpret_cast(func)) - (static_cast(obj)); - } - - template - static R _methodthunk(void *obj, void *func) { - return (static_cast(obj)->* - (*reinterpret_cast(func))) - (); - } - // Stored as pointer to function and pointer to optional object // Function pointer is stored as union of possible function types // to garuntee proper size and alignment @@ -872,10 +1568,311 @@ class Callback { void *_obj; // Thunk registered on attach to dispatch calls - R (*_thunk)(void*, void*); + R (*_thunk)(void*, void*, A0, A1, A2, A3, A4); }; - typedef Callback event_callback_t; +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 + */ +template +Callback callback(R (*func)() = 0) { + return Callback(func); +} + +template +Callback callback(const Callback &func) { + return Callback(func); +} +template +Callback callback(T *obj, R (*func)(T*)) { + return Callback(obj, func); +} + +template +Callback callback(const T *obj, R (*func)(const T*)) { + return Callback(obj, func); +} + +template +Callback callback(volatile T *obj, R (*func)(volatile T*)) { + return Callback(obj, func); +} + +template +Callback callback(const volatile T *obj, R (*func)(const volatile T*)) { + return Callback(obj, func); +} + +template +Callback callback(T *obj, R (T::*func)()) { + return Callback(obj, func); +} + +template +Callback callback(const T *obj, R (T::*func)() const) { + return Callback(obj, func); +} + +template +Callback callback(volatile T *obj, R (T::*func)() volatile) { + return Callback(obj, func); +} + +template +Callback callback(const volatile T *obj, R (T::*func)() const volatile) { + return Callback(obj, func); +} + +template +Callback callback(R (*func)(A0) = 0) { + return Callback(func); +} + +template +Callback callback(const Callback &func) { + return Callback(func); +} +template +Callback callback(T *obj, R (*func)(T*, A0)) { + return Callback(obj, func); +} + +template +Callback callback(const T *obj, R (*func)(const T*, A0)) { + return Callback(obj, func); +} + +template +Callback callback(volatile T *obj, R (*func)(volatile T*, A0)) { + return Callback(obj, func); +} + +template +Callback callback(const volatile T *obj, R (*func)(const volatile T*, A0)) { + return Callback(obj, func); +} + +template +Callback callback(T *obj, R (T::*func)(A0)) { + return Callback(obj, func); +} + +template +Callback callback(const T *obj, R (T::*func)(A0) const) { + return Callback(obj, func); +} + +template +Callback callback(volatile T *obj, R (T::*func)(A0) volatile) { + return Callback(obj, func); +} + +template +Callback callback(const volatile T *obj, R (T::*func)(A0) const volatile) { + return Callback(obj, func); +} + +template +Callback callback(R (*func)(A0, A1) = 0) { + return Callback(func); +} + +template +Callback callback(const Callback &func) { + return Callback(func); +} +template +Callback callback(T *obj, R (*func)(T*, A0, A1)) { + return Callback(obj, func); +} + +template +Callback callback(const T *obj, R (*func)(const T*, A0, A1)) { + return Callback(obj, func); +} + +template +Callback callback(volatile T *obj, R (*func)(volatile T*, A0, A1)) { + return Callback(obj, func); +} + +template +Callback callback(const volatile T *obj, R (*func)(const volatile T*, A0, A1)) { + return Callback(obj, func); +} + +template +Callback callback(T *obj, R (T::*func)(A0, A1)) { + return Callback(obj, func); +} + +template +Callback callback(const T *obj, R (T::*func)(A0, A1) const) { + return Callback(obj, func); +} + +template +Callback callback(volatile T *obj, R (T::*func)(A0, A1) volatile) { + return Callback(obj, func); +} + +template +Callback callback(const volatile T *obj, R (T::*func)(A0, A1) const volatile) { + return Callback(obj, func); +} + +template +Callback callback(R (*func)(A0, A1, A2) = 0) { + return Callback(func); +} + +template +Callback callback(const Callback &func) { + return Callback(func); +} +template +Callback callback(T *obj, R (*func)(T*, A0, A1, A2)) { + return Callback(obj, func); +} + +template +Callback callback(const T *obj, R (*func)(const T*, A0, A1, A2)) { + return Callback(obj, func); +} + +template +Callback callback(volatile T *obj, R (*func)(volatile T*, A0, A1, A2)) { + return Callback(obj, func); +} + +template +Callback callback(const volatile T *obj, R (*func)(const volatile T*, A0, A1, A2)) { + return Callback(obj, func); +} + +template +Callback callback(T *obj, R (T::*func)(A0, A1, A2)) { + return Callback(obj, func); +} + +template +Callback callback(const T *obj, R (T::*func)(A0, A1, A2) const) { + return Callback(obj, func); +} + +template +Callback callback(volatile T *obj, R (T::*func)(A0, A1, A2) volatile) { + return Callback(obj, func); +} + +template +Callback callback(const volatile T *obj, R (T::*func)(A0, A1, A2) const volatile) { + return Callback(obj, func); +} + +template +Callback callback(R (*func)(A0, A1, A2, A3) = 0) { + return Callback(func); +} + +template +Callback callback(const Callback &func) { + return Callback(func); +} +template +Callback callback(T *obj, R (*func)(T*, A0, A1, A2, A3)) { + return Callback(obj, func); +} + +template +Callback callback(const T *obj, R (*func)(const T*, A0, A1, A2, A3)) { + return Callback(obj, func); +} + +template +Callback callback(volatile T *obj, R (*func)(volatile T*, A0, A1, A2, A3)) { + return Callback(obj, func); +} + +template +Callback callback(const volatile T *obj, R (*func)(const volatile T*, A0, A1, A2, A3)) { + return Callback(obj, func); +} + +template +Callback callback(T *obj, R (T::*func)(A0, A1, A2, A3)) { + return Callback(obj, func); +} + +template +Callback callback(const T *obj, R (T::*func)(A0, A1, A2, A3) const) { + return Callback(obj, func); +} + +template +Callback callback(volatile T *obj, R (T::*func)(A0, A1, A2, A3) volatile) { + return Callback(obj, func); +} + +template +Callback callback(const volatile T *obj, R (T::*func)(A0, A1, A2, A3) const volatile) { + return Callback(obj, func); +} + +template +Callback callback(R (*func)(A0, A1, A2, A3, A4) = 0) { + return Callback(func); +} + +template +Callback callback(const Callback &func) { + return Callback(func); +} +template +Callback callback(T *obj, R (*func)(T*, A0, A1, A2, A3, A4)) { + return Callback(obj, func); +} + +template +Callback callback(const T *obj, R (*func)(const T*, A0, A1, A2, A3, A4)) { + return Callback(obj, func); +} + +template +Callback callback(volatile T *obj, R (*func)(volatile T*, A0, A1, A2, A3, A4)) { + return Callback(obj, func); +} + +template +Callback callback(const volatile T *obj, R (*func)(const volatile T*, A0, A1, A2, A3, A4)) { + return Callback(obj, func); +} + +template +Callback callback(T *obj, R (T::*func)(A0, A1, A2, A3, A4)) { + return Callback(obj, func); +} + +template +Callback callback(const T *obj, R (T::*func)(A0, A1, A2, A3, A4) const) { + return Callback(obj, func); +} + +template +Callback callback(volatile T *obj, R (T::*func)(A0, A1, A2, A3, A4) volatile) { + return Callback(obj, func); +} + +template +Callback callback(const volatile T *obj, R (T::*func)(A0, A1, A2, A3, A4) const volatile) { + return Callback(obj, func); +} } // namespace mbed diff --git a/hal/api/InterruptIn.h b/hal/api/InterruptIn.h index 3758ab5ca34..fcb7df4b81d 100644 --- a/hal/api/InterruptIn.h +++ b/hal/api/InterruptIn.h @@ -24,6 +24,7 @@ #include "gpio_irq_api.h" #include "Callback.h" #include "critical.h" +#include "toolchain.h" namespace mbed { @@ -88,11 +89,17 @@ class InterruptIn { * * @param obj pointer to the object to call the member function on * @param method pointer to the member function to be called + * @deprecated + * The rise function does not support cv-qualifiers. Replaced by + * rise(callback(obj, method)). */ template + MBED_DEPRECATED_SINCE("mbed-os-5.1", + "The rise function does not support cv-qualifiers. Replaced by " + "rise(callback(obj, method)).") void rise(T *obj, M method) { core_util_critical_section_enter(); - rise(Callback(obj, method)); + rise(callback(obj, method)); core_util_critical_section_exit(); } @@ -106,11 +113,17 @@ class InterruptIn { * * @param obj pointer to the object to call the member function on * @param method pointer to the member function to be called + * @deprecated + * The rise function does not support cv-qualifiers. Replaced by + * rise(callback(obj, method)). */ template + MBED_DEPRECATED_SINCE("mbed-os-5.1", + "The fall function does not support cv-qualifiers. Replaced by " + "fall(callback(obj, method)).") void fall(T *obj, M method) { core_util_critical_section_enter(); - fall(Callback(obj, method)); + fall(callback(obj, method)); core_util_critical_section_exit(); } diff --git a/hal/api/SerialBase.h b/hal/api/SerialBase.h index 1d7ae7c34dd..be792930953 100644 --- a/hal/api/SerialBase.h +++ b/hal/api/SerialBase.h @@ -23,6 +23,7 @@ #include "Stream.h" #include "Callback.h" #include "serial_api.h" +#include "toolchain.h" #if DEVICE_SERIAL_ASYNCH #include "CThunk.h" @@ -101,10 +102,16 @@ class SerialBase { * @param obj pointer to the object to call the member function on * @param method pointer to the member function to be called * @param type Which serial interrupt to attach the member function to (Seriall::RxIrq for receive, TxIrq for transmit buffer empty) + * @deprecated + * The attach function does not support cv-qualifiers. Replaced by + * attach(callback(obj, method), type). */ template + MBED_DEPRECATED_SINCE("mbed-os-5.1", + "The attach function does not support cv-qualifiers. Replaced by " + "attach(callback(obj, method), type).") void attach(T *obj, void (T::*method)(), IrqType type=RxIrq) { - attach(Callback(obj, method), type); + attach(callback(obj, method), type); } /** Attach a member function to call whenever a serial interrupt is generated @@ -112,10 +119,16 @@ class SerialBase { * @param obj pointer to the object to call the member function on * @param method pointer to the member function to be called * @param type Which serial interrupt to attach the member function to (Seriall::RxIrq for receive, TxIrq for transmit buffer empty) + * @deprecated + * The attach function does not support cv-qualifiers. Replaced by + * attach(callback(obj, method), type). */ template + MBED_DEPRECATED_SINCE("mbed-os-5.1", + "The attach function does not support cv-qualifiers. Replaced by " + "attach(callback(obj, method), type).") void attach(T *obj, void (*method)(T*), IrqType type=RxIrq) { - attach(Callback(obj, method), type); + attach(callback(obj, method), type); } /** Generate a break condition on the serial line diff --git a/hal/api/Ticker.h b/hal/api/Ticker.h index a7848ece4d6..5b2f97ba950 100644 --- a/hal/api/Ticker.h +++ b/hal/api/Ticker.h @@ -18,6 +18,7 @@ #include "TimerEvent.h" #include "Callback.h" +#include "toolchain.h" namespace mbed { @@ -80,10 +81,16 @@ class Ticker : public TimerEvent { * @param obj pointer to the object to call the member function on * @param method pointer to the member function to be called * @param t the time between calls in seconds + * @deprecated + * The attach function does not support cv-qualifiers. Replaced by + * attach(callback(obj, method), t). */ template + MBED_DEPRECATED_SINCE("mbed-os-5.1", + "The attach function does not support cv-qualifiers. Replaced by " + "attach(callback(obj, method), t).") void attach(T *obj, M method, float t) { - attach(Callback(obj, method), t); + attach(callback(obj, method), t); } /** Attach a function to be called by the Ticker, specifiying the interval in micro-seconds @@ -101,8 +108,14 @@ class Ticker : public TimerEvent { * @param tptr pointer to the object to call the member function on * @param mptr pointer to the member function to be called * @param t the time between calls in micro-seconds + * @deprecated + * The attach_us function does not support cv-qualifiers. Replaced by + * attach_us(callback(obj, method), t). */ template + MBED_DEPRECATED_SINCE("mbed-os-5.1", + "The attach_us function does not support cv-qualifiers. Replaced by " + "attach_us(callback(obj, method), t).") void attach_us(T *obj, M method, timestamp_t t) { attach_us(Callback(obj, method), t); } diff --git a/rtos/rtos/RtosTimer.h b/rtos/rtos/RtosTimer.h index ab698ebd36b..3f39a3999af 100644 --- a/rtos/rtos/RtosTimer.h +++ b/rtos/rtos/RtosTimer.h @@ -47,7 +47,7 @@ class RtosTimer { MBED_DEPRECATED_SINCE("mbed-os-5.1", "Replaced with RtosTimer(Callback, os_timer_type)") RtosTimer(void (*func)(void const *argument), os_timer_type type=osTimerPeriodic, void *argument=NULL) { - constructor(mbed::Callback(argument, (void (*)(void *))func), type); + constructor(mbed::callback(argument, (void (*)(void *))func), type); } /** Create timer. @@ -62,10 +62,16 @@ class RtosTimer { @param obj pointer to the object to call the member function on. @param method member function to be executed by this timer. @param type osTimerOnce for one-shot or osTimerPeriodic for periodic behaviour. (default: osTimerPeriodic) + @deprecated + The RtosTimer constructor does not support cv-qualifiers. Replaced by + RtosTimer(callback(obj, method), os_timer_type). */ template + MBED_DEPRECATED_SINCE("mbed-os-5.1", + "The RtosTimer constructor does not support cv-qualifiers. Replaced by " + "RtosTimer(callback(obj, method), os_timer_type).") RtosTimer(T *obj, M method, os_timer_type type=osTimerPeriodic) { - constructor(mbed::Callback(obj, method), type); + constructor(mbed::callback(obj, method), type); } /** Stop the timer. diff --git a/rtos/rtos/Thread.h b/rtos/rtos/Thread.h index eb1c39beab9..9d3356a6078 100644 --- a/rtos/rtos/Thread.h +++ b/rtos/rtos/Thread.h @@ -90,7 +90,7 @@ class Thread { osPriority priority=osPriorityNormal, uint32_t stack_size=DEFAULT_STACK_SIZE, unsigned char *stack_pointer=NULL) { - constructor(mbed::Callback(obj, method), + constructor(mbed::callback(obj, method), priority, stack_size, stack_pointer); } @@ -116,7 +116,7 @@ class Thread { osPriority priority=osPriorityNormal, uint32_t stack_size=DEFAULT_STACK_SIZE, unsigned char *stack_pointer=NULL) { - constructor(mbed::Callback(obj, method), + constructor(mbed::callback(obj, method), priority, stack_size, stack_pointer); } @@ -141,7 +141,7 @@ class Thread { osPriority priority=osPriorityNormal, uint32_t stack_size=DEFAULT_STACK_SIZE, unsigned char *stack_pointer=NULL) { - constructor(mbed::Callback(argument, (void (*)(void *))task), + constructor(mbed::callback(argument, (void (*)(void *))task), priority, stack_size, stack_pointer); } @@ -155,10 +155,16 @@ class Thread { @param obj argument to task @param method function to be executed by this thread. @return status code that indicates the execution status of the function. + @deprecated + The start function does not support cv-qualifiers. Replaced by + start(callback(obj, method)). */ template + MBED_DEPRECATED_SINCE("mbed-os-5.1", + "The start function does not support cv-qualifiers. Replaced by " + "start(callback(obj, method)).") osStatus start(T *obj, M method) { - return start(mbed::Callback(obj, method)); + return start(mbed::callback(obj, method)); } /** Wait for thread to terminate From c71e67f2dcf2a75c225fbecf16921949100ca6c9 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Fri, 19 Aug 2016 15:49:49 -0500 Subject: [PATCH 2/5] 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 | 132 +-- hal/api/Callback.h | 1263 +++++++++++++++++++++----- hal/api/FunctionPointer.h | 24 + hal/common/CAN.cpp | 8 + hal/common/InterruptIn.cpp | 10 +- hal/common/SerialBase.cpp | 7 + 6 files changed, 1108 insertions(+), 336 deletions(-) diff --git a/TESTS/mbed_drivers/callback/main.cpp b/TESTS/mbed_drivers/callback/main.cpp index d4f0e9af57b..403968a039b 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 8a415bb6c4b..fa784386551 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 @@ class Callback { 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 @@ class Callback { 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 @@ class Callback { 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 @@ class Callback { */ 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 @@ class Callback { * @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 @@ class Callback { 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 @@ class Callback { 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 @@ class Callback { 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 @@ class Callback { 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 @@ class Callback { 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 @@ class Callback { 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 @@ class Callback { 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 @@ class Callback { */ 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 @@ class Callback { * @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 @@ class Callback { 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 @@ class Callback { 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 @@ class Callback { 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 @@ class Callback { 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 @@ class Callback { 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 @@ class Callback { 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 @@ class Callback { 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 @@ class Callback { */ 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 @@ class Callback { * @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 @@ class Callback { 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 @@ class Callback { 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 @@ class Callback { 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 @@ class Callback { 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 @@ class Callback { 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 @@ class Callback { 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 @@ class Callback { 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); } - template - Callback(volatile T *obj, R (T::*func)(A0, A1, A2) volatile) { + /** 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 @@ class Callback { */ 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 @@ class Callback { * @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 @@ class Callback { 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 @@ class Callback { 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 @@ class Callback { 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 @@ class Callback { 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 @@ class Callback { 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 @@ class Callback { 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 @@ class Callback { 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 @@ class Callback { */ 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 @@ class Callback { * @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 @@ class Callback { 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 @@ class Callback { 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 @@ class Callback { 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 @@ class Callback { 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 @@ class Callback { 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 @@ class Callback { 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 @@ class Callback { 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 @@ class Callback { */ 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 @@ class Callback { * @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 @@ class Callback { 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 @@ class Callback { 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 @@ class Callback { 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 @@ class Callback { 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 1626e3e483b..af51a8c9291 100644 --- a/hal/api/FunctionPointer.h +++ b/hal/api/FunctionPointer.h @@ -43,6 +43,18 @@ class FunctionPointerArg1 : public Callback { 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 @@ class FunctionPointerArg1 : public Callback { 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 780a106b73d..84355b02302 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 0e5bde9bc21..d3986e88930 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 891c4509751..d75e479418c 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(); From 5c0f39f190dace90c1428c1b64d758db6561939c Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Thu, 25 Aug 2016 10:36:29 -0500 Subject: [PATCH 3/5] Split callback test into multiple tests based on types As the templated tests grew, the resulting binary exceeded a flash size of 64K. This caused the test to incorrectly fail on small devices. Moved and split into the following: TESTS/mbed_functional/callback TESTS/mbed_functional/callback_small TESTS/mbed_functional/callback_big TESTS/mbed_functional/functionpointer --- TESTS/mbed_functional/callback/main.cpp | 351 ++++++++++++++++++ TESTS/mbed_functional/callback_big/main.cpp | 351 ++++++++++++++++++ .../callback_small}/main.cpp | 33 -- .../mbed_functional/functionpointer/main.cpp | 225 +++++++++++ 4 files changed, 927 insertions(+), 33 deletions(-) create mode 100644 TESTS/mbed_functional/callback/main.cpp create mode 100644 TESTS/mbed_functional/callback_big/main.cpp rename TESTS/{mbed_drivers/callback => mbed_functional/callback_small}/main.cpp (91%) create mode 100644 TESTS/mbed_functional/functionpointer/main.cpp diff --git a/TESTS/mbed_functional/callback/main.cpp b/TESTS/mbed_functional/callback/main.cpp new file mode 100644 index 00000000000..8442448e538 --- /dev/null +++ b/TESTS/mbed_functional/callback/main.cpp @@ -0,0 +1,351 @@ +#include "mbed.h" +#include "greentea-client/test_env.h" +#include "unity.h" +#include "utest.h" + +using namespace utest::v1; + + +// static functions +template +T static_func0() { return 0; } +template +T static_func1(T a0) { return 0 | a0; } +template +T static_func2(T a0, T a1) { return 0 | a0 | a1; } +template +T static_func3(T a0, T a1, T a2) { return 0 | a0 | a1 | a2; } +template +T static_func4(T a0, T a1, T a2, T a3) { return 0 | a0 | a1 | a2 | a3; } +template +T static_func5(T a0, T a1, T a2, T a3, T a4) { return 0 | a0 | a1 | a2 | a3 | a4; } + +// class functions +template +struct Thing { + T t; + Thing() : t(0x80) {} + + T member_func0() { return t; } + T member_func1(T a0) { return t | a0; } + T member_func2(T a0, T a1) { return t | a0 | a1; } + T member_func3(T a0, T a1, T a2) { return t | a0 | a1 | a2; } + T member_func4(T a0, T a1, T a2, T a3) { return t | a0 | a1 | a2 | a3; } + T member_func5(T a0, T a1, T a2, T a3, T a4) { return t | a0 | a1 | a2 | a3 | a4; } + + T const_member_func0() const { return t; } + T const_member_func1(T a0) const { return t | a0; } + T const_member_func2(T a0, T a1) const { return t | a0 | a1; } + T const_member_func3(T a0, T a1, T a2) const { return t | a0 | a1 | a2; } + T const_member_func4(T a0, T a1, T a2, T a3) const { return t | a0 | a1 | a2 | a3; } + T const_member_func5(T a0, T a1, T a2, T a3, T a4) const { return t | a0 | a1 | a2 | a3 | a4; } + + T volatile_member_func0() volatile { return t; } + T volatile_member_func1(T a0) volatile { return t | a0; } + T volatile_member_func2(T a0, T a1) volatile { return t | a0 | a1; } + T volatile_member_func3(T a0, T a1, T a2) volatile { return t | a0 | a1 | a2; } + T volatile_member_func4(T a0, T a1, T a2, T a3) volatile { return t | a0 | a1 | a2 | a3; } + T volatile_member_func5(T a0, T a1, T a2, T a3, T a4) volatile { return t | a0 | a1 | a2 | a3 | a4; } + + T const_volatile_member_func0() const volatile { return t; } + T const_volatile_member_func1(T a0) const volatile { return t | a0; } + T const_volatile_member_func2(T a0, T a1) const volatile { return t | a0 | a1; } + T const_volatile_member_func3(T a0, T a1, T a2) const volatile { return t | a0 | a1 | a2; } + T const_volatile_member_func4(T a0, T a1, T a2, T a3) const volatile { return t | a0 | a1 | a2 | a3; } + T const_volatile_member_func5(T a0, T a1, T a2, T a3, T a4) const volatile { return t | a0 | a1 | a2 | a3 | a4; } +}; + +// bound functions +template +T bound_func0(Thing *t) { return t->t; } +template +T bound_func1(Thing *t, T a0) { return t->t | a0; } +template +T bound_func2(Thing *t, T a0, T a1) { return t->t | a0 | a1; } +template +T bound_func3(Thing *t, T a0, T a1, T a2) { return t->t | a0 | a1 | a2; } +template +T bound_func4(Thing *t, T a0, T a1, T a2, T a3) { return t->t | a0 | a1 | a2 | a3; } +template +T bound_func5(Thing *t, T a0, T a1, T a2, T a3, T a4) { return t->t | a0 | a1 | a2 | a3 | a4; } + +// const bound functions +template +T const_func0(const Thing *t) { return t->t; } +template +T const_func1(const Thing *t, T a0) { return t->t | a0; } +template +T const_func2(const Thing *t, T a0, T a1) { return t->t | a0 | a1; } +template +T const_func3(const Thing *t, T a0, T a1, T a2) { return t->t | a0 | a1 | a2; } +template +T const_func4(const Thing *t, T a0, T a1, T a2, T a3) { return t->t | a0 | a1 | a2 | a3; } +template +T const_func5(const Thing *t, T a0, T a1, T a2, T a3, T a4) { return t->t | a0 | a1 | a2 | a3 | a4; } + +// volatile bound functions +template +T volatile_func0(volatile Thing *t) { return t->t; } +template +T volatile_func1(volatile Thing *t, T a0) { return t->t | a0; } +template +T volatile_func2(volatile Thing *t, T a0, T a1) { return t->t | a0 | a1; } +template +T volatile_func3(volatile Thing *t, T a0, T a1, T a2) { return t->t | a0 | a1 | a2; } +template +T volatile_func4(volatile Thing *t, T a0, T a1, T a2, T a3) { return t->t | a0 | a1 | a2 | a3; } +template +T volatile_func5(volatile Thing *t, T a0, T a1, T a2, T a3, T a4) { return t->t | a0 | a1 | a2 | a3 | a4; } + +// const volatile bound functions +template +T const_volatile_func0(const volatile Thing *t) { return t->t; } +template +T const_volatile_func1(const volatile Thing *t, T a0) { return t->t | a0; } +template +T const_volatile_func2(const volatile Thing *t, T a0, T a1) { return t->t | a0 | a1; } +template +T const_volatile_func3(const volatile Thing *t, T a0, T a1, T a2) { return t->t | a0 | a1 | a2; } +template +T const_volatile_func4(const volatile Thing *t, T a0, T a1, T a2, T a3) { return t->t | a0 | a1 | a2 | a3; } +template +T const_volatile_func5(const volatile Thing *t, T a0, T a1, T a2, T a3, T a4) { return t->t | a0 | a1 | a2 | a3 | a4; } + + +// function call and result verification +template +struct Verifier { + static void verify0(Callback func) { + T result = func(); + TEST_ASSERT_EQUAL(result, 0x00); + } + + template + static void verify0(O *obj, M method) { + Callback func(obj, method); + T result = func(); + TEST_ASSERT_EQUAL(result, 0x80); + } + + static void verify1(Callback func) { + T result = func((1 << 0)); + TEST_ASSERT_EQUAL(result, 0x00 | (1 << 0)); + } + + template + static void verify1(O *obj, M method) { + Callback func(obj, method); + T result = func((1 << 0)); + TEST_ASSERT_EQUAL(result, 0x80 | (1 << 0)); + } + + static void verify2(Callback func) { + T result = func((1 << 0), (1 << 1)); + TEST_ASSERT_EQUAL(result, 0x00 | (1 << 0) | (1 << 1)); + } + + template + static void verify2(O *obj, M method) { + Callback func(obj, method); + T result = func((1 << 0), (1 << 1)); + TEST_ASSERT_EQUAL(result, 0x80 | (1 << 0) | (1 << 1)); + } + + static void verify3(Callback func) { + T result = func((1 << 0), (1 << 1), (1 << 2)); + TEST_ASSERT_EQUAL(result, 0x00 | (1 << 0) | (1 << 1) | (1 << 2)); + } + + template + static void verify3(O *obj, M method) { + Callback func(obj, method); + T result = func((1 << 0), (1 << 1), (1 << 2)); + TEST_ASSERT_EQUAL(result, 0x80 | (1 << 0) | (1 << 1) | (1 << 2)); + } + + static void verify4(Callback func) { + T result = func((1 << 0), (1 << 1), (1 << 2), (1 << 3)); + TEST_ASSERT_EQUAL(result, 0x00 | (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3)); + } + + template + static void verify4(O *obj, M method) { + Callback func(obj, method); + T result = func((1 << 0), (1 << 1), (1 << 2), (1 << 3)); + TEST_ASSERT_EQUAL(result, 0x80 | (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3)); + } + + static void verify5(Callback func) { + T result = func((1 << 0), (1 << 1), (1 << 2), (1 << 3), (1 << 4)); + TEST_ASSERT_EQUAL(result, 0x00 | (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4)); + } + + template + static void verify5(O *obj, M method) { + Callback func(obj, method); + T result = func((1 << 0), (1 << 1), (1 << 2), (1 << 3), (1 << 4)); + TEST_ASSERT_EQUAL(result, 0x80 | (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4)); + } +}; + + +// test dispatch +template +void test_dispatch0() { + Thing thing; + Verifier::verify0(static_func0); + Verifier::verify0(&thing, &Thing::member_func0); + Verifier::verify0((const Thing*)&thing, &Thing::const_member_func0); + Verifier::verify0((volatile Thing*)&thing, &Thing::volatile_member_func0); + Verifier::verify0((const volatile Thing*)&thing, &Thing::const_volatile_member_func0); + Verifier::verify0(&thing, &bound_func0); + Verifier::verify0((const Thing*)&thing, &const_func0); + Verifier::verify0((volatile Thing*)&thing, &volatile_func0); + Verifier::verify0((const volatile Thing*)&thing, &const_volatile_func0); + Verifier::verify0(callback(static_func0)); + + 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 +void test_dispatch1() { + Thing thing; + Verifier::verify1(static_func1); + Verifier::verify1(&thing, &Thing::member_func1); + Verifier::verify1((const Thing*)&thing, &Thing::const_member_func1); + Verifier::verify1((volatile Thing*)&thing, &Thing::volatile_member_func1); + Verifier::verify1((const volatile Thing*)&thing, &Thing::const_volatile_member_func1); + Verifier::verify1(&thing, &bound_func1); + Verifier::verify1((const Thing*)&thing, &const_func1); + Verifier::verify1((volatile Thing*)&thing, &volatile_func1); + Verifier::verify1((const volatile Thing*)&thing, &const_volatile_func1); + Verifier::verify1(callback(static_func1)); + + 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 +void test_dispatch2() { + Thing thing; + Verifier::verify2(static_func2); + Verifier::verify2(&thing, &Thing::member_func2); + Verifier::verify2((const Thing*)&thing, &Thing::const_member_func2); + Verifier::verify2((volatile Thing*)&thing, &Thing::volatile_member_func2); + Verifier::verify2((const volatile Thing*)&thing, &Thing::const_volatile_member_func2); + Verifier::verify2(&thing, &bound_func2); + Verifier::verify2((const Thing*)&thing, &const_func2); + Verifier::verify2((volatile Thing*)&thing, &volatile_func2); + Verifier::verify2((const volatile Thing*)&thing, &const_volatile_func2); + Verifier::verify2(callback(static_func2)); + + 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 +void test_dispatch3() { + Thing thing; + Verifier::verify3(static_func3); + Verifier::verify3(&thing, &Thing::member_func3); + Verifier::verify3((const Thing*)&thing, &Thing::const_member_func3); + Verifier::verify3((volatile Thing*)&thing, &Thing::volatile_member_func3); + Verifier::verify3((const volatile Thing*)&thing, &Thing::const_volatile_member_func3); + Verifier::verify3(&thing, &bound_func3); + Verifier::verify3((const Thing*)&thing, &const_func3); + Verifier::verify3((volatile Thing*)&thing, &volatile_func3); + Verifier::verify3((const volatile Thing*)&thing, &const_volatile_func3); + Verifier::verify3(callback(static_func3)); + + 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 +void test_dispatch4() { + Thing thing; + Verifier::verify4(static_func4); + Verifier::verify4(&thing, &Thing::member_func4); + Verifier::verify4((const Thing*)&thing, &Thing::const_member_func4); + Verifier::verify4((volatile Thing*)&thing, &Thing::volatile_member_func4); + Verifier::verify4((const volatile Thing*)&thing, &Thing::const_volatile_member_func4); + Verifier::verify4(&thing, &bound_func4); + Verifier::verify4((const Thing*)&thing, &const_func4); + Verifier::verify4((volatile Thing*)&thing, &volatile_func4); + Verifier::verify4((const volatile Thing*)&thing, &const_volatile_func4); + Verifier::verify4(callback(static_func4)); + + 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 +void test_dispatch5() { + Thing thing; + Verifier::verify5(static_func5); + Verifier::verify5(&thing, &Thing::member_func5); + Verifier::verify5((const Thing*)&thing, &Thing::const_member_func5); + Verifier::verify5((volatile Thing*)&thing, &Thing::volatile_member_func5); + Verifier::verify5((const volatile Thing*)&thing, &Thing::const_volatile_member_func5); + Verifier::verify5(&thing, &bound_func5); + Verifier::verify5((const Thing*)&thing, &const_func5); + Verifier::verify5((volatile Thing*)&thing, &volatile_func5); + Verifier::verify5((const volatile Thing*)&thing, &const_volatile_func5); + Verifier::verify5(callback(static_func5)); + + 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); +} + + +// Test setup +utest::v1::status_t test_setup(const size_t number_of_cases) { + GREENTEA_SETUP(10, "default_auto"); + return verbose_test_setup_handler(number_of_cases); +} + +Case cases[] = { + Case("Testing callbacks with 0 ints", test_dispatch0), + Case("Testing callbacks with 1 ints", test_dispatch1), + Case("Testing callbacks with 2 ints", test_dispatch2), + Case("Testing callbacks with 3 ints", test_dispatch3), + Case("Testing callbacks with 4 ints", test_dispatch4), + Case("Testing callbacks with 5 ints", test_dispatch5), +}; + +Specification specification(test_setup, cases); + +int main() { + return !Harness::run(specification); +} diff --git a/TESTS/mbed_functional/callback_big/main.cpp b/TESTS/mbed_functional/callback_big/main.cpp new file mode 100644 index 00000000000..47630a3f21c --- /dev/null +++ b/TESTS/mbed_functional/callback_big/main.cpp @@ -0,0 +1,351 @@ +#include "mbed.h" +#include "greentea-client/test_env.h" +#include "unity.h" +#include "utest.h" + +using namespace utest::v1; + + +// static functions +template +T static_func0() { return 0; } +template +T static_func1(T a0) { return 0 | a0; } +template +T static_func2(T a0, T a1) { return 0 | a0 | a1; } +template +T static_func3(T a0, T a1, T a2) { return 0 | a0 | a1 | a2; } +template +T static_func4(T a0, T a1, T a2, T a3) { return 0 | a0 | a1 | a2 | a3; } +template +T static_func5(T a0, T a1, T a2, T a3, T a4) { return 0 | a0 | a1 | a2 | a3 | a4; } + +// class functions +template +struct Thing { + T t; + Thing() : t(0x80) {} + + T member_func0() { return t; } + T member_func1(T a0) { return t | a0; } + T member_func2(T a0, T a1) { return t | a0 | a1; } + T member_func3(T a0, T a1, T a2) { return t | a0 | a1 | a2; } + T member_func4(T a0, T a1, T a2, T a3) { return t | a0 | a1 | a2 | a3; } + T member_func5(T a0, T a1, T a2, T a3, T a4) { return t | a0 | a1 | a2 | a3 | a4; } + + T const_member_func0() const { return t; } + T const_member_func1(T a0) const { return t | a0; } + T const_member_func2(T a0, T a1) const { return t | a0 | a1; } + T const_member_func3(T a0, T a1, T a2) const { return t | a0 | a1 | a2; } + T const_member_func4(T a0, T a1, T a2, T a3) const { return t | a0 | a1 | a2 | a3; } + T const_member_func5(T a0, T a1, T a2, T a3, T a4) const { return t | a0 | a1 | a2 | a3 | a4; } + + T volatile_member_func0() volatile { return t; } + T volatile_member_func1(T a0) volatile { return t | a0; } + T volatile_member_func2(T a0, T a1) volatile { return t | a0 | a1; } + T volatile_member_func3(T a0, T a1, T a2) volatile { return t | a0 | a1 | a2; } + T volatile_member_func4(T a0, T a1, T a2, T a3) volatile { return t | a0 | a1 | a2 | a3; } + T volatile_member_func5(T a0, T a1, T a2, T a3, T a4) volatile { return t | a0 | a1 | a2 | a3 | a4; } + + T const_volatile_member_func0() const volatile { return t; } + T const_volatile_member_func1(T a0) const volatile { return t | a0; } + T const_volatile_member_func2(T a0, T a1) const volatile { return t | a0 | a1; } + T const_volatile_member_func3(T a0, T a1, T a2) const volatile { return t | a0 | a1 | a2; } + T const_volatile_member_func4(T a0, T a1, T a2, T a3) const volatile { return t | a0 | a1 | a2 | a3; } + T const_volatile_member_func5(T a0, T a1, T a2, T a3, T a4) const volatile { return t | a0 | a1 | a2 | a3 | a4; } +}; + +// bound functions +template +T bound_func0(Thing *t) { return t->t; } +template +T bound_func1(Thing *t, T a0) { return t->t | a0; } +template +T bound_func2(Thing *t, T a0, T a1) { return t->t | a0 | a1; } +template +T bound_func3(Thing *t, T a0, T a1, T a2) { return t->t | a0 | a1 | a2; } +template +T bound_func4(Thing *t, T a0, T a1, T a2, T a3) { return t->t | a0 | a1 | a2 | a3; } +template +T bound_func5(Thing *t, T a0, T a1, T a2, T a3, T a4) { return t->t | a0 | a1 | a2 | a3 | a4; } + +// const bound functions +template +T const_func0(const Thing *t) { return t->t; } +template +T const_func1(const Thing *t, T a0) { return t->t | a0; } +template +T const_func2(const Thing *t, T a0, T a1) { return t->t | a0 | a1; } +template +T const_func3(const Thing *t, T a0, T a1, T a2) { return t->t | a0 | a1 | a2; } +template +T const_func4(const Thing *t, T a0, T a1, T a2, T a3) { return t->t | a0 | a1 | a2 | a3; } +template +T const_func5(const Thing *t, T a0, T a1, T a2, T a3, T a4) { return t->t | a0 | a1 | a2 | a3 | a4; } + +// volatile bound functions +template +T volatile_func0(volatile Thing *t) { return t->t; } +template +T volatile_func1(volatile Thing *t, T a0) { return t->t | a0; } +template +T volatile_func2(volatile Thing *t, T a0, T a1) { return t->t | a0 | a1; } +template +T volatile_func3(volatile Thing *t, T a0, T a1, T a2) { return t->t | a0 | a1 | a2; } +template +T volatile_func4(volatile Thing *t, T a0, T a1, T a2, T a3) { return t->t | a0 | a1 | a2 | a3; } +template +T volatile_func5(volatile Thing *t, T a0, T a1, T a2, T a3, T a4) { return t->t | a0 | a1 | a2 | a3 | a4; } + +// const volatile bound functions +template +T const_volatile_func0(const volatile Thing *t) { return t->t; } +template +T const_volatile_func1(const volatile Thing *t, T a0) { return t->t | a0; } +template +T const_volatile_func2(const volatile Thing *t, T a0, T a1) { return t->t | a0 | a1; } +template +T const_volatile_func3(const volatile Thing *t, T a0, T a1, T a2) { return t->t | a0 | a1 | a2; } +template +T const_volatile_func4(const volatile Thing *t, T a0, T a1, T a2, T a3) { return t->t | a0 | a1 | a2 | a3; } +template +T const_volatile_func5(const volatile Thing *t, T a0, T a1, T a2, T a3, T a4) { return t->t | a0 | a1 | a2 | a3 | a4; } + + +// function call and result verification +template +struct Verifier { + static void verify0(Callback func) { + T result = func(); + TEST_ASSERT_EQUAL(result, 0x00); + } + + template + static void verify0(O *obj, M method) { + Callback func(obj, method); + T result = func(); + TEST_ASSERT_EQUAL(result, 0x80); + } + + static void verify1(Callback func) { + T result = func((1 << 0)); + TEST_ASSERT_EQUAL(result, 0x00 | (1 << 0)); + } + + template + static void verify1(O *obj, M method) { + Callback func(obj, method); + T result = func((1 << 0)); + TEST_ASSERT_EQUAL(result, 0x80 | (1 << 0)); + } + + static void verify2(Callback func) { + T result = func((1 << 0), (1 << 1)); + TEST_ASSERT_EQUAL(result, 0x00 | (1 << 0) | (1 << 1)); + } + + template + static void verify2(O *obj, M method) { + Callback func(obj, method); + T result = func((1 << 0), (1 << 1)); + TEST_ASSERT_EQUAL(result, 0x80 | (1 << 0) | (1 << 1)); + } + + static void verify3(Callback func) { + T result = func((1 << 0), (1 << 1), (1 << 2)); + TEST_ASSERT_EQUAL(result, 0x00 | (1 << 0) | (1 << 1) | (1 << 2)); + } + + template + static void verify3(O *obj, M method) { + Callback func(obj, method); + T result = func((1 << 0), (1 << 1), (1 << 2)); + TEST_ASSERT_EQUAL(result, 0x80 | (1 << 0) | (1 << 1) | (1 << 2)); + } + + static void verify4(Callback func) { + T result = func((1 << 0), (1 << 1), (1 << 2), (1 << 3)); + TEST_ASSERT_EQUAL(result, 0x00 | (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3)); + } + + template + static void verify4(O *obj, M method) { + Callback func(obj, method); + T result = func((1 << 0), (1 << 1), (1 << 2), (1 << 3)); + TEST_ASSERT_EQUAL(result, 0x80 | (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3)); + } + + static void verify5(Callback func) { + T result = func((1 << 0), (1 << 1), (1 << 2), (1 << 3), (1 << 4)); + TEST_ASSERT_EQUAL(result, 0x00 | (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4)); + } + + template + static void verify5(O *obj, M method) { + Callback func(obj, method); + T result = func((1 << 0), (1 << 1), (1 << 2), (1 << 3), (1 << 4)); + TEST_ASSERT_EQUAL(result, 0x80 | (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4)); + } +}; + + +// test dispatch +template +void test_dispatch0() { + Thing thing; + Verifier::verify0(static_func0); + Verifier::verify0(&thing, &Thing::member_func0); + Verifier::verify0((const Thing*)&thing, &Thing::const_member_func0); + Verifier::verify0((volatile Thing*)&thing, &Thing::volatile_member_func0); + Verifier::verify0((const volatile Thing*)&thing, &Thing::const_volatile_member_func0); + Verifier::verify0(&thing, &bound_func0); + Verifier::verify0((const Thing*)&thing, &const_func0); + Verifier::verify0((volatile Thing*)&thing, &volatile_func0); + Verifier::verify0((const volatile Thing*)&thing, &const_volatile_func0); + Verifier::verify0(callback(static_func0)); + + 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 +void test_dispatch1() { + Thing thing; + Verifier::verify1(static_func1); + Verifier::verify1(&thing, &Thing::member_func1); + Verifier::verify1((const Thing*)&thing, &Thing::const_member_func1); + Verifier::verify1((volatile Thing*)&thing, &Thing::volatile_member_func1); + Verifier::verify1((const volatile Thing*)&thing, &Thing::const_volatile_member_func1); + Verifier::verify1(&thing, &bound_func1); + Verifier::verify1((const Thing*)&thing, &const_func1); + Verifier::verify1((volatile Thing*)&thing, &volatile_func1); + Verifier::verify1((const volatile Thing*)&thing, &const_volatile_func1); + Verifier::verify1(callback(static_func1)); + + 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 +void test_dispatch2() { + Thing thing; + Verifier::verify2(static_func2); + Verifier::verify2(&thing, &Thing::member_func2); + Verifier::verify2((const Thing*)&thing, &Thing::const_member_func2); + Verifier::verify2((volatile Thing*)&thing, &Thing::volatile_member_func2); + Verifier::verify2((const volatile Thing*)&thing, &Thing::const_volatile_member_func2); + Verifier::verify2(&thing, &bound_func2); + Verifier::verify2((const Thing*)&thing, &const_func2); + Verifier::verify2((volatile Thing*)&thing, &volatile_func2); + Verifier::verify2((const volatile Thing*)&thing, &const_volatile_func2); + Verifier::verify2(callback(static_func2)); + + 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 +void test_dispatch3() { + Thing thing; + Verifier::verify3(static_func3); + Verifier::verify3(&thing, &Thing::member_func3); + Verifier::verify3((const Thing*)&thing, &Thing::const_member_func3); + Verifier::verify3((volatile Thing*)&thing, &Thing::volatile_member_func3); + Verifier::verify3((const volatile Thing*)&thing, &Thing::const_volatile_member_func3); + Verifier::verify3(&thing, &bound_func3); + Verifier::verify3((const Thing*)&thing, &const_func3); + Verifier::verify3((volatile Thing*)&thing, &volatile_func3); + Verifier::verify3((const volatile Thing*)&thing, &const_volatile_func3); + Verifier::verify3(callback(static_func3)); + + 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 +void test_dispatch4() { + Thing thing; + Verifier::verify4(static_func4); + Verifier::verify4(&thing, &Thing::member_func4); + Verifier::verify4((const Thing*)&thing, &Thing::const_member_func4); + Verifier::verify4((volatile Thing*)&thing, &Thing::volatile_member_func4); + Verifier::verify4((const volatile Thing*)&thing, &Thing::const_volatile_member_func4); + Verifier::verify4(&thing, &bound_func4); + Verifier::verify4((const Thing*)&thing, &const_func4); + Verifier::verify4((volatile Thing*)&thing, &volatile_func4); + Verifier::verify4((const volatile Thing*)&thing, &const_volatile_func4); + Verifier::verify4(callback(static_func4)); + + 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 +void test_dispatch5() { + Thing thing; + Verifier::verify5(static_func5); + Verifier::verify5(&thing, &Thing::member_func5); + Verifier::verify5((const Thing*)&thing, &Thing::const_member_func5); + Verifier::verify5((volatile Thing*)&thing, &Thing::volatile_member_func5); + Verifier::verify5((const volatile Thing*)&thing, &Thing::const_volatile_member_func5); + Verifier::verify5(&thing, &bound_func5); + Verifier::verify5((const Thing*)&thing, &const_func5); + Verifier::verify5((volatile Thing*)&thing, &volatile_func5); + Verifier::verify5((const volatile Thing*)&thing, &const_volatile_func5); + Verifier::verify5(callback(static_func5)); + + 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); +} + + +// Test setup +utest::v1::status_t test_setup(const size_t number_of_cases) { + GREENTEA_SETUP(10, "default_auto"); + return verbose_test_setup_handler(number_of_cases); +} + +Case cases[] = { + Case("Testing callbacks with 0 uint64s", test_dispatch0), + Case("Testing callbacks with 1 uint64s", test_dispatch1), + Case("Testing callbacks with 2 uint64s", test_dispatch2), + Case("Testing callbacks with 3 uint64s", test_dispatch3), + Case("Testing callbacks with 4 uint64s", test_dispatch4), + Case("Testing callbacks with 5 uint64s", test_dispatch5), +}; + +Specification specification(test_setup, cases); + +int main() { + return !Harness::run(specification); +} diff --git a/TESTS/mbed_drivers/callback/main.cpp b/TESTS/mbed_functional/callback_small/main.cpp similarity index 91% rename from TESTS/mbed_drivers/callback/main.cpp rename to TESTS/mbed_functional/callback_small/main.cpp index 403968a039b..e5fa15b4b68 100644 --- a/TESTS/mbed_drivers/callback/main.cpp +++ b/TESTS/mbed_functional/callback_small/main.cpp @@ -328,22 +328,6 @@ void test_dispatch5() { Verifier::verify5((void*)&cb, &Callback::thunk); } -template -void test_fparg1() { - Thing thing; - FunctionPointerArg1 fp(static_func1); - Verifier::verify1(fp); - Verifier::verify1(fp.get_function()); -} - -template -void test_fparg0() { - Thing thing; - FunctionPointerArg1 fp(static_func0); - Verifier::verify0(fp); - Verifier::verify0(fp.get_function()); -} - // Test setup utest::v1::status_t test_setup(const size_t number_of_cases) { @@ -352,29 +336,12 @@ utest::v1::status_t test_setup(const size_t number_of_cases) { } Case cases[] = { - Case("Testing callbacks with 0 ints", test_dispatch0), - Case("Testing callbacks with 1 ints", test_dispatch1), - Case("Testing callbacks with 2 ints", test_dispatch2), - Case("Testing callbacks with 3 ints", test_dispatch3), - Case("Testing callbacks with 4 ints", test_dispatch4), - Case("Testing callbacks with 5 ints", test_dispatch5), - Case("Testing callbacks with 0 uchars", test_dispatch0), Case("Testing callbacks with 1 uchars", test_dispatch1), Case("Testing callbacks with 2 uchars", test_dispatch2), Case("Testing callbacks with 3 uchars", test_dispatch3), Case("Testing callbacks with 4 uchars", test_dispatch4), Case("Testing callbacks with 5 uchars", test_dispatch5), - - Case("Testing callbacks with 0 uint64s", test_dispatch0), - Case("Testing callbacks with 1 uint64s", test_dispatch1), - Case("Testing callbacks with 2 uint64s", test_dispatch2), - Case("Testing callbacks with 3 uint64s", test_dispatch3), - Case("Testing callbacks with 4 uint64s", test_dispatch4), - Case("Testing callbacks with 5 uint64s", test_dispatch5), - - Case("Testing FunctionPointerArg1 compatibility", test_fparg1), - Case("Testing FunctionPointer compatibility", test_fparg0), }; Specification specification(test_setup, cases); diff --git a/TESTS/mbed_functional/functionpointer/main.cpp b/TESTS/mbed_functional/functionpointer/main.cpp new file mode 100644 index 00000000000..7a61dc0abdf --- /dev/null +++ b/TESTS/mbed_functional/functionpointer/main.cpp @@ -0,0 +1,225 @@ +#include "mbed.h" +#include "greentea-client/test_env.h" +#include "unity.h" +#include "utest.h" + +using namespace utest::v1; + + +// static functions +template +T static_func0() { return 0; } +template +T static_func1(T a0) { return 0 | a0; } +template +T static_func2(T a0, T a1) { return 0 | a0 | a1; } +template +T static_func3(T a0, T a1, T a2) { return 0 | a0 | a1 | a2; } +template +T static_func4(T a0, T a1, T a2, T a3) { return 0 | a0 | a1 | a2 | a3; } +template +T static_func5(T a0, T a1, T a2, T a3, T a4) { return 0 | a0 | a1 | a2 | a3 | a4; } + +// class functions +template +struct Thing { + T t; + Thing() : t(0x80) {} + + T member_func0() { return t; } + T member_func1(T a0) { return t | a0; } + T member_func2(T a0, T a1) { return t | a0 | a1; } + T member_func3(T a0, T a1, T a2) { return t | a0 | a1 | a2; } + T member_func4(T a0, T a1, T a2, T a3) { return t | a0 | a1 | a2 | a3; } + T member_func5(T a0, T a1, T a2, T a3, T a4) { return t | a0 | a1 | a2 | a3 | a4; } + + T const_member_func0() const { return t; } + T const_member_func1(T a0) const { return t | a0; } + T const_member_func2(T a0, T a1) const { return t | a0 | a1; } + T const_member_func3(T a0, T a1, T a2) const { return t | a0 | a1 | a2; } + T const_member_func4(T a0, T a1, T a2, T a3) const { return t | a0 | a1 | a2 | a3; } + T const_member_func5(T a0, T a1, T a2, T a3, T a4) const { return t | a0 | a1 | a2 | a3 | a4; } + + T volatile_member_func0() volatile { return t; } + T volatile_member_func1(T a0) volatile { return t | a0; } + T volatile_member_func2(T a0, T a1) volatile { return t | a0 | a1; } + T volatile_member_func3(T a0, T a1, T a2) volatile { return t | a0 | a1 | a2; } + T volatile_member_func4(T a0, T a1, T a2, T a3) volatile { return t | a0 | a1 | a2 | a3; } + T volatile_member_func5(T a0, T a1, T a2, T a3, T a4) volatile { return t | a0 | a1 | a2 | a3 | a4; } + + T const_volatile_member_func0() const volatile { return t; } + T const_volatile_member_func1(T a0) const volatile { return t | a0; } + T const_volatile_member_func2(T a0, T a1) const volatile { return t | a0 | a1; } + T const_volatile_member_func3(T a0, T a1, T a2) const volatile { return t | a0 | a1 | a2; } + T const_volatile_member_func4(T a0, T a1, T a2, T a3) const volatile { return t | a0 | a1 | a2 | a3; } + T const_volatile_member_func5(T a0, T a1, T a2, T a3, T a4) const volatile { return t | a0 | a1 | a2 | a3 | a4; } +}; + +// bound functions +template +T bound_func0(Thing *t) { return t->t; } +template +T bound_func1(Thing *t, T a0) { return t->t | a0; } +template +T bound_func2(Thing *t, T a0, T a1) { return t->t | a0 | a1; } +template +T bound_func3(Thing *t, T a0, T a1, T a2) { return t->t | a0 | a1 | a2; } +template +T bound_func4(Thing *t, T a0, T a1, T a2, T a3) { return t->t | a0 | a1 | a2 | a3; } +template +T bound_func5(Thing *t, T a0, T a1, T a2, T a3, T a4) { return t->t | a0 | a1 | a2 | a3 | a4; } + +// const bound functions +template +T const_func0(const Thing *t) { return t->t; } +template +T const_func1(const Thing *t, T a0) { return t->t | a0; } +template +T const_func2(const Thing *t, T a0, T a1) { return t->t | a0 | a1; } +template +T const_func3(const Thing *t, T a0, T a1, T a2) { return t->t | a0 | a1 | a2; } +template +T const_func4(const Thing *t, T a0, T a1, T a2, T a3) { return t->t | a0 | a1 | a2 | a3; } +template +T const_func5(const Thing *t, T a0, T a1, T a2, T a3, T a4) { return t->t | a0 | a1 | a2 | a3 | a4; } + +// volatile bound functions +template +T volatile_func0(volatile Thing *t) { return t->t; } +template +T volatile_func1(volatile Thing *t, T a0) { return t->t | a0; } +template +T volatile_func2(volatile Thing *t, T a0, T a1) { return t->t | a0 | a1; } +template +T volatile_func3(volatile Thing *t, T a0, T a1, T a2) { return t->t | a0 | a1 | a2; } +template +T volatile_func4(volatile Thing *t, T a0, T a1, T a2, T a3) { return t->t | a0 | a1 | a2 | a3; } +template +T volatile_func5(volatile Thing *t, T a0, T a1, T a2, T a3, T a4) { return t->t | a0 | a1 | a2 | a3 | a4; } + +// const volatile bound functions +template +T const_volatile_func0(const volatile Thing *t) { return t->t; } +template +T const_volatile_func1(const volatile Thing *t, T a0) { return t->t | a0; } +template +T const_volatile_func2(const volatile Thing *t, T a0, T a1) { return t->t | a0 | a1; } +template +T const_volatile_func3(const volatile Thing *t, T a0, T a1, T a2) { return t->t | a0 | a1 | a2; } +template +T const_volatile_func4(const volatile Thing *t, T a0, T a1, T a2, T a3) { return t->t | a0 | a1 | a2 | a3; } +template +T const_volatile_func5(const volatile Thing *t, T a0, T a1, T a2, T a3, T a4) { return t->t | a0 | a1 | a2 | a3 | a4; } + + +// function call and result verification +template +struct Verifier { + static void verify0(Callback func) { + T result = func(); + TEST_ASSERT_EQUAL(result, 0x00); + } + + template + static void verify0(O *obj, M method) { + Callback func(obj, method); + T result = func(); + TEST_ASSERT_EQUAL(result, 0x80); + } + + static void verify1(Callback func) { + T result = func((1 << 0)); + TEST_ASSERT_EQUAL(result, 0x00 | (1 << 0)); + } + + template + static void verify1(O *obj, M method) { + Callback func(obj, method); + T result = func((1 << 0)); + TEST_ASSERT_EQUAL(result, 0x80 | (1 << 0)); + } + + static void verify2(Callback func) { + T result = func((1 << 0), (1 << 1)); + TEST_ASSERT_EQUAL(result, 0x00 | (1 << 0) | (1 << 1)); + } + + template + static void verify2(O *obj, M method) { + Callback func(obj, method); + T result = func((1 << 0), (1 << 1)); + TEST_ASSERT_EQUAL(result, 0x80 | (1 << 0) | (1 << 1)); + } + + static void verify3(Callback func) { + T result = func((1 << 0), (1 << 1), (1 << 2)); + TEST_ASSERT_EQUAL(result, 0x00 | (1 << 0) | (1 << 1) | (1 << 2)); + } + + template + static void verify3(O *obj, M method) { + Callback func(obj, method); + T result = func((1 << 0), (1 << 1), (1 << 2)); + TEST_ASSERT_EQUAL(result, 0x80 | (1 << 0) | (1 << 1) | (1 << 2)); + } + + static void verify4(Callback func) { + T result = func((1 << 0), (1 << 1), (1 << 2), (1 << 3)); + TEST_ASSERT_EQUAL(result, 0x00 | (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3)); + } + + template + static void verify4(O *obj, M method) { + Callback func(obj, method); + T result = func((1 << 0), (1 << 1), (1 << 2), (1 << 3)); + TEST_ASSERT_EQUAL(result, 0x80 | (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3)); + } + + static void verify5(Callback func) { + T result = func((1 << 0), (1 << 1), (1 << 2), (1 << 3), (1 << 4)); + TEST_ASSERT_EQUAL(result, 0x00 | (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4)); + } + + template + static void verify5(O *obj, M method) { + Callback func(obj, method); + T result = func((1 << 0), (1 << 1), (1 << 2), (1 << 3), (1 << 4)); + TEST_ASSERT_EQUAL(result, 0x80 | (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4)); + } +}; + + +// test dispatch +template +void test_fparg1() { + Thing thing; + FunctionPointerArg1 fp(static_func1); + Verifier::verify1(fp); + Verifier::verify1(fp.get_function()); +} + +template +void test_fparg0() { + Thing thing; + FunctionPointerArg1 fp(static_func0); + Verifier::verify0(fp); + Verifier::verify0(fp.get_function()); +} + + +// Test setup +utest::v1::status_t test_setup(const size_t number_of_cases) { + GREENTEA_SETUP(10, "default_auto"); + return verbose_test_setup_handler(number_of_cases); +} + +Case cases[] = { + Case("Testing FunctionPointerArg1 compatibility", test_fparg1), + Case("Testing FunctionPointer compatibility", test_fparg0), +}; + +Specification specification(test_setup, cases); + +int main() { + return !Harness::run(specification); +} From 756a09003c065330c899cae64fbb56fd1840ff7b Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Thu, 25 Aug 2016 12:25:01 -0500 Subject: [PATCH 4/5] Added explicit void specialization in callbacks One limitation of C++ is that implicit casts do not occur when matching template overloads, as a consequence the callback's argument type requires a strict match. Unfortunately, the prevents the previously common pattern of using void pointers as function arguments, causing unnecessary problems for users porting code. Thing *t; void doit(void *p) { blablabla } Callback cb(t, doit); To avoid this, explicit overloads on void pointers were added. This avoids a template expansion, and allows the implicit cast to occur as the user would expect. --- TESTS/mbed_functional/callback/main.cpp | 306 ++++-- .../mbed_functional/functionpointer/main.cpp | 246 +++-- hal/api/Callback.h | 982 +++++++++++++++++- 3 files changed, 1345 insertions(+), 189 deletions(-) diff --git a/TESTS/mbed_functional/callback/main.cpp b/TESTS/mbed_functional/callback/main.cpp index 8442448e538..6f6b7da4f76 100644 --- a/TESTS/mbed_functional/callback/main.cpp +++ b/TESTS/mbed_functional/callback/main.cpp @@ -8,17 +8,23 @@ using namespace utest::v1; // static functions template -T static_func0() { return 0; } +T static_func0() + { return 0; } template -T static_func1(T a0) { return 0 | a0; } +T static_func1(T a0) + { return 0 | a0; } template -T static_func2(T a0, T a1) { return 0 | a0 | a1; } +T static_func2(T a0, T a1) + { return 0 | a0 | a1; } template -T static_func3(T a0, T a1, T a2) { return 0 | a0 | a1 | a2; } +T static_func3(T a0, T a1, T a2) + { return 0 | a0 | a1 | a2; } template -T static_func4(T a0, T a1, T a2, T a3) { return 0 | a0 | a1 | a2 | a3; } +T static_func4(T a0, T a1, T a2, T a3) + { return 0 | a0 | a1 | a2 | a3; } template -T static_func5(T a0, T a1, T a2, T a3, T a4) { return 0 | a0 | a1 | a2 | a3 | a4; } +T static_func5(T a0, T a1, T a2, T a3, T a4) + { return 0 | a0 | a1 | a2 | a3 | a4; } // class functions template @@ -26,90 +32,206 @@ struct Thing { T t; Thing() : t(0x80) {} - T member_func0() { return t; } - T member_func1(T a0) { return t | a0; } - T member_func2(T a0, T a1) { return t | a0 | a1; } - T member_func3(T a0, T a1, T a2) { return t | a0 | a1 | a2; } - T member_func4(T a0, T a1, T a2, T a3) { return t | a0 | a1 | a2 | a3; } - T member_func5(T a0, T a1, T a2, T a3, T a4) { return t | a0 | a1 | a2 | a3 | a4; } - - T const_member_func0() const { return t; } - T const_member_func1(T a0) const { return t | a0; } - T const_member_func2(T a0, T a1) const { return t | a0 | a1; } - T const_member_func3(T a0, T a1, T a2) const { return t | a0 | a1 | a2; } - T const_member_func4(T a0, T a1, T a2, T a3) const { return t | a0 | a1 | a2 | a3; } - T const_member_func5(T a0, T a1, T a2, T a3, T a4) const { return t | a0 | a1 | a2 | a3 | a4; } - - T volatile_member_func0() volatile { return t; } - T volatile_member_func1(T a0) volatile { return t | a0; } - T volatile_member_func2(T a0, T a1) volatile { return t | a0 | a1; } - T volatile_member_func3(T a0, T a1, T a2) volatile { return t | a0 | a1 | a2; } - T volatile_member_func4(T a0, T a1, T a2, T a3) volatile { return t | a0 | a1 | a2 | a3; } - T volatile_member_func5(T a0, T a1, T a2, T a3, T a4) volatile { return t | a0 | a1 | a2 | a3 | a4; } - - T const_volatile_member_func0() const volatile { return t; } - T const_volatile_member_func1(T a0) const volatile { return t | a0; } - T const_volatile_member_func2(T a0, T a1) const volatile { return t | a0 | a1; } - T const_volatile_member_func3(T a0, T a1, T a2) const volatile { return t | a0 | a1 | a2; } - T const_volatile_member_func4(T a0, T a1, T a2, T a3) const volatile { return t | a0 | a1 | a2 | a3; } - T const_volatile_member_func5(T a0, T a1, T a2, T a3, T a4) const volatile { return t | a0 | a1 | a2 | a3 | a4; } + T member_func0() + { return t; } + T member_func1(T a0) + { return t | a0; } + T member_func2(T a0, T a1) + { return t | a0 | a1; } + T member_func3(T a0, T a1, T a2) + { return t | a0 | a1 | a2; } + T member_func4(T a0, T a1, T a2, T a3) + { return t | a0 | a1 | a2 | a3; } + T member_func5(T a0, T a1, T a2, T a3, T a4) + { return t | a0 | a1 | a2 | a3 | a4; } + + T const_member_func0() const + { return t; } + T const_member_func1(T a0) const + { return t | a0; } + T const_member_func2(T a0, T a1) const + { return t | a0 | a1; } + T const_member_func3(T a0, T a1, T a2) const + { return t | a0 | a1 | a2; } + T const_member_func4(T a0, T a1, T a2, T a3) const + { return t | a0 | a1 | a2 | a3; } + T const_member_func5(T a0, T a1, T a2, T a3, T a4) const + { return t | a0 | a1 | a2 | a3 | a4; } + + T volatile_member_func0() volatile + { return t; } + T volatile_member_func1(T a0) volatile + { return t | a0; } + T volatile_member_func2(T a0, T a1) volatile + { return t | a0 | a1; } + T volatile_member_func3(T a0, T a1, T a2) volatile + { return t | a0 | a1 | a2; } + T volatile_member_func4(T a0, T a1, T a2, T a3) volatile + { return t | a0 | a1 | a2 | a3; } + T volatile_member_func5(T a0, T a1, T a2, T a3, T a4) volatile + { return t | a0 | a1 | a2 | a3 | a4; } + + T const_volatile_member_func0() const volatile + { return t; } + T const_volatile_member_func1(T a0) const volatile + { return t | a0; } + T const_volatile_member_func2(T a0, T a1) const volatile + { return t | a0 | a1; } + T const_volatile_member_func3(T a0, T a1, T a2) const volatile + { return t | a0 | a1 | a2; } + T const_volatile_member_func4(T a0, T a1, T a2, T a3) const volatile + { return t | a0 | a1 | a2 | a3; } + T const_volatile_member_func5(T a0, T a1, T a2, T a3, T a4) const volatile + { return t | a0 | a1 | a2 | a3 | a4; } }; // bound functions template -T bound_func0(Thing *t) { return t->t; } +T bound_func0(Thing *t) + { return t->t; } template -T bound_func1(Thing *t, T a0) { return t->t | a0; } +T bound_func1(Thing *t, T a0) + { return t->t | a0; } template -T bound_func2(Thing *t, T a0, T a1) { return t->t | a0 | a1; } +T bound_func2(Thing *t, T a0, T a1) + { return t->t | a0 | a1; } template -T bound_func3(Thing *t, T a0, T a1, T a2) { return t->t | a0 | a1 | a2; } +T bound_func3(Thing *t, T a0, T a1, T a2) + { return t->t | a0 | a1 | a2; } template -T bound_func4(Thing *t, T a0, T a1, T a2, T a3) { return t->t | a0 | a1 | a2 | a3; } +T bound_func4(Thing *t, T a0, T a1, T a2, T a3) + { return t->t | a0 | a1 | a2 | a3; } template -T bound_func5(Thing *t, T a0, T a1, T a2, T a3, T a4) { return t->t | a0 | a1 | a2 | a3 | a4; } - -// const bound functions +T bound_func5(Thing *t, T a0, T a1, T a2, T a3, T a4) + { return t->t | a0 | a1 | a2 | a3 | a4; } template -T const_func0(const Thing *t) { return t->t; } +T const_bound_func0(const Thing *t) + { return t->t; } template -T const_func1(const Thing *t, T a0) { return t->t | a0; } +T const_bound_func1(const Thing *t, T a0) + { return t->t | a0; } template -T const_func2(const Thing *t, T a0, T a1) { return t->t | a0 | a1; } +T const_bound_func2(const Thing *t, T a0, T a1) + { return t->t | a0 | a1; } template -T const_func3(const Thing *t, T a0, T a1, T a2) { return t->t | a0 | a1 | a2; } +T const_bound_func3(const Thing *t, T a0, T a1, T a2) + { return t->t | a0 | a1 | a2; } template -T const_func4(const Thing *t, T a0, T a1, T a2, T a3) { return t->t | a0 | a1 | a2 | a3; } +T const_bound_func4(const Thing *t, T a0, T a1, T a2, T a3) + { return t->t | a0 | a1 | a2 | a3; } template -T const_func5(const Thing *t, T a0, T a1, T a2, T a3, T a4) { return t->t | a0 | a1 | a2 | a3 | a4; } - -// volatile bound functions +T const_bound_func5(const Thing *t, T a0, T a1, T a2, T a3, T a4) + { return t->t | a0 | a1 | a2 | a3 | a4; } +template +T volatile_bound_func0(volatile Thing *t) + { return t->t; } +template +T volatile_bound_func1(volatile Thing *t, T a0) + { return t->t | a0; } +template +T volatile_bound_func2(volatile Thing *t, T a0, T a1) + { return t->t | a0 | a1; } +template +T volatile_bound_func3(volatile Thing *t, T a0, T a1, T a2) + { return t->t | a0 | a1 | a2; } +template +T volatile_bound_func4(volatile Thing *t, T a0, T a1, T a2, T a3) + { return t->t | a0 | a1 | a2 | a3; } template -T volatile_func0(volatile Thing *t) { return t->t; } +T volatile_bound_func5(volatile Thing *t, T a0, T a1, T a2, T a3, T a4) + { return t->t | a0 | a1 | a2 | a3 | a4; } template -T volatile_func1(volatile Thing *t, T a0) { return t->t | a0; } +T const_volatile_bound_func0(const volatile Thing *t) + { return t->t; } template -T volatile_func2(volatile Thing *t, T a0, T a1) { return t->t | a0 | a1; } +T const_volatile_bound_func1(const volatile Thing *t, T a0) + { return t->t | a0; } template -T volatile_func3(volatile Thing *t, T a0, T a1, T a2) { return t->t | a0 | a1 | a2; } +T const_volatile_bound_func2(const volatile Thing *t, T a0, T a1) + { return t->t | a0 | a1; } template -T volatile_func4(volatile Thing *t, T a0, T a1, T a2, T a3) { return t->t | a0 | a1 | a2 | a3; } +T const_volatile_bound_func3(const volatile Thing *t, T a0, T a1, T a2) + { return t->t | a0 | a1 | a2; } template -T volatile_func5(volatile Thing *t, T a0, T a1, T a2, T a3, T a4) { return t->t | a0 | a1 | a2 | a3 | a4; } +T const_volatile_bound_func4(const volatile Thing *t, T a0, T a1, T a2, T a3) + { return t->t | a0 | a1 | a2 | a3; } +template +T const_volatile_bound_func5(const volatile Thing *t, T a0, T a1, T a2, T a3, T a4) + { return t->t | a0 | a1 | a2 | a3 | a4; } -// const volatile bound functions +// void functions +template +T void_func0(void *t) + { return static_cast*>(t)->t; } +template +T void_func1(void *t, T a0) + { return static_cast*>(t)->t | a0; } +template +T void_func2(void *t, T a0, T a1) + { return static_cast*>(t)->t | a0 | a1; } +template +T void_func3(void *t, T a0, T a1, T a2) + { return static_cast*>(t)->t | a0 | a1 | a2; } +template +T void_func4(void *t, T a0, T a1, T a2, T a3) + { return static_cast*>(t)->t | a0 | a1 | a2 | a3; } +template +T void_func5(void *t, T a0, T a1, T a2, T a3, T a4) + { return static_cast*>(t)->t | a0 | a1 | a2 | a3 | a4; } +template +T const_void_func0(const void *t) + { return static_cast*>(t)->t; } +template +T const_void_func1(const void *t, T a0) + { return static_cast*>(t)->t | a0; } +template +T const_void_func2(const void *t, T a0, T a1) + { return static_cast*>(t)->t | a0 | a1; } +template +T const_void_func3(const void *t, T a0, T a1, T a2) + { return static_cast*>(t)->t | a0 | a1 | a2; } +template +T const_void_func4(const void *t, T a0, T a1, T a2, T a3) + { return static_cast*>(t)->t | a0 | a1 | a2 | a3; } +template +T const_void_func5(const void *t, T a0, T a1, T a2, T a3, T a4) + { return static_cast*>(t)->t | a0 | a1 | a2 | a3 | a4; } +template +T volatile_void_func0(volatile void *t) + { return static_cast*>(t)->t; } +template +T volatile_void_func1(volatile void *t, T a0) + { return static_cast*>(t)->t | a0; } +template +T volatile_void_func2(volatile void *t, T a0, T a1) + { return static_cast*>(t)->t | a0 | a1; } +template +T volatile_void_func3(volatile void *t, T a0, T a1, T a2) + { return static_cast*>(t)->t | a0 | a1 | a2; } +template +T volatile_void_func4(volatile void *t, T a0, T a1, T a2, T a3) + { return static_cast*>(t)->t | a0 | a1 | a2 | a3; } +template +T volatile_void_func5(volatile void *t, T a0, T a1, T a2, T a3, T a4) + { return static_cast*>(t)->t | a0 | a1 | a2 | a3 | a4; } template -T const_volatile_func0(const volatile Thing *t) { return t->t; } +T const_volatile_void_func0(const volatile void *t) + { return static_cast*>(t)->t; } template -T const_volatile_func1(const volatile Thing *t, T a0) { return t->t | a0; } +T const_volatile_void_func1(const volatile void *t, T a0) + { return static_cast*>(t)->t | a0; } template -T const_volatile_func2(const volatile Thing *t, T a0, T a1) { return t->t | a0 | a1; } +T const_volatile_void_func2(const volatile void *t, T a0, T a1) + { return static_cast*>(t)->t | a0 | a1; } template -T const_volatile_func3(const volatile Thing *t, T a0, T a1, T a2) { return t->t | a0 | a1 | a2; } +T const_volatile_void_func3(const volatile void *t, T a0, T a1, T a2) + { return static_cast*>(t)->t | a0 | a1 | a2; } template -T const_volatile_func4(const volatile Thing *t, T a0, T a1, T a2, T a3) { return t->t | a0 | a1 | a2 | a3; } +T const_volatile_void_func4(const volatile void *t, T a0, T a1, T a2, T a3) + { return static_cast*>(t)->t | a0 | a1 | a2 | a3; } template -T const_volatile_func5(const volatile Thing *t, T a0, T a1, T a2, T a3, T a4) { return t->t | a0 | a1 | a2 | a3 | a4; } +T const_volatile_void_func5(const volatile void *t, T a0, T a1, T a2, T a3, T a4) + { return static_cast*>(t)->t | a0 | a1 | a2 | a3 | a4; } // function call and result verification @@ -199,9 +321,13 @@ void test_dispatch0() { Verifier::verify0((volatile Thing*)&thing, &Thing::volatile_member_func0); Verifier::verify0((const volatile Thing*)&thing, &Thing::const_volatile_member_func0); Verifier::verify0(&thing, &bound_func0); - Verifier::verify0((const Thing*)&thing, &const_func0); - Verifier::verify0((volatile Thing*)&thing, &volatile_func0); - Verifier::verify0((const volatile Thing*)&thing, &const_volatile_func0); + Verifier::verify0((const Thing*)&thing, &const_bound_func0); + Verifier::verify0((volatile Thing*)&thing, &volatile_bound_func0); + Verifier::verify0((const volatile Thing*)&thing, &const_volatile_bound_func0); + Verifier::verify0(&thing, &void_func0); + Verifier::verify0((const Thing*)&thing, &const_void_func0); + Verifier::verify0((volatile Thing*)&thing, &volatile_void_func0); + Verifier::verify0((const volatile Thing*)&thing, &const_volatile_void_func0); Verifier::verify0(callback(static_func0)); Callback cb(static_func0); @@ -222,9 +348,13 @@ void test_dispatch1() { Verifier::verify1((volatile Thing*)&thing, &Thing::volatile_member_func1); Verifier::verify1((const volatile Thing*)&thing, &Thing::const_volatile_member_func1); Verifier::verify1(&thing, &bound_func1); - Verifier::verify1((const Thing*)&thing, &const_func1); - Verifier::verify1((volatile Thing*)&thing, &volatile_func1); - Verifier::verify1((const volatile Thing*)&thing, &const_volatile_func1); + Verifier::verify1((const Thing*)&thing, &const_bound_func1); + Verifier::verify1((volatile Thing*)&thing, &volatile_bound_func1); + Verifier::verify1((const volatile Thing*)&thing, &const_volatile_bound_func1); + Verifier::verify1(&thing, &void_func1); + Verifier::verify1((const Thing*)&thing, &const_void_func1); + Verifier::verify1((volatile Thing*)&thing, &volatile_void_func1); + Verifier::verify1((const volatile Thing*)&thing, &const_volatile_void_func1); Verifier::verify1(callback(static_func1)); Callback cb(static_func1); @@ -245,9 +375,13 @@ void test_dispatch2() { Verifier::verify2((volatile Thing*)&thing, &Thing::volatile_member_func2); Verifier::verify2((const volatile Thing*)&thing, &Thing::const_volatile_member_func2); Verifier::verify2(&thing, &bound_func2); - Verifier::verify2((const Thing*)&thing, &const_func2); - Verifier::verify2((volatile Thing*)&thing, &volatile_func2); - Verifier::verify2((const volatile Thing*)&thing, &const_volatile_func2); + Verifier::verify2((const Thing*)&thing, &const_bound_func2); + Verifier::verify2((volatile Thing*)&thing, &volatile_bound_func2); + Verifier::verify2((const volatile Thing*)&thing, &const_volatile_bound_func2); + Verifier::verify2(&thing, &void_func2); + Verifier::verify2((const Thing*)&thing, &const_void_func2); + Verifier::verify2((volatile Thing*)&thing, &volatile_void_func2); + Verifier::verify2((const volatile Thing*)&thing, &const_volatile_void_func2); Verifier::verify2(callback(static_func2)); Callback cb(static_func2); @@ -268,9 +402,13 @@ void test_dispatch3() { Verifier::verify3((volatile Thing*)&thing, &Thing::volatile_member_func3); Verifier::verify3((const volatile Thing*)&thing, &Thing::const_volatile_member_func3); Verifier::verify3(&thing, &bound_func3); - Verifier::verify3((const Thing*)&thing, &const_func3); - Verifier::verify3((volatile Thing*)&thing, &volatile_func3); - Verifier::verify3((const volatile Thing*)&thing, &const_volatile_func3); + Verifier::verify3((const Thing*)&thing, &const_bound_func3); + Verifier::verify3((volatile Thing*)&thing, &volatile_bound_func3); + Verifier::verify3((const volatile Thing*)&thing, &const_volatile_bound_func3); + Verifier::verify3(&thing, &void_func3); + Verifier::verify3((const Thing*)&thing, &const_void_func3); + Verifier::verify3((volatile Thing*)&thing, &volatile_void_func3); + Verifier::verify3((const volatile Thing*)&thing, &const_volatile_void_func3); Verifier::verify3(callback(static_func3)); Callback cb(static_func3); @@ -291,9 +429,13 @@ void test_dispatch4() { Verifier::verify4((volatile Thing*)&thing, &Thing::volatile_member_func4); Verifier::verify4((const volatile Thing*)&thing, &Thing::const_volatile_member_func4); Verifier::verify4(&thing, &bound_func4); - Verifier::verify4((const Thing*)&thing, &const_func4); - Verifier::verify4((volatile Thing*)&thing, &volatile_func4); - Verifier::verify4((const volatile Thing*)&thing, &const_volatile_func4); + Verifier::verify4((const Thing*)&thing, &const_bound_func4); + Verifier::verify4((volatile Thing*)&thing, &volatile_bound_func4); + Verifier::verify4((const volatile Thing*)&thing, &const_volatile_bound_func4); + Verifier::verify4(&thing, &void_func4); + Verifier::verify4((const Thing*)&thing, &const_void_func4); + Verifier::verify4((volatile Thing*)&thing, &volatile_void_func4); + Verifier::verify4((const volatile Thing*)&thing, &const_volatile_void_func4); Verifier::verify4(callback(static_func4)); Callback cb(static_func4); @@ -314,9 +456,13 @@ void test_dispatch5() { Verifier::verify5((volatile Thing*)&thing, &Thing::volatile_member_func5); Verifier::verify5((const volatile Thing*)&thing, &Thing::const_volatile_member_func5); Verifier::verify5(&thing, &bound_func5); - Verifier::verify5((const Thing*)&thing, &const_func5); - Verifier::verify5((volatile Thing*)&thing, &volatile_func5); - Verifier::verify5((const volatile Thing*)&thing, &const_volatile_func5); + Verifier::verify5((const Thing*)&thing, &const_bound_func5); + Verifier::verify5((volatile Thing*)&thing, &volatile_bound_func5); + Verifier::verify5((const volatile Thing*)&thing, &const_volatile_bound_func5); + Verifier::verify5(&thing, &void_func5); + Verifier::verify5((const Thing*)&thing, &const_void_func5); + Verifier::verify5((volatile Thing*)&thing, &volatile_void_func5); + Verifier::verify5((const volatile Thing*)&thing, &const_volatile_void_func5); Verifier::verify5(callback(static_func5)); Callback cb(static_func5); diff --git a/TESTS/mbed_functional/functionpointer/main.cpp b/TESTS/mbed_functional/functionpointer/main.cpp index 7a61dc0abdf..603bd4336f8 100644 --- a/TESTS/mbed_functional/functionpointer/main.cpp +++ b/TESTS/mbed_functional/functionpointer/main.cpp @@ -8,17 +8,23 @@ using namespace utest::v1; // static functions template -T static_func0() { return 0; } +T static_func0() + { return 0; } template -T static_func1(T a0) { return 0 | a0; } +T static_func1(T a0) + { return 0 | a0; } template -T static_func2(T a0, T a1) { return 0 | a0 | a1; } +T static_func2(T a0, T a1) + { return 0 | a0 | a1; } template -T static_func3(T a0, T a1, T a2) { return 0 | a0 | a1 | a2; } +T static_func3(T a0, T a1, T a2) + { return 0 | a0 | a1 | a2; } template -T static_func4(T a0, T a1, T a2, T a3) { return 0 | a0 | a1 | a2 | a3; } +T static_func4(T a0, T a1, T a2, T a3) + { return 0 | a0 | a1 | a2 | a3; } template -T static_func5(T a0, T a1, T a2, T a3, T a4) { return 0 | a0 | a1 | a2 | a3 | a4; } +T static_func5(T a0, T a1, T a2, T a3, T a4) + { return 0 | a0 | a1 | a2 | a3 | a4; } // class functions template @@ -26,90 +32,206 @@ struct Thing { T t; Thing() : t(0x80) {} - T member_func0() { return t; } - T member_func1(T a0) { return t | a0; } - T member_func2(T a0, T a1) { return t | a0 | a1; } - T member_func3(T a0, T a1, T a2) { return t | a0 | a1 | a2; } - T member_func4(T a0, T a1, T a2, T a3) { return t | a0 | a1 | a2 | a3; } - T member_func5(T a0, T a1, T a2, T a3, T a4) { return t | a0 | a1 | a2 | a3 | a4; } - - T const_member_func0() const { return t; } - T const_member_func1(T a0) const { return t | a0; } - T const_member_func2(T a0, T a1) const { return t | a0 | a1; } - T const_member_func3(T a0, T a1, T a2) const { return t | a0 | a1 | a2; } - T const_member_func4(T a0, T a1, T a2, T a3) const { return t | a0 | a1 | a2 | a3; } - T const_member_func5(T a0, T a1, T a2, T a3, T a4) const { return t | a0 | a1 | a2 | a3 | a4; } - - T volatile_member_func0() volatile { return t; } - T volatile_member_func1(T a0) volatile { return t | a0; } - T volatile_member_func2(T a0, T a1) volatile { return t | a0 | a1; } - T volatile_member_func3(T a0, T a1, T a2) volatile { return t | a0 | a1 | a2; } - T volatile_member_func4(T a0, T a1, T a2, T a3) volatile { return t | a0 | a1 | a2 | a3; } - T volatile_member_func5(T a0, T a1, T a2, T a3, T a4) volatile { return t | a0 | a1 | a2 | a3 | a4; } - - T const_volatile_member_func0() const volatile { return t; } - T const_volatile_member_func1(T a0) const volatile { return t | a0; } - T const_volatile_member_func2(T a0, T a1) const volatile { return t | a0 | a1; } - T const_volatile_member_func3(T a0, T a1, T a2) const volatile { return t | a0 | a1 | a2; } - T const_volatile_member_func4(T a0, T a1, T a2, T a3) const volatile { return t | a0 | a1 | a2 | a3; } - T const_volatile_member_func5(T a0, T a1, T a2, T a3, T a4) const volatile { return t | a0 | a1 | a2 | a3 | a4; } + T member_func0() + { return t; } + T member_func1(T a0) + { return t | a0; } + T member_func2(T a0, T a1) + { return t | a0 | a1; } + T member_func3(T a0, T a1, T a2) + { return t | a0 | a1 | a2; } + T member_func4(T a0, T a1, T a2, T a3) + { return t | a0 | a1 | a2 | a3; } + T member_func5(T a0, T a1, T a2, T a3, T a4) + { return t | a0 | a1 | a2 | a3 | a4; } + + T const_member_func0() const + { return t; } + T const_member_func1(T a0) const + { return t | a0; } + T const_member_func2(T a0, T a1) const + { return t | a0 | a1; } + T const_member_func3(T a0, T a1, T a2) const + { return t | a0 | a1 | a2; } + T const_member_func4(T a0, T a1, T a2, T a3) const + { return t | a0 | a1 | a2 | a3; } + T const_member_func5(T a0, T a1, T a2, T a3, T a4) const + { return t | a0 | a1 | a2 | a3 | a4; } + + T volatile_member_func0() volatile + { return t; } + T volatile_member_func1(T a0) volatile + { return t | a0; } + T volatile_member_func2(T a0, T a1) volatile + { return t | a0 | a1; } + T volatile_member_func3(T a0, T a1, T a2) volatile + { return t | a0 | a1 | a2; } + T volatile_member_func4(T a0, T a1, T a2, T a3) volatile + { return t | a0 | a1 | a2 | a3; } + T volatile_member_func5(T a0, T a1, T a2, T a3, T a4) volatile + { return t | a0 | a1 | a2 | a3 | a4; } + + T const_volatile_member_func0() const volatile + { return t; } + T const_volatile_member_func1(T a0) const volatile + { return t | a0; } + T const_volatile_member_func2(T a0, T a1) const volatile + { return t | a0 | a1; } + T const_volatile_member_func3(T a0, T a1, T a2) const volatile + { return t | a0 | a1 | a2; } + T const_volatile_member_func4(T a0, T a1, T a2, T a3) const volatile + { return t | a0 | a1 | a2 | a3; } + T const_volatile_member_func5(T a0, T a1, T a2, T a3, T a4) const volatile + { return t | a0 | a1 | a2 | a3 | a4; } }; // bound functions template -T bound_func0(Thing *t) { return t->t; } +T bound_func0(Thing *t) + { return t->t; } template -T bound_func1(Thing *t, T a0) { return t->t | a0; } +T bound_func1(Thing *t, T a0) + { return t->t | a0; } template -T bound_func2(Thing *t, T a0, T a1) { return t->t | a0 | a1; } +T bound_func2(Thing *t, T a0, T a1) + { return t->t | a0 | a1; } template -T bound_func3(Thing *t, T a0, T a1, T a2) { return t->t | a0 | a1 | a2; } +T bound_func3(Thing *t, T a0, T a1, T a2) + { return t->t | a0 | a1 | a2; } template -T bound_func4(Thing *t, T a0, T a1, T a2, T a3) { return t->t | a0 | a1 | a2 | a3; } +T bound_func4(Thing *t, T a0, T a1, T a2, T a3) + { return t->t | a0 | a1 | a2 | a3; } template -T bound_func5(Thing *t, T a0, T a1, T a2, T a3, T a4) { return t->t | a0 | a1 | a2 | a3 | a4; } - -// const bound functions +T bound_func5(Thing *t, T a0, T a1, T a2, T a3, T a4) + { return t->t | a0 | a1 | a2 | a3 | a4; } template -T const_func0(const Thing *t) { return t->t; } +T const_bound_func0(const Thing *t) + { return t->t; } template -T const_func1(const Thing *t, T a0) { return t->t | a0; } +T const_bound_func1(const Thing *t, T a0) + { return t->t | a0; } template -T const_func2(const Thing *t, T a0, T a1) { return t->t | a0 | a1; } +T const_bound_func2(const Thing *t, T a0, T a1) + { return t->t | a0 | a1; } template -T const_func3(const Thing *t, T a0, T a1, T a2) { return t->t | a0 | a1 | a2; } +T const_bound_func3(const Thing *t, T a0, T a1, T a2) + { return t->t | a0 | a1 | a2; } template -T const_func4(const Thing *t, T a0, T a1, T a2, T a3) { return t->t | a0 | a1 | a2 | a3; } +T const_bound_func4(const Thing *t, T a0, T a1, T a2, T a3) + { return t->t | a0 | a1 | a2 | a3; } template -T const_func5(const Thing *t, T a0, T a1, T a2, T a3, T a4) { return t->t | a0 | a1 | a2 | a3 | a4; } - -// volatile bound functions +T const_bound_func5(const Thing *t, T a0, T a1, T a2, T a3, T a4) + { return t->t | a0 | a1 | a2 | a3 | a4; } +template +T volatile_bound_func0(volatile Thing *t) + { return t->t; } +template +T volatile_bound_func1(volatile Thing *t, T a0) + { return t->t | a0; } +template +T volatile_bound_func2(volatile Thing *t, T a0, T a1) + { return t->t | a0 | a1; } +template +T volatile_bound_func3(volatile Thing *t, T a0, T a1, T a2) + { return t->t | a0 | a1 | a2; } +template +T volatile_bound_func4(volatile Thing *t, T a0, T a1, T a2, T a3) + { return t->t | a0 | a1 | a2 | a3; } template -T volatile_func0(volatile Thing *t) { return t->t; } +T volatile_bound_func5(volatile Thing *t, T a0, T a1, T a2, T a3, T a4) + { return t->t | a0 | a1 | a2 | a3 | a4; } template -T volatile_func1(volatile Thing *t, T a0) { return t->t | a0; } +T const_volatile_bound_func0(const volatile Thing *t) + { return t->t; } template -T volatile_func2(volatile Thing *t, T a0, T a1) { return t->t | a0 | a1; } +T const_volatile_bound_func1(const volatile Thing *t, T a0) + { return t->t | a0; } template -T volatile_func3(volatile Thing *t, T a0, T a1, T a2) { return t->t | a0 | a1 | a2; } +T const_volatile_bound_func2(const volatile Thing *t, T a0, T a1) + { return t->t | a0 | a1; } template -T volatile_func4(volatile Thing *t, T a0, T a1, T a2, T a3) { return t->t | a0 | a1 | a2 | a3; } +T const_volatile_bound_func3(const volatile Thing *t, T a0, T a1, T a2) + { return t->t | a0 | a1 | a2; } template -T volatile_func5(volatile Thing *t, T a0, T a1, T a2, T a3, T a4) { return t->t | a0 | a1 | a2 | a3 | a4; } +T const_volatile_bound_func4(const volatile Thing *t, T a0, T a1, T a2, T a3) + { return t->t | a0 | a1 | a2 | a3; } +template +T const_volatile_bound_func5(const volatile Thing *t, T a0, T a1, T a2, T a3, T a4) + { return t->t | a0 | a1 | a2 | a3 | a4; } -// const volatile bound functions +// void functions +template +T void_func0(void *t) + { return static_cast*>(t)->t; } +template +T void_func1(void *t, T a0) + { return static_cast*>(t)->t | a0; } +template +T void_func2(void *t, T a0, T a1) + { return static_cast*>(t)->t | a0 | a1; } +template +T void_func3(void *t, T a0, T a1, T a2) + { return static_cast*>(t)->t | a0 | a1 | a2; } +template +T void_func4(void *t, T a0, T a1, T a2, T a3) + { return static_cast*>(t)->t | a0 | a1 | a2 | a3; } +template +T void_func5(void *t, T a0, T a1, T a2, T a3, T a4) + { return static_cast*>(t)->t | a0 | a1 | a2 | a3 | a4; } +template +T const_void_func0(const void *t) + { return static_cast*>(t)->t; } +template +T const_void_func1(const void *t, T a0) + { return static_cast*>(t)->t | a0; } +template +T const_void_func2(const void *t, T a0, T a1) + { return static_cast*>(t)->t | a0 | a1; } +template +T const_void_func3(const void *t, T a0, T a1, T a2) + { return static_cast*>(t)->t | a0 | a1 | a2; } +template +T const_void_func4(const void *t, T a0, T a1, T a2, T a3) + { return static_cast*>(t)->t | a0 | a1 | a2 | a3; } +template +T const_void_func5(const void *t, T a0, T a1, T a2, T a3, T a4) + { return static_cast*>(t)->t | a0 | a1 | a2 | a3 | a4; } +template +T volatile_void_func0(volatile void *t) + { return static_cast*>(t)->t; } +template +T volatile_void_func1(volatile void *t, T a0) + { return static_cast*>(t)->t | a0; } +template +T volatile_void_func2(volatile void *t, T a0, T a1) + { return static_cast*>(t)->t | a0 | a1; } +template +T volatile_void_func3(volatile void *t, T a0, T a1, T a2) + { return static_cast*>(t)->t | a0 | a1 | a2; } +template +T volatile_void_func4(volatile void *t, T a0, T a1, T a2, T a3) + { return static_cast*>(t)->t | a0 | a1 | a2 | a3; } +template +T volatile_void_func5(volatile void *t, T a0, T a1, T a2, T a3, T a4) + { return static_cast*>(t)->t | a0 | a1 | a2 | a3 | a4; } template -T const_volatile_func0(const volatile Thing *t) { return t->t; } +T const_volatile_void_func0(const volatile void *t) + { return static_cast*>(t)->t; } template -T const_volatile_func1(const volatile Thing *t, T a0) { return t->t | a0; } +T const_volatile_void_func1(const volatile void *t, T a0) + { return static_cast*>(t)->t | a0; } template -T const_volatile_func2(const volatile Thing *t, T a0, T a1) { return t->t | a0 | a1; } +T const_volatile_void_func2(const volatile void *t, T a0, T a1) + { return static_cast*>(t)->t | a0 | a1; } template -T const_volatile_func3(const volatile Thing *t, T a0, T a1, T a2) { return t->t | a0 | a1 | a2; } +T const_volatile_void_func3(const volatile void *t, T a0, T a1, T a2) + { return static_cast*>(t)->t | a0 | a1 | a2; } template -T const_volatile_func4(const volatile Thing *t, T a0, T a1, T a2, T a3) { return t->t | a0 | a1 | a2 | a3; } +T const_volatile_void_func4(const volatile void *t, T a0, T a1, T a2, T a3) + { return static_cast*>(t)->t | a0 | a1 | a2 | a3; } template -T const_volatile_func5(const volatile Thing *t, T a0, T a1, T a2, T a3, T a4) { return t->t | a0 | a1 | a2 | a3 | a4; } +T const_volatile_void_func5(const volatile void *t, T a0, T a1, T a2, T a3, T a4) + { return static_cast*>(t)->t | a0 | a1 | a2 | a3 | a4; } // function call and result verification diff --git a/hal/api/Callback.h b/hal/api/Callback.h index fa784386551..c1a294bc4f3 100644 --- a/hal/api/Callback.h +++ b/hal/api/Callback.h @@ -44,6 +44,38 @@ class Callback { 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 + */ + Callback(void *obj, R (*func)(void*)) { + 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 + */ + Callback(const void *obj, R (*func)(const void*)) { + 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 + */ + Callback(volatile void *obj, R (*func)(volatile void*)) { + 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 + */ + Callback(const volatile void *obj, R (*func)(const volatile void*)) { + 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 @@ -143,6 +175,78 @@ class Callback { _thunk = func._thunk; } + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ + void attach(void *obj, R (*func)(void*)) { + struct local { + static R _thunk(void *obj, const void *func) { + return (*static_cast(func))( + (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 + */ + void attach(const void *obj, R (*func)(const void*)) { + struct local { + static R _thunk(void *obj, const void *func) { + return (*static_cast(func))( + (const 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 + */ + void attach(volatile void *obj, R (*func)(volatile void*)) { + struct local { + static R _thunk(void *obj, const void *func) { + return (*static_cast(func))( + (volatile 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 + */ + void attach(const volatile void *obj, R (*func)(const volatile void*)) { + struct local { + static R _thunk(void *obj, const void *func) { + return (*static_cast(func))( + (const volatile 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 @@ -369,6 +473,38 @@ class Callback { 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 + */ + Callback(void *obj, R (*func)(void*, 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 + */ + Callback(const void *obj, R (*func)(const void*, 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 + */ + Callback(volatile void *obj, R (*func)(volatile void*, 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 + */ + Callback(const volatile void *obj, R (*func)(const volatile void*, 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 @@ -468,6 +604,78 @@ class Callback { _thunk = func._thunk; } + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ + void attach(void *obj, R (*func)(void*, A0)) { + struct local { + static R _thunk(void *obj, const void *func, A0 a0) { + return (*static_cast(func))( + (void*)obj, a0); + } + }; + + 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 + */ + void attach(const void *obj, R (*func)(const void*, A0)) { + struct local { + static R _thunk(void *obj, const void *func, A0 a0) { + return (*static_cast(func))( + (const void*)obj, a0); + } + }; + + 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 + */ + void attach(volatile void *obj, R (*func)(volatile void*, A0)) { + struct local { + static R _thunk(void *obj, const void *func, A0 a0) { + return (*static_cast(func))( + (volatile void*)obj, a0); + } + }; + + 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 + */ + void attach(const volatile void *obj, R (*func)(const volatile void*, A0)) { + struct local { + static R _thunk(void *obj, const void *func, A0 a0) { + return (*static_cast(func))( + (const volatile void*)obj, a0); + } + }; + + 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 @@ -694,6 +902,38 @@ class Callback { 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 + */ + Callback(void *obj, R (*func)(void*, 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 + */ + Callback(const void *obj, R (*func)(const void*, 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 + */ + Callback(volatile void *obj, R (*func)(volatile void*, 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 + */ + Callback(const volatile void *obj, R (*func)(const volatile void*, 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 @@ -797,12 +1037,11 @@ class Callback { * @param obj Pointer to object to bind to function * @param func Static function to attach */ - template - void attach(T *obj, R (*func)(T*, A0, A1)) { + void attach(void *obj, R (*func)(void*, A0, A1)) { struct local { static R _thunk(void *obj, const void *func, A0 a0, A1 a1) { - return (*static_cast(func))( - (T*)obj, a0, a1); + return (*static_cast(func))( + (void*)obj, a0, a1); } }; @@ -816,12 +1055,11 @@ class Callback { * @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)) { + void attach(const void *obj, R (*func)(const void*, A0, A1)) { struct local { static R _thunk(void *obj, const void *func, A0 a0, A1 a1) { - return (*static_cast(func))( - (const T*)obj, a0, a1); + return (*static_cast(func))( + (const void*)obj, a0, a1); } }; @@ -835,12 +1073,11 @@ class Callback { * @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)) { + void attach(volatile void *obj, R (*func)(volatile void*, A0, A1)) { struct local { static R _thunk(void *obj, const void *func, A0 a0, A1 a1) { - return (*static_cast(func))( - (volatile T*)obj, a0, a1); + return (*static_cast(func))( + (volatile void*)obj, a0, a1); } }; @@ -854,12 +1091,11 @@ class Callback { * @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)) { + void attach(const volatile void *obj, R (*func)(const volatile void*, A0, A1)) { struct local { static R _thunk(void *obj, const void *func, A0 a0, A1 a1) { - return (*static_cast(func))( - (const volatile T*)obj, a0, a1); + return (*static_cast(func))( + (const volatile void*)obj, a0, a1); } }; @@ -869,17 +1105,16 @@ class Callback { _thunk = &local::_thunk; } - /** Attach a member function - * @param obj Pointer to object to invoke member function on - * @param func Member function to attach + /** 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(T *obj, R (T::*func)(A0, A1)) { + template + void attach(T *obj, R (*func)(T*, A0, A1)) { struct local { static R _thunk(void *obj, const void *func, A0 a0, A1 a1) { - return (((T*)obj)->* - (*static_cast(func)))( - a0, a1); + return (*static_cast(func))( + (T*)obj, a0, a1); } }; @@ -889,17 +1124,16 @@ class Callback { _thunk = &local::_thunk; } - /** Attach a member function - * @param obj Pointer to object to invoke member function on - * @param func Member function to attach + /** 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 (T::*func)(A0, A1) const) { + template + void attach(const T *obj, R (*func)(const T*, A0, A1)) { struct local { static R _thunk(void *obj, const void *func, A0 a0, A1 a1) { - return (((const T*)obj)->* - (*static_cast(func)))( - a0, a1); + return (*static_cast(func))( + (const T*)obj, a0, a1); } }; @@ -909,9 +1143,87 @@ class Callback { _thunk = &local::_thunk; } - /** Attach a member function - * @param obj Pointer to object to invoke member function on - * @param func Member function to attach + /** 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, const void *func, A0 a0, A1 a1) { + return (*static_cast(func))( + (volatile T*)obj, a0, a1); + } + }; + + 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, const void *func, A0 a0, A1 a1) { + return (*static_cast(func))( + (const volatile T*)obj, a0, a1); + } + }; + + 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(T *obj, R (T::*func)(A0, A1)) { + struct local { + static R _thunk(void *obj, const void *func, A0 a0, A1 a1) { + return (((T*)obj)->* + (*static_cast(func)))( + a0, a1); + } + }; + + 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, const void *func, A0 a0, A1 a1) { + return (((const T*)obj)->* + (*static_cast(func)))( + a0, a1); + } + }; + + 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) { @@ -1019,6 +1331,38 @@ class Callback { 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 + */ + Callback(void *obj, R (*func)(void*, 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 + */ + Callback(const void *obj, R (*func)(const void*, 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 + */ + Callback(volatile void *obj, R (*func)(volatile void*, 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 + */ + Callback(const volatile void *obj, R (*func)(const volatile void*, 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 @@ -1118,6 +1462,78 @@ class Callback { _thunk = func._thunk; } + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ + void attach(void *obj, R (*func)(void*, A0, A1, A2)) { + struct local { + static R _thunk(void *obj, const void *func, A0 a0, A1 a1, A2 a2) { + return (*static_cast(func))( + (void*)obj, a0, a1, a2); + } + }; + + 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 + */ + void attach(const void *obj, R (*func)(const void*, A0, A1, A2)) { + struct local { + static R _thunk(void *obj, const void *func, A0 a0, A1 a1, A2 a2) { + return (*static_cast(func))( + (const void*)obj, a0, a1, a2); + } + }; + + 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 + */ + void attach(volatile void *obj, R (*func)(volatile void*, A0, A1, A2)) { + struct local { + static R _thunk(void *obj, const void *func, A0 a0, A1 a1, A2 a2) { + return (*static_cast(func))( + (volatile void*)obj, a0, a1, a2); + } + }; + + 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 + */ + void attach(const volatile void *obj, R (*func)(const volatile void*, A0, A1, A2)) { + struct local { + static R _thunk(void *obj, const void *func, A0 a0, A1 a1, A2 a2) { + return (*static_cast(func))( + (const volatile void*)obj, a0, a1, a2); + } + }; + + 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 @@ -1344,6 +1760,38 @@ class Callback { 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 + */ + Callback(void *obj, R (*func)(void*, 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 + */ + Callback(const void *obj, R (*func)(const void*, 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 + */ + Callback(volatile void *obj, R (*func)(volatile void*, 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 + */ + Callback(const volatile void *obj, R (*func)(const volatile void*, 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 @@ -1443,6 +1891,78 @@ class Callback { _thunk = func._thunk; } + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ + void attach(void *obj, R (*func)(void*, A0, A1, A2, A3)) { + struct local { + static R _thunk(void *obj, const void *func, A0 a0, A1 a1, A2 a2, A3 a3) { + return (*static_cast(func))( + (void*)obj, a0, a1, a2, a3); + } + }; + + 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 + */ + void attach(const void *obj, R (*func)(const void*, A0, A1, A2, A3)) { + struct local { + static R _thunk(void *obj, const void *func, A0 a0, A1 a1, A2 a2, A3 a3) { + return (*static_cast(func))( + (const void*)obj, a0, a1, a2, a3); + } + }; + + 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 + */ + void attach(volatile void *obj, R (*func)(volatile void*, A0, A1, A2, A3)) { + struct local { + static R _thunk(void *obj, const void *func, A0 a0, A1 a1, A2 a2, A3 a3) { + return (*static_cast(func))( + (volatile void*)obj, a0, a1, a2, a3); + } + }; + + 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 + */ + void attach(const volatile void *obj, R (*func)(const volatile void*, A0, A1, A2, A3)) { + struct local { + static R _thunk(void *obj, const void *func, A0 a0, A1 a1, A2 a2, A3 a3) { + return (*static_cast(func))( + (const volatile void*)obj, a0, a1, a2, a3); + } + }; + + 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 @@ -1669,6 +2189,38 @@ class Callback { 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 + */ + Callback(void *obj, R (*func)(void*, 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 + */ + Callback(const void *obj, R (*func)(const void*, 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 + */ + Callback(volatile void *obj, R (*func)(volatile void*, 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 + */ + Callback(const volatile void *obj, R (*func)(const volatile void*, 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 @@ -1754,18 +2306,90 @@ class Callback { memset(&_func, 0, sizeof _func); memcpy(&_func, &func, sizeof func); - _obj = 0; - _thunk = func ? &local::_thunk : 0; - } - - /** Attach a Callback - * @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; - _thunk = func._thunk; + _obj = 0; + _thunk = func ? &local::_thunk : 0; + } + + /** Attach a Callback + * @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; + _thunk = func._thunk; + } + + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ + void attach(void *obj, R (*func)(void*, A0, A1, A2, A3, A4)) { + struct local { + static R _thunk(void *obj, const void *func, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) { + return (*static_cast(func))( + (void*)obj, a0, a1, a2, a3, a4); + } + }; + + 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 + */ + void attach(const void *obj, R (*func)(const void*, A0, A1, A2, A3, A4)) { + struct local { + static R _thunk(void *obj, const void *func, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) { + return (*static_cast(func))( + (const void*)obj, a0, a1, a2, a3, a4); + } + }; + + 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 + */ + void attach(volatile void *obj, R (*func)(volatile void*, A0, A1, A2, A3, A4)) { + struct local { + static R _thunk(void *obj, const void *func, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) { + return (*static_cast(func))( + (volatile void*)obj, a0, a1, a2, a3, a4); + } + }; + + 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 + */ + void attach(const volatile void *obj, R (*func)(const volatile void*, A0, A1, A2, A3, A4)) { + struct local { + static R _thunk(void *obj, const void *func, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) { + return (*static_cast(func))( + (const volatile void*)obj, a0, a1, a2, a3, a4); + } + }; + + memset(&_func, 0, sizeof _func); + memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; + _thunk = &local::_thunk; } /** Attach a static function with a bound pointer @@ -2004,6 +2628,50 @@ 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(void *obj, R (*func)(void*)) { + 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 void *obj, R (*func)(const void*)) { + 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 void *obj, R (*func)(volatile void*)) { + 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 void *obj, R (*func)(const volatile void*)) { + return Callback(obj, func); +} + /** Create a callback class with type infered from the arguments * * @param obj Optional pointer to object to bind to function @@ -2113,6 +2781,50 @@ 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(void *obj, R (*func)(void*, 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 void *obj, R (*func)(const void*, 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 void *obj, R (*func)(volatile void*, 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 void *obj, R (*func)(const volatile void*, 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 @@ -2222,6 +2934,50 @@ 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(void *obj, R (*func)(void*, 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 void *obj, R (*func)(const void*, 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 void *obj, R (*func)(volatile void*, 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 void *obj, R (*func)(const volatile void*, 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 @@ -2331,6 +3087,50 @@ 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(void *obj, R (*func)(void*, 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 void *obj, R (*func)(const void*, 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 void *obj, R (*func)(volatile void*, 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 void *obj, R (*func)(const volatile void*, 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 @@ -2440,6 +3240,50 @@ 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(void *obj, R (*func)(void*, 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 void *obj, R (*func)(const void*, 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 void *obj, R (*func)(volatile void*, 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 void *obj, R (*func)(const volatile void*, 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 @@ -2549,6 +3393,50 @@ Callback callback(const Callback & 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(void *obj, R (*func)(void*, 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 void *obj, R (*func)(const void*, 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 void *obj, R (*func)(volatile void*, 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 void *obj, R (*func)(const volatile void*, 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 From 022f821d0c00b416f8e0cc3529fcc6df9f8ff1d5 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Thu, 25 Aug 2016 13:08:35 -0500 Subject: [PATCH 5/5] Rewrote thread deprecation notices to help migration User feedback indicated that the previous deprecation notices were confusing and mislead migration from the old style of thread spawning. The deprecation notices were updated to emphasize the replacement functions, and examples of correct usage were added in the doxygen. --- rtos/rtos/Thread.h | 112 ++++++++++++++++++++++++++++++++------------- 1 file changed, 79 insertions(+), 33 deletions(-) diff --git a/rtos/rtos/Thread.h b/rtos/rtos/Thread.h index 9d3356a6078..f2b5cb9300a 100644 --- a/rtos/rtos/Thread.h +++ b/rtos/rtos/Thread.h @@ -31,7 +31,34 @@ namespace rtos { -/** The Thread class allow defining, creating, and controlling thread functions in the system. */ +/** The Thread class allow defining, creating, and controlling thread functions in the system. + * + * Example: + * @code + * #include "mbed.h" + * #include "rtos.h" + * + * Thread thread; + * DigitalOut led1(LED1); + * volatile bool running = true; + * + * // Blink function toggles the led in a long running loop + * void blink(DigitalOut *led) { + * while (running) { + * *led = !*led; + * Thread::wait(1000); + * } + * } + * + * // Spawns a thread to run blink for 5 seconds + * int main() { + * thread.start(led1, blink); + * Thread::wait(5000); + * running = false; + * thread.join(); + * } + * @endcode + */ class Thread { public: /** Allocate a new thread without starting execution @@ -52,15 +79,20 @@ class Thread { @param stack_size stack size (in bytes) requirements for the thread function. (default: DEFAULT_STACK_SIZE). @param stack_pointer pointer to the stack area to be used by this thread (default: NULL). @deprecated - Thread-spawning constructors hide errors and may lead to complex - program state when a thread is declared. + Thread-spawning constructors hide errors. Replaced by thread.start(task). - The explicit Thread::start member function should be used to spawn - a thread. + @code + Thread thread(priority, stack_size, stack_pointer); + + osStatus status = thread.start(task); + if (status != osOK) { + error("oh no!"); + } + @endcode */ MBED_DEPRECATED_SINCE("mbed-os-5.1", - "Thread-spawning constructors hide errors and may lead to complex " - "program state when a thread is declared") + "Thread-spawning constructors hide errors. " + "Replaced by thread.start(task).") Thread(mbed::Callback task, osPriority priority=osPriorityNormal, uint32_t stack_size=DEFAULT_STACK_SIZE, @@ -76,21 +108,26 @@ class Thread { @param stack_size stack size (in bytes) requirements for the thread function. (default: DEFAULT_STACK_SIZE). @param stack_pointer pointer to the stack area to be used by this thread (default: NULL). @deprecated - Thread-spawning constructors hide errors and may lead to complex - program state when a thread is declared. + Thread-spawning constructors hide errors. Replaced by thread.start(callback(argument, task)). + + @code + Thread thread(priority, stack_size, stack_pointer); - The explicit Thread::start member function should be used to spawn - a thread. + osStatus status = thread.start(callback(argument, task)); + if (status != osOK) { + error("oh no!"); + } + @endcode */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", - "Thread-spawning constructors hide errors and may lead to complex " - "program state when a thread is declared") - Thread(T *obj, void (T::*method)(), + "Thread-spawning constructors hide errors. " + "Replaced by thread.start(callback(argument, task)).") + Thread(T *argument, void (T::*task)(), osPriority priority=osPriorityNormal, uint32_t stack_size=DEFAULT_STACK_SIZE, unsigned char *stack_pointer=NULL) { - constructor(mbed::callback(obj, method), + constructor(mbed::callback(argument, task), priority, stack_size, stack_pointer); } @@ -102,21 +139,26 @@ class Thread { @param stack_size stack size (in bytes) requirements for the thread function. (default: DEFAULT_STACK_SIZE). @param stack_pointer pointer to the stack area to be used by this thread (default: NULL). @deprecated - Thread-spawning constructors hide errors and may lead to complex - program state when a thread is declared. + Thread-spawning constructors hide errors. Replaced by thread.start(callback(argument, task)). - The explicit Thread::start member function should be used to spawn - a thread. + @code + Thread thread(priority, stack_size, stack_pointer); + + osStatus status = thread.start(callback(argument, task)); + if (status != osOK) { + error("oh no!"); + } + @endcode */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", - "Thread-spawning constructors hide errors and may lead to complex " - "program state when a thread is declared") - Thread(T *obj, void (*method)(T *), + "Thread-spawning constructors hide errors. " + "Replaced by thread.start(callback(argument, task)).") + Thread(T *argument, void (*task)(T *), osPriority priority=osPriorityNormal, uint32_t stack_size=DEFAULT_STACK_SIZE, unsigned char *stack_pointer=NULL) { - constructor(mbed::callback(obj, method), + constructor(mbed::callback(argument, task), priority, stack_size, stack_pointer); } @@ -128,15 +170,20 @@ class Thread { @param stack_size stack size (in bytes) requirements for the thread function. (default: DEFAULT_STACK_SIZE). @param stack_pointer pointer to the stack area to be used by this thread (default: NULL). @deprecated - Thread-spawning constructors hide errors and may lead to complex - program state when a thread is declared. + Thread-spawning constructors hide errors. Replaced by thread.start(callback(argument, task)). + + @code + Thread thread(priority, stack_size, stack_pointer); - The explicit Thread::start member function should be used to spawn - a thread. + osStatus status = thread.start(callback(argument, task)); + if (status != osOK) { + error("oh no!"); + } + @endcode */ MBED_DEPRECATED_SINCE("mbed-os-5.1", - "Thread-spawning constructors hide errors and may lead to complex " - "program state when a thread is declared") + "Thread-spawning constructors hide errors. " + "Replaced by thread.start(callback(argument, task)).") Thread(void (*task)(void const *argument), void *argument=NULL, osPriority priority=osPriorityNormal, uint32_t stack_size=DEFAULT_STACK_SIZE, @@ -156,13 +203,12 @@ class Thread { @param method function to be executed by this thread. @return status code that indicates the execution status of the function. @deprecated - The start function does not support cv-qualifiers. Replaced by - start(callback(obj, method)). + The start function does not support cv-qualifiers. Replaced by start(callback(obj, method)). */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", - "The start function does not support cv-qualifiers. Replaced by " - "start(callback(obj, method)).") + "The start function does not support cv-qualifiers. " + "Replaced by thread.start(callback(obj, method)).") osStatus start(T *obj, M method) { return start(mbed::callback(obj, method)); }