Merge pull request #1793 from theotherjimmy/callback

mv #1783(Improve FunctionPointer class) + minor compatibility fix
pull/1804/head
Martin Kojtal 2016-05-27 17:54:25 +01:00
commit c3d9192bc5
14 changed files with 1025 additions and 281 deletions

View File

@ -22,7 +22,7 @@
#include "can_api.h"
#include "can_helper.h"
#include "FunctionPointer.h"
#include "Callback.h"
namespace mbed {
@ -206,34 +206,40 @@ public:
/** Attach a function to call whenever a CAN frame received interrupt is
* generated.
*
* @param fptr A pointer to a void function, or 0 to set as none
* @param func A pointer to a void function, or 0 to set as none
* @param event Which CAN interrupt to attach the member function to (CAN::RxIrq for message received, CAN::TxIrq for transmitted or aborted, CAN::EwIrq for error warning, CAN::DoIrq for data overrun, CAN::WuIrq for wake-up, CAN::EpIrq for error passive, CAN::AlIrq for arbitration lost, CAN::BeIrq for bus error)
*/
void attach(void (*fptr)(void), IrqType type=RxIrq);
void attach(Callback<void()> func, IrqType type=RxIrq);
/** Attach a member function to call whenever a CAN frame received interrupt
* is generated.
*
* @param tptr pointer to the object to call the member function on
* @param mptr pointer to the member function to be called
* @param obj pointer to the object to call the member function on
* @param method pointer to the member function to be called
* @param event Which CAN interrupt to attach the member function to (CAN::RxIrq for message received, TxIrq for transmitted or aborted, EwIrq for error warning, DoIrq for data overrun, WuIrq for wake-up, EpIrq for error passive, AlIrq for arbitration lost, BeIrq for bus error)
*/
template<typename T>
void attach(T* tptr, void (T::*mptr)(void), IrqType type=RxIrq) {
if((mptr != NULL) && (tptr != NULL)) {
_irq[type].attach(tptr, mptr);
can_irq_set(&_can, (CanIrqType)type, 1);
}
else {
can_irq_set(&_can, (CanIrqType)type, 0);
}
template<typename T>
void attach(T* obj, void (T::*method)(), IrqType type=RxIrq) {
attach(Callback<void()>(obj, method), type);
}
/** Attach a member function to call whenever a CAN frame received interrupt
* is generated.
*
* @param obj pointer to the object to call the member function on
* @param method pointer to the member function to be called
* @param event Which CAN interrupt to attach the member function to (CAN::RxIrq for message received, TxIrq for transmitted or aborted, EwIrq for error warning, DoIrq for data overrun, WuIrq for wake-up, EpIrq for error passive, AlIrq for arbitration lost, BeIrq for bus error)
*/
template<typename T>
void attach(T* obj, void (*method)(T*), IrqType type=RxIrq) {
attach(Callback<void()>(obj, method), type);
}
static void _irq_handler(uint32_t id, CanIrqType type);
protected:
can_t _can;
FunctionPointer _irq[9];
can_t _can;
Callback<void()> _irq[9];
};
} // namespace mbed

View File

@ -16,7 +16,7 @@
#ifndef MBED_CALLCHAIN_H
#define MBED_CALLCHAIN_H
#include "FunctionPointer.h"
#include "Callback.h"
#include <string.h>
namespace mbed {
@ -57,7 +57,7 @@ namespace mbed {
* @endcode
*/
typedef FunctionPointer* pFunctionPointer_t;
typedef Callback<void()> *pFunctionPointer_t;
class CallChain {
public:
@ -70,34 +70,34 @@ public:
/** Add a function at the end of the chain
*
* @param function A pointer to a void function
* @param func A pointer to a void function
*
* @returns
* The function object created for 'function'
* The function object created for 'func'
*/
pFunctionPointer_t add(void (*function)(void));
pFunctionPointer_t add(Callback<void()> func);
/** Add a function at the end of the chain
*
* @param tptr pointer to the object to call the member function on
* @param mptr pointer to the member function to be called
* @param obj pointer to the object to call the member function on
* @param method pointer to the member function to be called
*
* @returns
* The function object created for 'tptr' and 'mptr'
* The function object created for 'obj' and 'method'
*/
template<typename T>
pFunctionPointer_t add(T *tptr, void (T::*mptr)(void)) {
return common_add(new FunctionPointer(tptr, mptr));
template<typename T, typename M>
pFunctionPointer_t add(T *obj, M method) {
return add(Callback<void()>(obj, method));
}
/** Add a function at the beginning of the chain
*
* @param function A pointer to a void function
* @param func A pointer to a void function
*
* @returns
* The function object created for 'function'
* The function object created for 'func'
*/
pFunctionPointer_t add_front(void (*function)(void));
pFunctionPointer_t add_front(Callback<void()> func);
/** Add a function at the beginning of the chain
*
@ -107,9 +107,9 @@ public:
* @returns
* The function object created for 'tptr' and 'mptr'
*/
template<typename T>
pFunctionPointer_t add_front(T *tptr, void (T::*mptr)(void)) {
return common_add_front(new FunctionPointer(tptr, mptr));
template<typename T, typename M>
pFunctionPointer_t add_front(T *obj, M method) {
return add_front(Callback<void()>(obj, method));
}
/** Get the number of functions in the chain
@ -162,8 +162,6 @@ public:
private:
void _check_size();
pFunctionPointer_t common_add(pFunctionPointer_t pf);
pFunctionPointer_t common_add_front(pFunctionPointer_t pf);
pFunctionPointer_t* _chain;
int _size;

881
hal/api/Callback.h Normal file
View File

@ -0,0 +1,881 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2015 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MBED_CALLBACK_H
#define MBED_CALLBACK_H
#include <string.h>
#include <stdint.h>
namespace mbed {
/** Callback class based on template specialization
*/
template <typename F>
class Callback;
/** Templated function class
*/
template <typename R, typename A0, typename A1, typename A2, typename A3, typename A4>
class Callback<R(A0, A1, A2, A3, A4)> {
public:
/** Create a Callback with a static function
* @param func Static function to attach
*/
Callback(R (*func)(A0, A1, A2, A3, A4) = 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
*/
template<typename T>
Callback(T *obj, R (*func)(T*, A0, A1, A2, A3, A4)) {
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<typename T>
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<R(A0, A1, A2, A3, A4)> &func) {
attach(func);
}
/** Attach a static function
* @param func Static function to attach
*/
void attach(R (*func)(A0, A1, A2, A3, A4)) {
memcpy(&_func, &func, sizeof func);
_thunk = func ? &Callback::_staticthunk : 0;
}
/** Attach a static function with a bound pointer
* @param obj Pointer to object to bind to function
* @param func Static function to attach
*/
template <typename T>
void attach(T *obj, R (*func)(T*, A0, A1, A2, A3, A4)) {
_obj = static_cast<void*>(obj);
memcpy(&_func, &func, sizeof func);
_thunk = &Callback::_boundthunk<T>;
}
/** Attach a member function
* @param obj Pointer to object to invoke member function on
* @param func Member function to attach
*/
template<typename T>
void attach(T *obj, R (T::*func)(A0, A1, A2, A3, A4)) {
_obj = static_cast<void*>(obj);
memcpy(&_func, &func, sizeof func);
_thunk = &Callback::_methodthunk<T>;
}
/** Attach a Callback
* @param func The Callback to attach
*/
void attach(const Callback<R(A0, A1, A2, A3, A4)> &func) {
_obj = func._obj;
memcpy(&_func, &func._func, sizeof _func);
_thunk = func._thunk;
}
/** Call the attached function
*/
R call(A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) {
if (!_thunk) {
return (R)0;
}
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) {
return call(a0, a1, a2, a3, a4);
}
/** Test if function has been attached
*/
operator bool() const {
return _thunk;
}
/** 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<Callback<R(A0, A1, A2, A3, A4)>*>(func)
->call(a0, a1, a2, a3, a4);
}
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<R (**)(A0, A1, A2, A3, A4)>(func))
(a0, a1, a2, a3, a4);
}
template<typename T>
static R _boundthunk(void *obj, void *func, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) {
return (*reinterpret_cast<R (**)(T*, A0, A1, A2, A3, A4)>(func))
(static_cast<T*>(obj), a0, a1, a2, a3, a4);
}
template<typename T>
static R _methodthunk(void *obj, void *func, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) {
return (static_cast<T*>(obj)->*
(*reinterpret_cast<R (T::**)(A0, A1, A2, A3, A4)>(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
struct _class;
union {
void (*_staticfunc)();
void (*_boundfunc)(_class *);
void (_class::*_methodfunc)();
} _func;
void *_obj;
// Thunk registered on attach to dispatch calls
R (*_thunk)(void*, void*, A0, A1, A2, A3, A4);
};
/** Templated function class
*/
template <typename R, typename A0, typename A1, typename A2, typename A3>
class Callback<R(A0, A1, A2, A3)> {
public:
/** Create a Callback with a static function
* @param func Static function to attach
*/
Callback(R (*func)(A0, A1, A2, A3) = 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
*/
template<typename T>
Callback(T *obj, R (*func)(T*, A0, A1, A2, A3)) {
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<typename T>
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<R(A0, A1, A2, A3)> &func) {
attach(func);
}
/** Attach a static function
* @param func Static function to attach
*/
void attach(R (*func)(A0, A1, A2, A3)) {
memcpy(&_func, &func, sizeof func);
_thunk = func ? &Callback::_staticthunk : 0;
}
/** Attach a static function with a bound pointer
* @param obj Pointer to object to bind to function
* @param func Static function to attach
*/
template <typename T>
void attach(T *obj, R (*func)(T*, A0, A1, A2, A3)) {
_obj = static_cast<void*>(obj);
memcpy(&_func, &func, sizeof func);
_thunk = &Callback::_boundthunk<T>;
}
/** Attach a member function
* @param obj Pointer to object to invoke member function on
* @param func Member function to attach
*/
template<typename T>
void attach(T *obj, R (T::*func)(A0, A1, A2, A3)) {
_obj = static_cast<void*>(obj);
memcpy(&_func, &func, sizeof func);
_thunk = &Callback::_methodthunk<T>;
}
/** Attach a Callback
* @param func The Callback to attach
*/
void attach(const Callback<R(A0, A1, A2, A3)> &func) {
_obj = func._obj;
memcpy(&_func, &func._func, sizeof _func);
_thunk = func._thunk;
}
/** Call the attached function
*/
R call(A0 a0, A1 a1, A2 a2, A3 a3) {
if (!_thunk) {
return (R)0;
}
return _thunk(_obj, &_func, a0, a1, a2, a3);
}
/** Call the attached function
*/
R operator()(A0 a0, A1 a1, A2 a2, A3 a3) {
return call(a0, a1, a2, a3);
}
/** Test if function has been attached
*/
operator bool() const {
return _thunk;
}
/** 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<Callback<R(A0, A1, A2, A3)>*>(func)
->call(a0, a1, a2, a3);
}
private:
// Internal thunks for various function types
static R _staticthunk(void*, void *func, A0 a0, A1 a1, A2 a2, A3 a3) {
return (*reinterpret_cast<R (**)(A0, A1, A2, A3)>(func))
(a0, a1, a2, a3);
}
template<typename T>
static R _boundthunk(void *obj, void *func, A0 a0, A1 a1, A2 a2, A3 a3) {
return (*reinterpret_cast<R (**)(T*, A0, A1, A2, A3)>(func))
(static_cast<T*>(obj), a0, a1, a2, a3);
}
template<typename T>
static R _methodthunk(void *obj, void *func, A0 a0, A1 a1, A2 a2, A3 a3) {
return (static_cast<T*>(obj)->*
(*reinterpret_cast<R (T::**)(A0, A1, A2, A3)>(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
struct _class;
union {
void (*_staticfunc)();
void (*_boundfunc)(_class *);
void (_class::*_methodfunc)();
} _func;
void *_obj;
// Thunk registered on attach to dispatch calls
R (*_thunk)(void*, void*, A0, A1, A2, A3);
};
/** Templated function class
*/
template <typename R, typename A0, typename A1, typename A2>
class Callback<R(A0, A1, A2)> {
public:
/** Create a Callback with a static function
* @param func Static function to attach
*/
Callback(R (*func)(A0, A1, A2) = 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
*/
template<typename T>
Callback(T *obj, R (*func)(T*, A0, A1, A2)) {
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<typename T>
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<R(A0, A1, A2)> &func) {
attach(func);
}
/** Attach a static function
* @param func Static function to attach
*/
void attach(R (*func)(A0, A1, A2)) {
memcpy(&_func, &func, sizeof func);
_thunk = func ? &Callback::_staticthunk : 0;
}
/** Attach a static function with a bound pointer
* @param obj Pointer to object to bind to function
* @param func Static function to attach
*/
template <typename T>
void attach(T *obj, R (*func)(T*, A0, A1, A2)) {
_obj = static_cast<void*>(obj);
memcpy(&_func, &func, sizeof func);
_thunk = &Callback::_boundthunk<T>;
}
/** Attach a member function
* @param obj Pointer to object to invoke member function on
* @param func Member function to attach
*/
template<typename T>
void attach(T *obj, R (T::*func)(A0, A1, A2)) {
_obj = static_cast<void*>(obj);
memcpy(&_func, &func, sizeof func);
_thunk = &Callback::_methodthunk<T>;
}
/** Attach a Callback
* @param func The Callback to attach
*/
void attach(const Callback<R(A0, A1, A2)> &func) {
_obj = func._obj;
memcpy(&_func, &func._func, sizeof _func);
_thunk = func._thunk;
}
/** Call the attached function
*/
R call(A0 a0, A1 a1, A2 a2) {
if (!_thunk) {
return (R)0;
}
return _thunk(_obj, &_func, a0, a1, a2);
}
/** Call the attached function
*/
R operator()(A0 a0, A1 a1, A2 a2) {
return call(a0, a1, a2);
}
/** Test if function has been attached
*/
operator bool() const {
return _thunk;
}
/** 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<Callback<R(A0, A1, A2)>*>(func)
->call(a0, a1, a2);
}
private:
// Internal thunks for various function types
static R _staticthunk(void*, void *func, A0 a0, A1 a1, A2 a2) {
return (*reinterpret_cast<R (**)(A0, A1, A2)>(func))
(a0, a1, a2);
}
template<typename T>
static R _boundthunk(void *obj, void *func, A0 a0, A1 a1, A2 a2) {
return (*reinterpret_cast<R (**)(T*, A0, A1, A2)>(func))
(static_cast<T*>(obj), a0, a1, a2);
}
template<typename T>
static R _methodthunk(void *obj, void *func, A0 a0, A1 a1, A2 a2) {
return (static_cast<T*>(obj)->*
(*reinterpret_cast<R (T::**)(A0, A1, A2)>(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
struct _class;
union {
void (*_staticfunc)();
void (*_boundfunc)(_class *);
void (_class::*_methodfunc)();
} _func;
void *_obj;
// Thunk registered on attach to dispatch calls
R (*_thunk)(void*, void*, A0, A1, A2);
};
/** Templated function class
*/
template <typename R, typename A0, typename A1>
class Callback<R(A0, A1)> {
public:
/** Create a Callback with a static function
* @param func Static function to attach
*/
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
*/
template<typename T>
Callback(T *obj, R (*func)(T*, A0, A1)) {
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<typename T>
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<R(A0, A1)> &func) {
attach(func);
}
/** Attach a static function
* @param func Static function to attach
*/
void attach(R (*func)(A0, A1)) {
memcpy(&_func, &func, sizeof func);
_thunk = func ? &Callback::_staticthunk : 0;
}
/** Attach a static function with a bound pointer
* @param obj Pointer to object to bind to function
* @param func Static function to attach
*/
template <typename T>
void attach(T *obj, R (*func)(T*, A0, A1)) {
_obj = static_cast<void*>(obj);
memcpy(&_func, &func, sizeof func);
_thunk = &Callback::_boundthunk<T>;
}
/** Attach a member function
* @param obj Pointer to object to invoke member function on
* @param func Member function to attach
*/
template<typename T>
void attach(T *obj, R (T::*func)(A0, A1)) {
_obj = static_cast<void*>(obj);
memcpy(&_func, &func, sizeof func);
_thunk = &Callback::_methodthunk<T>;
}
/** Attach a Callback
* @param func The Callback to attach
*/
void attach(const Callback<R(A0, A1)> &func) {
_obj = func._obj;
memcpy(&_func, &func._func, sizeof _func);
_thunk = func._thunk;
}
/** Call the attached function
*/
R call(A0 a0, A1 a1) {
if (!_thunk) {
return (R)0;
}
return _thunk(_obj, &_func, a0, a1);
}
/** Call the attached function
*/
R operator()(A0 a0, A1 a1) {
return call(a0, a1);
}
/** Test if function has been attached
*/
operator bool() const {
return _thunk;
}
/** 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<Callback<R(A0, A1)>*>(func)
->call(a0, a1);
}
private:
// Internal thunks for various function types
static R _staticthunk(void*, void *func, A0 a0, A1 a1) {
return (*reinterpret_cast<R (**)(A0, A1)>(func))
(a0, a1);
}
template<typename T>
static R _boundthunk(void *obj, void *func, A0 a0, A1 a1) {
return (*reinterpret_cast<R (**)(T*, A0, A1)>(func))
(static_cast<T*>(obj), a0, a1);
}
template<typename T>
static R _methodthunk(void *obj, void *func, A0 a0, A1 a1) {
return (static_cast<T*>(obj)->*
(*reinterpret_cast<R (T::**)(A0, A1)>(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
struct _class;
union {
void (*_staticfunc)();
void (*_boundfunc)(_class *);
void (_class::*_methodfunc)();
} _func;
void *_obj;
// Thunk registered on attach to dispatch calls
R (*_thunk)(void*, void*, A0, A1);
};
/** Templated function class
*/
template <typename R, typename A0>
class Callback<R(A0)> {
public:
/** Create a Callback with a static function
* @param func Static function to attach
*/
Callback(R (*func)(A0) = 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
*/
template<typename T>
Callback(T *obj, R (*func)(T*, A0)) {
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<typename T>
Callback(T *obj, R (T::*func)(A0)) {
attach(obj, func);
}
/** Create a Callback with another Callback
* @param func Callback to attach
*/
Callback(const Callback<R(A0)> &func) {
attach(func);
}
/** Attach a static function
* @param func Static function to attach
*/
void attach(R (*func)(A0)) {
memcpy(&_func, &func, sizeof func);
_thunk = func ? &Callback::_staticthunk : 0;
}
/** Attach a static function with a bound pointer
* @param obj Pointer to object to bind to function
* @param func Static function to attach
*/
template <typename T>
void attach(T *obj, R (*func)(T*, A0)) {
_obj = static_cast<void*>(obj);
memcpy(&_func, &func, sizeof func);
_thunk = &Callback::_boundthunk<T>;
}
/** Attach a member function
* @param obj Pointer to object to invoke member function on
* @param func Member function to attach
*/
template<typename T>
void attach(T *obj, R (T::*func)(A0)) {
_obj = static_cast<void*>(obj);
memcpy(&_func, &func, sizeof func);
_thunk = &Callback::_methodthunk<T>;
}
/** Attach a Callback
* @param func The Callback to attach
*/
void attach(const Callback<R(A0)> &func) {
_obj = func._obj;
memcpy(&_func, &func._func, sizeof _func);
_thunk = func._thunk;
}
/** Call the attached function
*/
R call(A0 a0) {
if (!_thunk) {
return (R)0;
}
return _thunk(_obj, &_func, a0);
}
/** Call the attached function
*/
R operator()(A0 a0) {
return call(a0);
}
/** Test if function has been attached
*/
operator bool() const {
return _thunk;
}
/** 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<Callback<R(A0)>*>(func)
->call(a0);
}
private:
// Internal thunks for various function types
static R _staticthunk(void*, void *func, A0 a0) {
return (*reinterpret_cast<R (**)(A0)>(func))
(a0);
}
template<typename T>
static R _boundthunk(void *obj, void *func, A0 a0) {
return (*reinterpret_cast<R (**)(T*, A0)>(func))
(static_cast<T*>(obj), a0);
}
template<typename T>
static R _methodthunk(void *obj, void *func, A0 a0) {
return (static_cast<T*>(obj)->*
(*reinterpret_cast<R (T::**)(A0)>(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
struct _class;
union {
void (*_staticfunc)();
void (*_boundfunc)(_class *);
void (_class::*_methodfunc)();
} _func;
void *_obj;
// Thunk registered on attach to dispatch calls
R (*_thunk)(void*, void*, A0);
};
/** Templated function class
*/
template <typename R>
class Callback<R()> {
public:
/** Create a Callback with a static function
* @param func Static function to attach
*/
Callback(R (*func)() = 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
*/
template<typename T>
Callback(T *obj, R (*func)(T*)) {
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<typename T>
Callback(T *obj, R (T::*func)()) {
attach(obj, func);
}
/** Create a Callback with another Callback
* @param func Callback to attach
*/
Callback(const Callback<R()> &func) {
attach(func);
}
/** Attach a static function
* @param func Static function to attach
*/
void attach(R (*func)()) {
memcpy(&_func, &func, sizeof func);
_thunk = func ? &Callback::_staticthunk : 0;
}
/** Attach a static function with a bound pointer
* @param obj Pointer to object to bind to function
* @param func Static function to attach
*/
template <typename T>
void attach(T *obj, R (*func)(T*)) {
_obj = static_cast<void*>(obj);
memcpy(&_func, &func, sizeof func);
_thunk = &Callback::_boundthunk<T>;
}
/** Attach a member function
* @param obj Pointer to object to invoke member function on
* @param func Member function to attach
*/
template<typename T>
void attach(T *obj, R (T::*func)()) {
_obj = static_cast<void*>(obj);
memcpy(&_func, &func, sizeof func);
_thunk = &Callback::_methodthunk<T>;
}
/** Attach a Callback
* @param func The Callback to attach
*/
void attach(const Callback<R()> &func) {
_obj = func._obj;
memcpy(&_func, &func._func, sizeof _func);
_thunk = func._thunk;
}
/** Call the attached function
*/
R call() {
if (!_thunk) {
return (R)0;
}
return _thunk(_obj, &_func);
}
/** Call the attached function
*/
R operator()() {
return call();
}
/** Test if function has been attached
*/
operator bool() const {
return _thunk;
}
/** 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<Callback<R()>*>(func)
->call();
}
private:
// Internal thunks for various function types
static R _staticthunk(void*, void *func) {
return (*reinterpret_cast<R (**)()>(func))
();
}
template<typename T>
static R _boundthunk(void *obj, void *func) {
return (*reinterpret_cast<R (**)(T*)>(func))
(static_cast<T*>(obj));
}
template<typename T>
static R _methodthunk(void *obj, void *func) {
return (static_cast<T*>(obj)->*
(*reinterpret_cast<R (T::**)()>(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
struct _class;
union {
void (*_staticfunc)();
void (*_boundfunc)(_class *);
void (_class::*_methodfunc)();
} _func;
void *_obj;
// Thunk registered on attach to dispatch calls
R (*_thunk)(void*, void*);
};
typedef Callback<void(int)> event_callback_t;
} // namespace mbed
#endif

View File

@ -16,186 +16,47 @@
#ifndef MBED_FUNCTIONPOINTER_H
#define MBED_FUNCTIONPOINTER_H
#include "Callback.h"
#include <string.h>
#include <stdint.h>
namespace mbed {
/* If we had variaditic templates, this wouldn't be a problem, but until C++11 is enabled, we are stuck with multiple classes... */
/** A class for storing and calling a pointer to a static or member function
*/
// Declarations for backwards compatibility
// To be foward compatible, code should adopt the Callback class
template <typename R, typename A1>
class FunctionPointerArg1{
class FunctionPointerArg1 : public Callback<R(A1)> {
public:
/** Create a FunctionPointer, attaching a static function
*
* @param function The static function to attach (default is none)
*/
FunctionPointerArg1(R (*function)(A1) = 0) {
attach(function);
}
FunctionPointerArg1(R (*function)(A1) = 0)
: Callback<R(A1)>(function) {}
/** Create a FunctionPointer, attaching a member function
*
* @param object The object pointer to invoke the member function on (i.e. the this pointer)
* @param function The address of the member function to attach
*/
template<typename T>
FunctionPointerArg1(T *object, R (T::*member)(A1)) {
attach(object, member);
}
FunctionPointerArg1(T *object, R (T::*member)(A1))
: Callback<R(A1)>(object, member) {}
/** Attach a static function
*
* @param function The static function to attach (default is none)
*/
void attach(R (*function)(A1)) {
_p.function = function;
_membercaller = 0;
R (*get_function())(A1) {
return *reinterpret_cast<R (**)(A1)>(this);
}
/** Attach a member function
*
* @param object The object pointer to invoke the member function on (i.e. the this pointer)
* @param function The address of the member function to attach
*/
template<typename T>
void attach(T *object, R (T::*member)(A1)) {
_p.object = static_cast<void*>(object);
*reinterpret_cast<R (T::**)(A1)>(_member) = member;
_membercaller = &FunctionPointerArg1::membercaller<T>;
}
/** Call the attached static or member function
*/
R call(A1 a) {
if (_membercaller == 0 && _p.function) {
return _p.function(a);
} else if (_membercaller && _p.object) {
return _membercaller(_p.object, _member, a);
}
return (R)0;
}
/** Get registered static function
*/
R(*get_function(A1))() {
return _membercaller ? (R(*)(A1))0 : (R(*)(A1))_p.function;
}
#ifdef MBED_OPERATORS
R operator ()(A1 a) {
return call(a);
}
operator bool(void) const {
return (_membercaller != NULL ? _p.object : (void*)_p.function) != NULL;
}
#endif
private:
template<typename T>
static R membercaller(void *object, uintptr_t *member, A1 a) {
T* o = static_cast<T*>(object);
R (T::**m)(A1) = reinterpret_cast<R (T::**)(A1)>(member);
return (o->**m)(a);
}
union {
R (*function)(A1); // static function pointer
void *object; // object this pointer
} _p;
uintptr_t _member[4]; // aligned raw member function pointer storage - converted back by registered _membercaller
R (*_membercaller)(void*, uintptr_t*, A1); // registered membercaller function to convert back and call _m.member on _object
};
/** A class for storing and calling a pointer to a static or member function (R ()(void))
*/
template <typename R>
class FunctionPointerArg1<R, void>{
class FunctionPointerArg1<R, void> : public Callback<R()> {
public:
/** Create a FunctionPointer, attaching a static function
*
* @param function The static function to attach (default is none)
*/
FunctionPointerArg1(R (*function)(void) = 0) {
attach(function);
}
FunctionPointerArg1(R (*function)() = 0)
: Callback<R()>(function) {}
/** Create a FunctionPointer, attaching a member function
*
* @param object The object pointer to invoke the member function on (i.e. the this pointer)
* @param function The address of the void member function to attach
*/
template<typename T>
FunctionPointerArg1(T *object, R (T::*member)(void)) {
attach(object, member);
}
FunctionPointerArg1(T *object, R (T::*member)())
: Callback<R()>(object, member) {}
/** Attach a static function
*
* @param function The void static function to attach (default is none)
*/
void attach(R (*function)(void)) {
_p.function = function;
_membercaller = 0;
R (*get_function())() {
return *reinterpret_cast<R (**)()>(this);
}
/** Attach a member function
*
* @param object The object pointer to invoke the member function on (i.e. the this pointer)
* @param function The address of the void member function to attach
*/
template<typename T>
void attach(T *object, R (T::*member)(void)) {
_p.object = static_cast<void*>(object);
*reinterpret_cast<R (T::**)(void)>(_member) = member;
_membercaller = &FunctionPointerArg1::membercaller<T>;
}
/** Call the attached static or member function
*/
R call(){
if (_membercaller == 0 && _p.function) {
return _p.function();
} else if (_membercaller && _p.object) {
return _membercaller(_p.object, _member);
}
return (R)0;
}
/** Get registered static function
*/
R(*get_function())() {
return _membercaller ? (R(*)())0 : (R(*)())_p.function;
}
#ifdef MBED_OPERATORS
R operator ()(void) {
return call();
}
operator bool(void) const {
return (_membercaller != NULL ? _p.object : (void*)_p.function) != NULL;
}
#endif
private:
template<typename T>
static R membercaller(void *object, uintptr_t *member) {
T* o = static_cast<T*>(object);
R (T::**m)(void) = reinterpret_cast<R (T::**)(void)>(member);
return (o->**m)();
}
union {
R (*function)(void); // static function pointer
void *object; // object this pointer
} _p;
uintptr_t _member[4]; // aligned raw member function pointer storage - converted back by registered _membercaller
R (*_membercaller)(void*, uintptr_t*); // registered membercaller function to convert back and call _m.member on _object
};
typedef FunctionPointerArg1<void, void> FunctionPointer;
typedef FunctionPointerArg1<void, int> event_callback_t;
} // namespace mbed

View File

@ -22,7 +22,7 @@
#include "gpio_api.h"
#include "gpio_irq_api.h"
#include "FunctionPointer.h"
#include "Callback.h"
namespace mbed {
@ -70,36 +70,34 @@ public:
/** Attach a function to call when a rising edge occurs on the input
*
* @param fptr A pointer to a void function, or 0 to set as none
* @param func A pointer to a void function, or 0 to set as none
*/
void rise(void (*fptr)(void));
void rise(Callback<void()> func);
/** Attach a member function to call when a rising edge occurs on the input
*
* @param tptr pointer to the object to call the member function on
* @param mptr pointer to the member function to be called
* @param obj pointer to the object to call the member function on
* @param method pointer to the member function to be called
*/
template<typename T>
void rise(T* tptr, void (T::*mptr)(void)) {
_rise.attach(tptr, mptr);
gpio_irq_set(&gpio_irq, IRQ_RISE, 1);
template<typename T, typename M>
void rise(T *obj, M method) {
rise(Callback<void()>(obj, method));
}
/** Attach a function to call when a falling edge occurs on the input
*
* @param fptr A pointer to a void function, or 0 to set as none
* @param func A pointer to a void function, or 0 to set as none
*/
void fall(void (*fptr)(void));
void fall(Callback<void()> func);
/** Attach a member function to call when a falling edge occurs on the input
*
* @param tptr pointer to the object to call the member function on
* @param mptr pointer to the member function to be called
* @param obj pointer to the object to call the member function on
* @param method pointer to the member function to be called
*/
template<typename T>
void fall(T* tptr, void (T::*mptr)(void)) {
_fall.attach(tptr, mptr);
gpio_irq_set(&gpio_irq, IRQ_FALL, 1);
template<typename T, typename M>
void fall(T *obj, M method) {
fall(Callback<void()>(obj, method));
}
/** Set the input pin mode
@ -124,8 +122,8 @@ protected:
gpio_t gpio;
gpio_irq_t gpio_irq;
FunctionPointer _rise;
FunctionPointer _fall;
Callback<void()> _rise;
Callback<void()> _fall;
};
} // namespace mbed

View File

@ -21,7 +21,7 @@
#if DEVICE_SERIAL
#include "Stream.h"
#include "FunctionPointer.h"
#include "Callback.h"
#include "serial_api.h"
#if DEVICE_SERIAL_ASYNCH
@ -89,25 +89,31 @@ public:
/** Attach a function to call whenever a serial interrupt is generated
*
* @param fptr A pointer to a void function, or 0 to set as none
* @param func A pointer to a void function, or 0 to set as none
* @param type Which serial interrupt to attach the member function to (Seriall::RxIrq for receive, TxIrq for transmit buffer empty)
*/
void attach(void (*fptr)(void), IrqType type=RxIrq);
void attach(Callback<void()> func, IrqType type=RxIrq);
/** Attach a member function to call whenever a serial interrupt is generated
*
* @param tptr pointer to the object to call the member function on
* @param mptr pointer to the member function to be called
* @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)
*/
template<typename T>
void attach(T* tptr, void (T::*mptr)(void), IrqType type=RxIrq) {
if((mptr != NULL) && (tptr != NULL)) {
_irq[type].attach(tptr, mptr);
serial_irq_set(&_serial, (SerialIrq)type, 1);
} else {
serial_irq_set(&_serial, (SerialIrq)type, 0);
}
void attach(T *obj, void (T::*method)(), IrqType type=RxIrq) {
attach(Callback<void()>(obj, method), type);
}
/** Attach a member function to call whenever a serial interrupt is generated
*
* @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)
*/
template<typename T>
void attach(T *obj, void (*method)(T*), IrqType type=RxIrq) {
attach(Callback<void()>(obj, method), type);
}
/** Generate a break condition on the serial line
@ -210,9 +216,9 @@ protected:
DMAUsage _rx_usage;
#endif
serial_t _serial;
FunctionPointer _irq[2];
int _baud;
serial_t _serial;
Callback<void()> _irq[2];
int _baud;
};

View File

@ -17,7 +17,7 @@
#define MBED_TICKER_H
#include "TimerEvent.h"
#include "FunctionPointer.h"
#include "Callback.h"
namespace mbed {
@ -65,22 +65,22 @@ public:
/** Attach a function to be called by the Ticker, specifiying the interval in seconds
*
* @param fptr pointer to the function to be called
* @param func pointer to the function to be called
* @param t the time between calls in seconds
*/
void attach(void (*fptr)(void), float t) {
attach_us(fptr, t * 1000000.0f);
void attach(Callback<void()> func, float t) {
attach_us(func, t * 1000000.0f);
}
/** Attach a member function to be called by the Ticker, specifiying the interval in seconds
*
* @param tptr pointer to the object to call the member function on
* @param mptr pointer to the member function to be called
* @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
*/
template<typename T>
void attach(T* tptr, void (T::*mptr)(void), float t) {
attach_us(tptr, mptr, t * 1000000.0f);
template<typename T, typename M>
void attach(T *obj, M method, float t) {
attach(Callback<void()>(obj, method), t);
}
/** Attach a function to be called by the Ticker, specifiying the interval in micro-seconds
@ -88,8 +88,8 @@ public:
* @param fptr pointer to the function to be called
* @param t the time between calls in micro-seconds
*/
void attach_us(void (*fptr)(void), timestamp_t t) {
_function.attach(fptr);
void attach_us(Callback<void()> func, timestamp_t t) {
_function.attach(func);
setup(t);
}
@ -99,10 +99,9 @@ public:
* @param mptr pointer to the member function to be called
* @param t the time between calls in micro-seconds
*/
template<typename T>
void attach_us(T* tptr, void (T::*mptr)(void), timestamp_t t) {
_function.attach(tptr, mptr);
setup(t);
template<typename T, typename M>
void attach_us(T *obj, M method, timestamp_t t) {
attach_us(Callback<void()>(obj, method), t);
}
virtual ~Ticker() {
@ -118,8 +117,8 @@ protected:
virtual void handler();
protected:
timestamp_t _delay; /**< Time delay (in microseconds) for re-setting the multi-shot callback. */
FunctionPointer _function; /**< Callback. */
timestamp_t _delay; /**< Time delay (in microseconds) for re-setting the multi-shot callback. */
Callback<void()> _function; /**< Callback. */
};
} // namespace mbed

View File

@ -18,6 +18,7 @@
#define MBED_LIBRARY_VERSION 121
#include "toolchain.h"
#include "platform.h"
// Useful C libraries
@ -63,6 +64,10 @@
#include "sleep_api.h"
#include "rtc_time.h"
// mbed Non-hardware components
#include "Callback.h"
#include "FunctionPointer.h"
using namespace mbed;
using namespace std;

View File

@ -32,4 +32,9 @@ typedef int FILEHANDLE;
# define PACKED __attribute__((packed))
#endif
// Backwards compatibility
#ifndef EXTERN
#define EXTERN extern
#endif
#endif

View File

@ -67,9 +67,9 @@ int CAN::filter(unsigned int id, unsigned int mask, CANFormat format, int handle
return can_filter(&_can, id, mask, format, handle);
}
void CAN::attach(void (*fptr)(void), IrqType type) {
if (fptr) {
_irq[(CanIrqType)type].attach(fptr);
void CAN::attach(Callback<void()> func, IrqType type) {
if (func) {
_irq[(CanIrqType)type].attach(func);
can_irq_set(&_can, (CanIrqType)type, 1);
} else {
can_irq_set(&_can, (CanIrqType)type, 0);

View File

@ -12,12 +12,19 @@ CallChain::~CallChain() {
delete _chain;
}
pFunctionPointer_t CallChain::add(void (*function)(void)) {
return common_add(new FunctionPointer(function));
pFunctionPointer_t CallChain::add(Callback<void()> func) {
_check_size();
_chain[_elements] = new Callback<void()>(func);
_elements ++;
return _chain[_elements];
}
pFunctionPointer_t CallChain::add_front(void (*function)(void)) {
return common_add_front(new FunctionPointer(function));
pFunctionPointer_t CallChain::add_front(Callback<void()> func) {
_check_size();
memmove(_chain + 1, _chain, _elements * sizeof(pFunctionPointer_t));
_chain[0] = new Callback<void()>(func);
_elements ++;
return _chain[0];
}
int CallChain::size() const {
@ -72,19 +79,4 @@ void CallChain::_check_size() {
_chain = new_chain;
}
pFunctionPointer_t CallChain::common_add(pFunctionPointer_t pf) {
_check_size();
_chain[_elements] = pf;
_elements ++;
return pf;
}
pFunctionPointer_t CallChain::common_add_front(pFunctionPointer_t pf) {
_check_size();
memmove(_chain + 1, _chain, _elements * sizeof(pFunctionPointer_t));
_chain[0] = pf;
_elements ++;
return pf;
}
} // namespace mbed

View File

@ -39,9 +39,9 @@ void InterruptIn::mode(PinMode pull) {
gpio_mode(&gpio, pull);
}
void InterruptIn::rise(void (*fptr)(void)) {
if (fptr) {
_rise.attach(fptr);
void InterruptIn::rise(Callback<void()> func) {
if (func) {
_rise.attach(func);
gpio_irq_set(&gpio_irq, IRQ_RISE, 1);
} else {
_rise.attach(NULL);
@ -49,9 +49,9 @@ void InterruptIn::rise(void (*fptr)(void)) {
}
}
void InterruptIn::fall(void (*fptr)(void)) {
if (fptr) {
_fall.attach(fptr);
void InterruptIn::fall(Callback<void()> func) {
if (func) {
_fall.attach(func);
gpio_irq_set(&gpio_irq, IRQ_FALL, 1);
} else {
_fall.attach(NULL);

View File

@ -66,13 +66,6 @@ bool InterruptManager::remove_handler(pFunctionPointer_t handler, IRQn_Type irq)
return false;
if (!_chains[irq_pos]->remove(handler))
return false;
// If there's a single function left in the chain, swith the interrupt vector
// to call that function directly. This way we save both time and space.
if (_chains[irq_pos]->size() == 1 && NULL != _chains[irq_pos]->get(0)->get_function()) {
NVIC_SetVector(irq, (uint32_t)_chains[irq_pos]->get(0)->get_function());
delete _chains[irq_pos];
_chains[irq_pos] = (CallChain*) NULL;
}
return true;
}

View File

@ -48,9 +48,9 @@ int SerialBase::writeable() {
return serial_writable(&_serial);
}
void SerialBase::attach(void (*fptr)(void), IrqType type) {
if (fptr) {
_irq[type].attach(fptr);
void SerialBase::attach(Callback<void()> func, IrqType type) {
if (func) {
_irq[type].attach(func);
serial_irq_set(&_serial, (SerialIrq)type, 1);
} else {
serial_irq_set(&_serial, (SerialIrq)type, 0);