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
pull/2496/head
Christopher Haster 2016-08-19 15:49:49 -05:00
parent 45d25ed493
commit c71e67f2dc
6 changed files with 1100 additions and 328 deletions

View File

@ -203,20 +203,14 @@ void test_dispatch0() {
Verifier<T>::verify0((volatile Thing<T>*)&thing, &volatile_func0<T>); Verifier<T>::verify0((volatile Thing<T>*)&thing, &volatile_func0<T>);
Verifier<T>::verify0((const volatile Thing<T>*)&thing, &const_volatile_func0<T>); Verifier<T>::verify0((const volatile Thing<T>*)&thing, &const_volatile_func0<T>);
Verifier<T>::verify0(callback(static_func0<T>)); Verifier<T>::verify0(callback(static_func0<T>));
Verifier<T>::verify0(callback(&thing, &Thing<T>::member_func0));
Verifier<T>::verify0(callback((const Thing<T>*)&thing, &Thing<T>::const_member_func0));
Verifier<T>::verify0(callback((volatile Thing<T>*)&thing, &Thing<T>::volatile_member_func0));
Verifier<T>::verify0(callback((const volatile Thing<T>*)&thing, &Thing<T>::const_volatile_member_func0));
Verifier<T>::verify0(callback(&thing, &bound_func0<T>));
Verifier<T>::verify0(callback((const Thing<T>*)&thing, &const_func0<T>));
Verifier<T>::verify0(callback((volatile Thing<T>*)&thing, &volatile_func0<T>));
Verifier<T>::verify0(callback((const volatile Thing<T>*)&thing, &const_volatile_func0<T>));
Callback<T()> callback(static_func0); Callback<T()> cb(static_func0);
Verifier<T>::verify0(callback); Verifier<T>::verify0(cb);
callback.attach(&thing, &bound_func0<T>); cb = static_func0;
Verifier<T>::verify0(&callback, &Callback<T()>::call); Verifier<T>::verify0(cb);
Verifier<T>::verify0((void*)&callback, &Callback<T()>::thunk); cb.attach(&thing, &bound_func0<T>);
Verifier<T>::verify0(&cb, &Callback<T()>::call);
Verifier<T>::verify0((void*)&cb, &Callback<T()>::thunk);
} }
template <typename T> template <typename T>
@ -232,20 +226,14 @@ void test_dispatch1() {
Verifier<T>::verify1((volatile Thing<T>*)&thing, &volatile_func1<T>); Verifier<T>::verify1((volatile Thing<T>*)&thing, &volatile_func1<T>);
Verifier<T>::verify1((const volatile Thing<T>*)&thing, &const_volatile_func1<T>); Verifier<T>::verify1((const volatile Thing<T>*)&thing, &const_volatile_func1<T>);
Verifier<T>::verify1(callback(static_func1<T>)); Verifier<T>::verify1(callback(static_func1<T>));
Verifier<T>::verify1(callback(&thing, &Thing<T>::member_func1));
Verifier<T>::verify1(callback((const Thing<T>*)&thing, &Thing<T>::const_member_func1));
Verifier<T>::verify1(callback((volatile Thing<T>*)&thing, &Thing<T>::volatile_member_func1));
Verifier<T>::verify1(callback((const volatile Thing<T>*)&thing, &Thing<T>::const_volatile_member_func1));
Verifier<T>::verify1(callback(&thing, &bound_func1<T>));
Verifier<T>::verify1(callback((const Thing<T>*)&thing, &const_func1<T>));
Verifier<T>::verify1(callback((volatile Thing<T>*)&thing, &volatile_func1<T>));
Verifier<T>::verify1(callback((const volatile Thing<T>*)&thing, &const_volatile_func1<T>));
Callback<T(T)> callback(static_func1); Callback<T(T)> cb(static_func1);
Verifier<T>::verify1(callback); Verifier<T>::verify1(cb);
callback.attach(&thing, &bound_func1<T>); cb = static_func1;
Verifier<T>::verify1(&callback, &Callback<T(T)>::call); Verifier<T>::verify1(cb);
Verifier<T>::verify1((void*)&callback, &Callback<T(T)>::thunk); cb.attach(&thing, &bound_func1<T>);
Verifier<T>::verify1(&cb, &Callback<T(T)>::call);
Verifier<T>::verify1((void*)&cb, &Callback<T(T)>::thunk);
} }
template <typename T> template <typename T>
@ -261,20 +249,14 @@ void test_dispatch2() {
Verifier<T>::verify2((volatile Thing<T>*)&thing, &volatile_func2<T>); Verifier<T>::verify2((volatile Thing<T>*)&thing, &volatile_func2<T>);
Verifier<T>::verify2((const volatile Thing<T>*)&thing, &const_volatile_func2<T>); Verifier<T>::verify2((const volatile Thing<T>*)&thing, &const_volatile_func2<T>);
Verifier<T>::verify2(callback(static_func2<T>)); Verifier<T>::verify2(callback(static_func2<T>));
Verifier<T>::verify2(callback(&thing, &Thing<T>::member_func2));
Verifier<T>::verify2(callback((const Thing<T>*)&thing, &Thing<T>::const_member_func2));
Verifier<T>::verify2(callback((volatile Thing<T>*)&thing, &Thing<T>::volatile_member_func2));
Verifier<T>::verify2(callback((const volatile Thing<T>*)&thing, &Thing<T>::const_volatile_member_func2));
Verifier<T>::verify2(callback(&thing, &bound_func2<T>));
Verifier<T>::verify2(callback((const Thing<T>*)&thing, &const_func2<T>));
Verifier<T>::verify2(callback((volatile Thing<T>*)&thing, &volatile_func2<T>));
Verifier<T>::verify2(callback((const volatile Thing<T>*)&thing, &const_volatile_func2<T>));
Callback<T(T, T)> callback(static_func2); Callback<T(T, T)> cb(static_func2);
Verifier<T>::verify2(callback); Verifier<T>::verify2(cb);
callback.attach(&thing, &bound_func2<T>); cb = static_func2;
Verifier<T>::verify2(&callback, &Callback<T(T, T)>::call); Verifier<T>::verify2(cb);
Verifier<T>::verify2((void*)&callback, &Callback<T(T, T)>::thunk); cb.attach(&thing, &bound_func2<T>);
Verifier<T>::verify2(&cb, &Callback<T(T, T)>::call);
Verifier<T>::verify2((void*)&cb, &Callback<T(T, T)>::thunk);
} }
template <typename T> template <typename T>
@ -290,20 +272,14 @@ void test_dispatch3() {
Verifier<T>::verify3((volatile Thing<T>*)&thing, &volatile_func3<T>); Verifier<T>::verify3((volatile Thing<T>*)&thing, &volatile_func3<T>);
Verifier<T>::verify3((const volatile Thing<T>*)&thing, &const_volatile_func3<T>); Verifier<T>::verify3((const volatile Thing<T>*)&thing, &const_volatile_func3<T>);
Verifier<T>::verify3(callback(static_func3<T>)); Verifier<T>::verify3(callback(static_func3<T>));
Verifier<T>::verify3(callback(&thing, &Thing<T>::member_func3));
Verifier<T>::verify3(callback((const Thing<T>*)&thing, &Thing<T>::const_member_func3));
Verifier<T>::verify3(callback((volatile Thing<T>*)&thing, &Thing<T>::volatile_member_func3));
Verifier<T>::verify3(callback((const volatile Thing<T>*)&thing, &Thing<T>::const_volatile_member_func3));
Verifier<T>::verify3(callback(&thing, &bound_func3<T>));
Verifier<T>::verify3(callback((const Thing<T>*)&thing, &const_func3<T>));
Verifier<T>::verify3(callback((volatile Thing<T>*)&thing, &volatile_func3<T>));
Verifier<T>::verify3(callback((const volatile Thing<T>*)&thing, &const_volatile_func3<T>));
Callback<T(T, T, T)> callback(static_func3); Callback<T(T, T, T)> cb(static_func3);
Verifier<T>::verify3(callback); Verifier<T>::verify3(cb);
callback.attach(&thing, &bound_func3<T>); cb = static_func3;
Verifier<T>::verify3(&callback, &Callback<T(T, T, T)>::call); Verifier<T>::verify3(cb);
Verifier<T>::verify3((void*)&callback, &Callback<T(T, T, T)>::thunk); cb.attach(&thing, &bound_func3<T>);
Verifier<T>::verify3(&cb, &Callback<T(T, T, T)>::call);
Verifier<T>::verify3((void*)&cb, &Callback<T(T, T, T)>::thunk);
} }
template <typename T> template <typename T>
@ -319,20 +295,14 @@ void test_dispatch4() {
Verifier<T>::verify4((volatile Thing<T>*)&thing, &volatile_func4<T>); Verifier<T>::verify4((volatile Thing<T>*)&thing, &volatile_func4<T>);
Verifier<T>::verify4((const volatile Thing<T>*)&thing, &const_volatile_func4<T>); Verifier<T>::verify4((const volatile Thing<T>*)&thing, &const_volatile_func4<T>);
Verifier<T>::verify4(callback(static_func4<T>)); Verifier<T>::verify4(callback(static_func4<T>));
Verifier<T>::verify4(callback(&thing, &Thing<T>::member_func4));
Verifier<T>::verify4(callback((const Thing<T>*)&thing, &Thing<T>::const_member_func4));
Verifier<T>::verify4(callback((volatile Thing<T>*)&thing, &Thing<T>::volatile_member_func4));
Verifier<T>::verify4(callback((const volatile Thing<T>*)&thing, &Thing<T>::const_volatile_member_func4));
Verifier<T>::verify4(callback(&thing, &bound_func4<T>));
Verifier<T>::verify4(callback((const Thing<T>*)&thing, &const_func4<T>));
Verifier<T>::verify4(callback((volatile Thing<T>*)&thing, &volatile_func4<T>));
Verifier<T>::verify4(callback((const volatile Thing<T>*)&thing, &const_volatile_func4<T>));
Callback<T(T, T, T, T)> callback(static_func4); Callback<T(T, T, T, T)> cb(static_func4);
Verifier<T>::verify4(callback); Verifier<T>::verify4(cb);
callback.attach(&thing, &bound_func4<T>); cb = static_func4;
Verifier<T>::verify4(&callback, &Callback<T(T, T, T, T)>::call); Verifier<T>::verify4(cb);
Verifier<T>::verify4((void*)&callback, &Callback<T(T, T, T, T)>::thunk); cb.attach(&thing, &bound_func4<T>);
Verifier<T>::verify4(&cb, &Callback<T(T, T, T, T)>::call);
Verifier<T>::verify4((void*)&cb, &Callback<T(T, T, T, T)>::thunk);
} }
template <typename T> template <typename T>
@ -348,20 +318,14 @@ void test_dispatch5() {
Verifier<T>::verify5((volatile Thing<T>*)&thing, &volatile_func5<T>); Verifier<T>::verify5((volatile Thing<T>*)&thing, &volatile_func5<T>);
Verifier<T>::verify5((const volatile Thing<T>*)&thing, &const_volatile_func5<T>); Verifier<T>::verify5((const volatile Thing<T>*)&thing, &const_volatile_func5<T>);
Verifier<T>::verify5(callback(static_func5<T>)); Verifier<T>::verify5(callback(static_func5<T>));
Verifier<T>::verify5(callback(&thing, &Thing<T>::member_func5));
Verifier<T>::verify5(callback((const Thing<T>*)&thing, &Thing<T>::const_member_func5));
Verifier<T>::verify5(callback((volatile Thing<T>*)&thing, &Thing<T>::volatile_member_func5));
Verifier<T>::verify5(callback((const volatile Thing<T>*)&thing, &Thing<T>::const_volatile_member_func5));
Verifier<T>::verify5(callback(&thing, &bound_func5<T>));
Verifier<T>::verify5(callback((const Thing<T>*)&thing, &const_func5<T>));
Verifier<T>::verify5(callback((volatile Thing<T>*)&thing, &volatile_func5<T>));
Verifier<T>::verify5(callback((const volatile Thing<T>*)&thing, &const_volatile_func5<T>));
Callback<T(T, T, T, T, T)> callback(static_func5); Callback<T(T, T, T, T, T)> cb(static_func5);
Verifier<T>::verify5(callback); Verifier<T>::verify5(cb);
callback.attach(&thing, &bound_func5<T>); cb = static_func5;
Verifier<T>::verify5(&callback, &Callback<T(T, T, T, T, T)>::call); Verifier<T>::verify5(cb);
Verifier<T>::verify5((void*)&callback, &Callback<T(T, T, T, T, T)>::thunk); cb.attach(&thing, &bound_func5<T>);
Verifier<T>::verify5(&cb, &Callback<T(T, T, T, T, T)>::call);
Verifier<T>::verify5((void*)&cb, &Callback<T(T, T, T, T, T)>::thunk);
} }
template <typename T> template <typename T>

File diff suppressed because it is too large Load Diff

View File

@ -43,6 +43,18 @@ public:
R (*get_function())(A1) { R (*get_function())(A1) {
return *reinterpret_cast<R (**)(A1)>(this); return *reinterpret_cast<R (**)(A1)>(this);
} }
R call(A1 a1) const {
if (!Callback<R(A1)>::operator bool()) {
return (R)0;
}
return Callback<R(A1)>::call(a1);
}
R operator()(A1 a1) const {
return Callback<R(A1)>::call(a1);
}
}; };
template <typename R> template <typename R>
@ -62,6 +74,18 @@ public:
R (*get_function())() { R (*get_function())() {
return *reinterpret_cast<R (**)()>(this); return *reinterpret_cast<R (**)()>(this);
} }
R call() const {
if (!Callback<R()>::operator bool()) {
return (R)0;
}
return Callback<R()>::call();
}
R operator()() const {
return Callback<R()>::call();
}
}; };
typedef FunctionPointerArg1<void, void> FunctionPointer; typedef FunctionPointerArg1<void, void> FunctionPointer;

View File

@ -21,8 +21,15 @@
namespace mbed { namespace mbed {
static void donothing() {}
CAN::CAN(PinName rd, PinName td) : _can(), _irq() { CAN::CAN(PinName rd, PinName td) : _can(), _irq() {
// No lock needed in constructor // 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_init(&_can, rd, td);
can_irq_init(&_can, (&CAN::_irq_handler), (uint32_t)this); can_irq_init(&_can, (&CAN::_irq_handler), (uint32_t)this);
} }
@ -100,6 +107,7 @@ void CAN::attach(Callback<void()> func, IrqType type) {
_irq[(CanIrqType)type].attach(func); _irq[(CanIrqType)type].attach(func);
can_irq_set(&_can, (CanIrqType)type, 1); can_irq_set(&_can, (CanIrqType)type, 1);
} else { } else {
_irq[(CanIrqType)type].attach(donothing);
can_irq_set(&_can, (CanIrqType)type, 0); can_irq_set(&_can, (CanIrqType)type, 0);
} }
unlock(); unlock();

View File

@ -19,11 +19,17 @@
namespace mbed { namespace mbed {
static void donothing() {}
InterruptIn::InterruptIn(PinName pin) : gpio(), InterruptIn::InterruptIn(PinName pin) : gpio(),
gpio_irq(), gpio_irq(),
_rise(), _rise(),
_fall() { _fall() {
// No lock needed in the constructor // 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_irq_init(&gpio_irq, pin, (&InterruptIn::_irq_handler), (uint32_t)this);
gpio_init_in(&gpio, pin); gpio_init_in(&gpio, pin);
} }
@ -50,7 +56,7 @@ void InterruptIn::rise(Callback<void()> func) {
_rise.attach(func); _rise.attach(func);
gpio_irq_set(&gpio_irq, IRQ_RISE, 1); gpio_irq_set(&gpio_irq, IRQ_RISE, 1);
} else { } else {
_rise.attach(NULL); _rise.attach(donothing);
gpio_irq_set(&gpio_irq, IRQ_RISE, 0); gpio_irq_set(&gpio_irq, IRQ_RISE, 0);
} }
core_util_critical_section_exit(); core_util_critical_section_exit();
@ -62,7 +68,7 @@ void InterruptIn::fall(Callback<void()> func) {
_fall.attach(func); _fall.attach(func);
gpio_irq_set(&gpio_irq, IRQ_FALL, 1); gpio_irq_set(&gpio_irq, IRQ_FALL, 1);
} else { } else {
_fall.attach(NULL); _fall.attach(donothing);
gpio_irq_set(&gpio_irq, IRQ_FALL, 0); gpio_irq_set(&gpio_irq, IRQ_FALL, 0);
} }
core_util_critical_section_exit(); core_util_critical_section_exit();

View File

@ -21,6 +21,8 @@
namespace mbed { namespace mbed {
static void donothing() {};
SerialBase::SerialBase(PinName tx, PinName rx) : SerialBase::SerialBase(PinName tx, PinName rx) :
#if DEVICE_SERIAL_ASYNCH #if DEVICE_SERIAL_ASYNCH
_thunk_irq(this), _tx_usage(DMA_USAGE_NEVER), _thunk_irq(this), _tx_usage(DMA_USAGE_NEVER),
@ -29,6 +31,10 @@ SerialBase::SerialBase(PinName tx, PinName rx) :
_serial(), _baud(9600) { _serial(), _baud(9600) {
// No lock needed in the constructor // 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_init(&_serial, tx, rx);
serial_irq_handler(&_serial, SerialBase::_irq_handler, (uint32_t)this); serial_irq_handler(&_serial, SerialBase::_irq_handler, (uint32_t)this);
} }
@ -69,6 +75,7 @@ void SerialBase::attach(Callback<void()> func, IrqType type) {
_irq[type].attach(func); _irq[type].attach(func);
serial_irq_set(&_serial, (SerialIrq)type, 1); serial_irq_set(&_serial, (SerialIrq)type, 1);
} else { } else {
_irq[type].attach(donothing);
serial_irq_set(&_serial, (SerialIrq)type, 0); serial_irq_set(&_serial, (SerialIrq)type, 0);
} }
core_util_critical_section_exit(); core_util_critical_section_exit();