From 756a09003c065330c899cae64fbb56fd1840ff7b Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Thu, 25 Aug 2016 12:25:01 -0500 Subject: [PATCH 1/2] 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 | 300 ++++-- .../mbed_functional/functionpointer/main.cpp | 240 +++-- hal/api/Callback.h | 888 ++++++++++++++++++ 3 files changed, 1292 insertions(+), 136 deletions(-) diff --git a/TESTS/mbed_functional/callback/main.cpp b/TESTS/mbed_functional/callback/main.cpp index 8442448e53..6f6b7da4f7 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 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 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 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 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; } +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_bound_func0(const Thing *t) + { return t->t; } +template +T const_bound_func1(const Thing *t, T a0) + { return t->t | a0; } +template +T const_bound_func2(const Thing *t, T a0, T a1) + { return t->t | a0 | a1; } +template +T const_bound_func3(const Thing *t, T a0, T a1, T a2) + { return t->t | a0 | a1 | a2; } +template +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_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_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 const_volatile_bound_func0(const volatile Thing *t) + { return t->t; } +template +T const_volatile_bound_func1(const volatile Thing *t, T a0) + { return t->t | a0; } +template +T const_volatile_bound_func2(const volatile Thing *t, T a0, T a1) + { return t->t | a0 | a1; } +template +T const_volatile_bound_func3(const volatile Thing *t, T a0, T a1, T a2) + { return t->t | a0 | a1 | a2; } +template +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 bound functions +// void functions template -T const_func0(const Thing *t) { return t->t; } +T void_func0(void *t) + { return static_cast*>(t)->t; } template -T const_func1(const Thing *t, T a0) { return t->t | a0; } +T void_func1(void *t, T a0) + { return static_cast*>(t)->t | a0; } template -T const_func2(const Thing *t, T a0, T a1) { return t->t | a0 | a1; } +T void_func2(void *t, T a0, T a1) + { return static_cast*>(t)->t | a0 | a1; } template -T const_func3(const Thing *t, T a0, T a1, T a2) { return t->t | a0 | a1 | a2; } +T void_func3(void *t, T a0, T a1, T a2) + { return static_cast*>(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 void_func4(void *t, T a0, T a1, T a2, T a3) + { return static_cast*>(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 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 volatile_func0(volatile Thing *t) { return t->t; } +T const_void_func0(const void *t) + { return static_cast*>(t)->t; } template -T volatile_func1(volatile Thing *t, T a0) { return t->t | a0; } +T const_void_func1(const void *t, T a0) + { return static_cast*>(t)->t | a0; } template -T volatile_func2(volatile Thing *t, T a0, T a1) { return t->t | a0 | a1; } +T const_void_func2(const void *t, T a0, T a1) + { return static_cast*>(t)->t | a0 | a1; } template -T volatile_func3(volatile Thing *t, T a0, T a1, T a2) { return t->t | a0 | a1 | a2; } +T const_void_func3(const void *t, T a0, T a1, T a2) + { return static_cast*>(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; } +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 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 +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 const_volatile_func0(const volatile Thing *t) { return t->t; } +T volatile_void_func0(volatile void *t) + { return static_cast*>(t)->t; } template -T const_volatile_func1(const volatile Thing *t, T a0) { return t->t | a0; } +T volatile_void_func1(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 volatile_void_func2(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 volatile_void_func3(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 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 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_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_void_func0(const volatile void *t) + { return static_cast*>(t)->t; } +template +T const_volatile_void_func1(const volatile void *t, T a0) + { return static_cast*>(t)->t | a0; } +template +T const_volatile_void_func2(const volatile void *t, T a0, T a1) + { return static_cast*>(t)->t | a0 | a1; } +template +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_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_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 7a61dc0abd..603bd4336f 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 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 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 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 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; } +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_bound_func0(const Thing *t) + { return t->t; } +template +T const_bound_func1(const Thing *t, T a0) + { return t->t | a0; } +template +T const_bound_func2(const Thing *t, T a0, T a1) + { return t->t | a0 | a1; } +template +T const_bound_func3(const Thing *t, T a0, T a1, T a2) + { return t->t | a0 | a1 | a2; } +template +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_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_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 const_volatile_bound_func0(const volatile Thing *t) + { return t->t; } +template +T const_volatile_bound_func1(const volatile Thing *t, T a0) + { return t->t | a0; } +template +T const_volatile_bound_func2(const volatile Thing *t, T a0, T a1) + { return t->t | a0 | a1; } +template +T const_volatile_bound_func3(const volatile Thing *t, T a0, T a1, T a2) + { return t->t | a0 | a1 | a2; } +template +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 bound functions +// void functions template -T const_func0(const Thing *t) { return t->t; } +T void_func0(void *t) + { return static_cast*>(t)->t; } template -T const_func1(const Thing *t, T a0) { return t->t | a0; } +T void_func1(void *t, T a0) + { return static_cast*>(t)->t | a0; } template -T const_func2(const Thing *t, T a0, T a1) { return t->t | a0 | a1; } +T void_func2(void *t, T a0, T a1) + { return static_cast*>(t)->t | a0 | a1; } template -T const_func3(const Thing *t, T a0, T a1, T a2) { return t->t | a0 | a1 | a2; } +T void_func3(void *t, T a0, T a1, T a2) + { return static_cast*>(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 void_func4(void *t, T a0, T a1, T a2, T a3) + { return static_cast*>(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 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 volatile_func0(volatile Thing *t) { return t->t; } +T const_void_func0(const void *t) + { return static_cast*>(t)->t; } template -T volatile_func1(volatile Thing *t, T a0) { return t->t | a0; } +T const_void_func1(const void *t, T a0) + { return static_cast*>(t)->t | a0; } template -T volatile_func2(volatile Thing *t, T a0, T a1) { return t->t | a0 | a1; } +T const_void_func2(const void *t, T a0, T a1) + { return static_cast*>(t)->t | a0 | a1; } template -T volatile_func3(volatile Thing *t, T a0, T a1, T a2) { return t->t | a0 | a1 | a2; } +T const_void_func3(const void *t, T a0, T a1, T a2) + { return static_cast*>(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; } +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 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 +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 const_volatile_func0(const volatile Thing *t) { return t->t; } +T volatile_void_func0(volatile void *t) + { return static_cast*>(t)->t; } template -T const_volatile_func1(const volatile Thing *t, T a0) { return t->t | a0; } +T volatile_void_func1(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 volatile_void_func2(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 volatile_void_func3(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 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 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_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_void_func0(const volatile void *t) + { return static_cast*>(t)->t; } +template +T const_volatile_void_func1(const volatile void *t, T a0) + { return static_cast*>(t)->t | a0; } +template +T const_volatile_void_func2(const volatile void *t, T a0, T a1) + { return static_cast*>(t)->t | a0 | a1; } +template +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_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_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 fa78438655..c1a294bc4f 100644 --- a/hal/api/Callback.h +++ b/hal/api/Callback.h @@ -44,6 +44,38 @@ public: 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 @@ public: _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 @@ public: 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 @@ public: _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 @@ public: 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 @@ -793,6 +1033,78 @@ public: _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)) { + struct local { + static R _thunk(void *obj, const void *func, A0 a0, A1 a1) { + return (*static_cast(func))( + (void*)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 + */ + 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 void*)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 + */ + 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 void*)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 + */ + 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 void*)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 @@ -1019,6 +1331,38 @@ public: 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 @@ public: _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 @@ public: 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 @@ public: _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 @@ public: 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 @@ -1768,6 +2320,78 @@ public: _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 * @param obj Pointer to object to bind to function * @param func Static function to attach @@ -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 2/2] 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 9d3356a607..f2b5cb9300 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 @@ public: @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 @@ public: @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 (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 @@ public: @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 @@ public: @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 */ 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 @@ public: @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)); }