Preliminary main mbed library for nexpaq development
Diff: hal/api/Callback.h
- Revision:
- 0:6c56fb4bc5f0
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hal/api/Callback.h Fri Nov 04 20:27:58 2016 +0000 @@ -0,0 +1,3531 @@ +/* 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> +#include "mbed_assert.h" + +namespace mbed { + + +/** Callback class based on template specialization + * + * @Note Synchronization level: Not protected + */ +template <typename F> +class Callback; + +/** Callback class based on template specialization + * + * @Note Synchronization level: Not protected + */ +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 + */ + 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 + */ + template<typename T> + Callback(T *obj, R (*func)(T*)) { + attach(obj, func); + } + + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ + template<typename T> + Callback(const T *obj, R (*func)(const T*)) { + attach(obj, func); + } + + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ + template<typename T> + Callback(volatile T *obj, R (*func)(volatile T*)) { + attach(obj, func); + } + + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ + template<typename T> + Callback(const volatile T *obj, R (*func)(const volatile 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 a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ + template<typename T> + Callback(const T *obj, R (T::*func)() const) { + attach(obj, func); + } + + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ + template<typename T> + Callback(volatile T *obj, R (T::*func)() volatile) { + attach(obj, func); + } + + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ + template<typename T> + Callback(const volatile T *obj, R (T::*func)() const volatile) { + attach(obj, func); + } + + /** Attach a static function + * @param func Static function to attach + */ + void attach(R (*func)()) { + struct local { + static R _thunk(void*, const void *func) { + return (*static_cast<R (*const *)()>(func))( + ); + } + }; + + memset(&_func, 0, sizeof _func); + memcpy(&_func, &func, sizeof func); + _obj = 0; + _thunk = func ? &local::_thunk : 0; + } + + /** Attach a Callback + * @param func The Callback to attach + */ + void attach(const Callback<R()> &func) { + memset(&_func, 0, sizeof _func); + memcpy(&_func, &func._func, sizeof func); + _obj = func._obj; + _thunk = func._thunk; + } + + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ + void attach(void *obj, R (*func)(void*)) { + struct local { + static R _thunk(void *obj, const void *func) { + return (*static_cast<R (*const *)(void*)>(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<R (*const *)(const void*)>(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<R (*const *)(volatile void*)>(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<R (*const *)(const volatile void*)>(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 + */ + template <typename T> + void attach(T *obj, R (*func)(T*)) { + struct local { + static R _thunk(void *obj, const void *func) { + return (*static_cast<R (*const *)(T*)>(func))( + (T*)obj); + } + }; + + memset(&_func, 0, sizeof _func); + memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; + _thunk = &local::_thunk; + } + + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ + template <typename T> + void attach(const T *obj, R (*func)(const T*)) { + struct local { + static R _thunk(void *obj, const void *func) { + return (*static_cast<R (*const *)(const T*)>(func))( + (const T*)obj); + } + }; + + memset(&_func, 0, sizeof _func); + memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; + _thunk = &local::_thunk; + } + + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ + template <typename T> + void attach(volatile T *obj, R (*func)(volatile T*)) { + struct local { + static R _thunk(void *obj, const void *func) { + return (*static_cast<R (*const *)(volatile T*)>(func))( + (volatile T*)obj); + } + }; + + memset(&_func, 0, sizeof _func); + memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; + _thunk = &local::_thunk; + } + + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ + template <typename T> + void attach(const volatile T *obj, R (*func)(const volatile T*)) { + struct local { + static R _thunk(void *obj, const void *func) { + return (*static_cast<R (*const *)(const volatile T*)>(func))( + (const volatile T*)obj); + } + }; + + memset(&_func, 0, sizeof _func); + memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; + _thunk = &local::_thunk; + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ + template<typename T> + void attach(T *obj, R (T::*func)()) { + struct local { + static R _thunk(void *obj, const void *func) { + return (((T*)obj)->* + (*static_cast<R (T::*const *)()>(func)))( + ); + } + }; + + memset(&_func, 0, sizeof _func); + memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; + _thunk = &local::_thunk; + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ + template<typename T> + void attach(const T *obj, R (T::*func)() const) { + struct local { + static R _thunk(void *obj, const void *func) { + return (((const T*)obj)->* + (*static_cast<R (T::*const *)() const>(func)))( + ); + } + }; + + memset(&_func, 0, sizeof _func); + memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; + _thunk = &local::_thunk; + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ + template<typename T> + void attach(volatile T *obj, R (T::*func)() volatile) { + struct local { + static R _thunk(void *obj, const void *func) { + return (((volatile T*)obj)->* + (*static_cast<R (T::*const *)() volatile>(func)))( + ); + } + }; + + memset(&_func, 0, sizeof _func); + memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; + _thunk = &local::_thunk; + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ + template<typename T> + void attach(const volatile T *obj, R (T::*func)() const volatile) { + struct local { + static R _thunk(void *obj, const void *func) { + return (((const volatile T*)obj)->* + (*static_cast<R (T::*const *)() const volatile>(func)))( + ); + } + }; + + memset(&_func, 0, sizeof _func); + memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; + _thunk = &local::_thunk; + } + + /** Call the attached function + */ + R call() const { + MBED_ASSERT(_thunk); + return _thunk(_obj, &_func); + } + + /** Call the attached function + */ + R operator()() const { + return call(); + } + + /** Test if function has been attached + */ + operator bool() const { + return _thunk; + } + + /** Test for equality + */ + friend bool operator==(const Callback &l, const Callback &r) { + return memcmp(&l, &r, sizeof(Callback)) == 0; + } + + /** Test for inequality + */ + friend bool operator!=(const Callback &l, const Callback &r) { + return !(l == r); + } + + /** Static thunk for passing as C-style function + * @param func Callback to call passed as void pointer + */ + static R thunk(void *func) { + return static_cast<Callback<R()>*>(func)->call( + ); + } + +private: + // 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*, const void*); +}; + +/** Callback class based on template specialization + * + * @Note Synchronization level: Not protected + */ +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 + */ + 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 + */ + template<typename T> + Callback(T *obj, R (*func)(T*, A0)) { + attach(obj, func); + } + + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ + template<typename T> + Callback(const T *obj, R (*func)(const T*, A0)) { + attach(obj, func); + } + + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ + template<typename T> + Callback(volatile T *obj, R (*func)(volatile T*, A0)) { + attach(obj, func); + } + + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ + template<typename T> + Callback(const volatile T *obj, R (*func)(const volatile 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 a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ + template<typename T> + Callback(const T *obj, R (T::*func)(A0) const) { + attach(obj, func); + } + + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ + template<typename T> + Callback(volatile T *obj, R (T::*func)(A0) volatile) { + attach(obj, func); + } + + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ + template<typename T> + Callback(const volatile T *obj, R (T::*func)(A0) const volatile) { + attach(obj, func); + } + + /** Attach a static function + * @param func Static function to attach + */ + void attach(R (*func)(A0)) { + struct local { + static R _thunk(void*, const void *func, A0 a0) { + return (*static_cast<R (*const *)(A0)>(func))( + a0); + } + }; + + memset(&_func, 0, sizeof _func); + memcpy(&_func, &func, sizeof func); + _obj = 0; + _thunk = func ? &local::_thunk : 0; + } + + /** Attach a Callback + * @param func The Callback to attach + */ + void attach(const Callback<R(A0)> &func) { + memset(&_func, 0, sizeof _func); + memcpy(&_func, &func._func, sizeof func); + _obj = func._obj; + _thunk = func._thunk; + } + + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ + void attach(void *obj, R (*func)(void*, A0)) { + struct local { + static R _thunk(void *obj, const void *func, A0 a0) { + return (*static_cast<R (*const *)(void*, A0)>(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<R (*const *)(const void*, A0)>(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<R (*const *)(volatile void*, A0)>(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<R (*const *)(const volatile void*, A0)>(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 + */ + template <typename T> + void attach(T *obj, R (*func)(T*, A0)) { + struct local { + static R _thunk(void *obj, const void *func, A0 a0) { + return (*static_cast<R (*const *)(T*, A0)>(func))( + (T*)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 + */ + template <typename T> + void attach(const T *obj, R (*func)(const T*, A0)) { + struct local { + static R _thunk(void *obj, const void *func, A0 a0) { + return (*static_cast<R (*const *)(const T*, A0)>(func))( + (const T*)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 + */ + template <typename T> + void attach(volatile T *obj, R (*func)(volatile T*, A0)) { + struct local { + static R _thunk(void *obj, const void *func, A0 a0) { + return (*static_cast<R (*const *)(volatile T*, A0)>(func))( + (volatile T*)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 + */ + template <typename T> + void attach(const volatile T *obj, R (*func)(const volatile T*, A0)) { + struct local { + static R _thunk(void *obj, const void *func, A0 a0) { + return (*static_cast<R (*const *)(const volatile T*, A0)>(func))( + (const volatile T*)obj, a0); + } + }; + + memset(&_func, 0, sizeof _func); + memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; + _thunk = &local::_thunk; + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ + template<typename T> + void attach(T *obj, R (T::*func)(A0)) { + struct local { + static R _thunk(void *obj, const void *func, A0 a0) { + return (((T*)obj)->* + (*static_cast<R (T::*const *)(A0)>(func)))( + a0); + } + }; + + memset(&_func, 0, sizeof _func); + memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; + _thunk = &local::_thunk; + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ + template<typename T> + void attach(const T *obj, R (T::*func)(A0) const) { + struct local { + static R _thunk(void *obj, const void *func, A0 a0) { + return (((const T*)obj)->* + (*static_cast<R (T::*const *)(A0) const>(func)))( + a0); + } + }; + + memset(&_func, 0, sizeof _func); + memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; + _thunk = &local::_thunk; + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ + template<typename T> + void attach(volatile T *obj, R (T::*func)(A0) volatile) { + struct local { + static R _thunk(void *obj, const void *func, A0 a0) { + return (((volatile T*)obj)->* + (*static_cast<R (T::*const *)(A0) volatile>(func)))( + a0); + } + }; + + memset(&_func, 0, sizeof _func); + memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; + _thunk = &local::_thunk; + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ + template<typename T> + void attach(const volatile T *obj, R (T::*func)(A0) const volatile) { + struct local { + static R _thunk(void *obj, const void *func, A0 a0) { + return (((const volatile T*)obj)->* + (*static_cast<R (T::*const *)(A0) const volatile>(func)))( + a0); + } + }; + + memset(&_func, 0, sizeof _func); + memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; + _thunk = &local::_thunk; + } + + /** Call the attached function + */ + R call(A0 a0) const { + MBED_ASSERT(_thunk); + return _thunk(_obj, &_func, a0); + } + + /** Call the attached function + */ + R operator()(A0 a0) const { + return call(a0); + } + + /** Test if function has been attached + */ + operator bool() const { + return _thunk; + } + + /** Test for equality + */ + friend bool operator==(const Callback &l, const Callback &r) { + return memcmp(&l, &r, sizeof(Callback)) == 0; + } + + /** Test for inequality + */ + friend bool operator!=(const Callback &l, const Callback &r) { + return !(l == r); + } + + /** Static thunk for passing as C-style function + * @param func Callback to call passed as void pointer + */ + static R thunk(void *func, A0 a0) { + return static_cast<Callback<R(A0)>*>(func)->call( + a0); + } + +private: + // 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*, const void*, A0); +}; + +/** Callback class based on template specialization + * + * @Note Synchronization level: Not protected + */ +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 + */ + 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 + */ + template<typename T> + Callback(T *obj, R (*func)(T*, A0, A1)) { + attach(obj, func); + } + + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ + template<typename T> + Callback(const T *obj, R (*func)(const T*, A0, A1)) { + attach(obj, func); + } + + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ + template<typename T> + Callback(volatile T *obj, R (*func)(volatile T*, A0, A1)) { + attach(obj, func); + } + + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ + template<typename T> + Callback(const volatile T *obj, R (*func)(const volatile 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 a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ + template<typename T> + Callback(const T *obj, R (T::*func)(A0, A1) const) { + attach(obj, func); + } + + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ + template<typename T> + Callback(volatile T *obj, R (T::*func)(A0, A1) volatile) { + attach(obj, func); + } + + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ + template<typename T> + Callback(const volatile T *obj, R (T::*func)(A0, A1) const volatile) { + attach(obj, func); + } + + /** Attach a static function + * @param func Static function to attach + */ + void attach(R (*func)(A0, A1)) { + struct local { + static R _thunk(void*, const void *func, A0 a0, A1 a1) { + return (*static_cast<R (*const *)(A0, A1)>(func))( + a0, a1); + } + }; + + memset(&_func, 0, sizeof _func); + memcpy(&_func, &func, sizeof func); + _obj = 0; + _thunk = func ? &local::_thunk : 0; + } + + /** Attach a Callback + * @param func The Callback to attach + */ + void attach(const Callback<R(A0, A1)> &func) { + memset(&_func, 0, sizeof _func); + memcpy(&_func, &func._func, sizeof func); + _obj = func._obj; + _thunk = func._thunk; + } + + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ + void attach(void *obj, R (*func)(void*, A0, A1)) { + struct local { + static R _thunk(void *obj, const void *func, A0 a0, A1 a1) { + return (*static_cast<R (*const *)(void*, A0, A1)>(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<R (*const *)(const void*, A0, A1)>(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<R (*const *)(volatile void*, A0, A1)>(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<R (*const *)(const volatile void*, A0, A1)>(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 + */ + template <typename T> + void attach(T *obj, R (*func)(T*, A0, A1)) { + struct local { + static R _thunk(void *obj, const void *func, A0 a0, A1 a1) { + return (*static_cast<R (*const *)(T*, A0, A1)>(func))( + (T*)obj, a0, a1); + } + }; + + memset(&_func, 0, sizeof _func); + memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; + _thunk = &local::_thunk; + } + + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ + template <typename T> + void attach(const T *obj, R (*func)(const T*, A0, A1)) { + struct local { + static R _thunk(void *obj, const void *func, A0 a0, A1 a1) { + return (*static_cast<R (*const *)(const T*, A0, A1)>(func))( + (const T*)obj, a0, a1); + } + }; + + memset(&_func, 0, sizeof _func); + memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; + _thunk = &local::_thunk; + } + + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ + template <typename T> + void attach(volatile T *obj, R (*func)(volatile T*, A0, A1)) { + struct local { + static R _thunk(void *obj, const void *func, A0 a0, A1 a1) { + return (*static_cast<R (*const *)(volatile T*, A0, A1)>(func))( + (volatile T*)obj, a0, a1); + } + }; + + memset(&_func, 0, sizeof _func); + memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; + _thunk = &local::_thunk; + } + + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ + template <typename T> + void attach(const volatile T *obj, R (*func)(const volatile T*, A0, A1)) { + struct local { + static R _thunk(void *obj, const void *func, A0 a0, A1 a1) { + return (*static_cast<R (*const *)(const volatile T*, A0, A1)>(func))( + (const volatile T*)obj, a0, a1); + } + }; + + memset(&_func, 0, sizeof _func); + memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; + _thunk = &local::_thunk; + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ + template<typename T> + void attach(T *obj, R (T::*func)(A0, A1)) { + struct local { + static R _thunk(void *obj, const void *func, A0 a0, A1 a1) { + return (((T*)obj)->* + (*static_cast<R (T::*const *)(A0, A1)>(func)))( + a0, a1); + } + }; + + memset(&_func, 0, sizeof _func); + memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; + _thunk = &local::_thunk; + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ + template<typename T> + void attach(const T *obj, R (T::*func)(A0, A1) const) { + struct local { + static R _thunk(void *obj, const void *func, A0 a0, A1 a1) { + return (((const T*)obj)->* + (*static_cast<R (T::*const *)(A0, A1) const>(func)))( + a0, a1); + } + }; + + memset(&_func, 0, sizeof _func); + memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; + _thunk = &local::_thunk; + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ + template<typename T> + void attach(volatile T *obj, R (T::*func)(A0, A1) volatile) { + struct local { + static R _thunk(void *obj, const void *func, A0 a0, A1 a1) { + return (((volatile T*)obj)->* + (*static_cast<R (T::*const *)(A0, A1) volatile>(func)))( + a0, a1); + } + }; + + memset(&_func, 0, sizeof _func); + memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; + _thunk = &local::_thunk; + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ + template<typename T> + void attach(const volatile T *obj, R (T::*func)(A0, A1) const volatile) { + struct local { + static R _thunk(void *obj, const void *func, A0 a0, A1 a1) { + return (((const volatile T*)obj)->* + (*static_cast<R (T::*const *)(A0, A1) const volatile>(func)))( + a0, a1); + } + }; + + memset(&_func, 0, sizeof _func); + memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; + _thunk = &local::_thunk; + } + + /** Call the attached function + */ + R call(A0 a0, A1 a1) const { + MBED_ASSERT(_thunk); + return _thunk(_obj, &_func, a0, a1); + } + + /** Call the attached function + */ + R operator()(A0 a0, A1 a1) const { + return call(a0, a1); + } + + /** Test if function has been attached + */ + operator bool() const { + return _thunk; + } + + /** Test for equality + */ + friend bool operator==(const Callback &l, const Callback &r) { + return memcmp(&l, &r, sizeof(Callback)) == 0; + } + + /** Test for inequality + */ + friend bool operator!=(const Callback &l, const Callback &r) { + return !(l == r); + } + + /** Static thunk for passing as C-style function + * @param func Callback to call passed as void pointer + */ + static R thunk(void *func, A0 a0, A1 a1) { + return static_cast<Callback<R(A0, A1)>*>(func)->call( + a0, a1); + } + +private: + // 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*, const void*, A0, A1); +}; + +/** Callback class based on template specialization + * + * @Note Synchronization level: Not protected + */ +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 + */ + 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 + */ + template<typename T> + Callback(T *obj, R (*func)(T*, A0, A1, A2)) { + attach(obj, func); + } + + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ + template<typename T> + Callback(const T *obj, R (*func)(const T*, A0, A1, A2)) { + attach(obj, func); + } + + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ + template<typename T> + Callback(volatile T *obj, R (*func)(volatile T*, A0, A1, A2)) { + attach(obj, func); + } + + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ + template<typename T> + Callback(const volatile T *obj, R (*func)(const volatile 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 a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ + template<typename T> + Callback(const T *obj, R (T::*func)(A0, A1, A2) const) { + attach(obj, func); + } + + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ + template<typename T> + Callback(volatile T *obj, R (T::*func)(A0, A1, A2) volatile) { + attach(obj, func); + } + + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ + template<typename T> + Callback(const volatile T *obj, R (T::*func)(A0, A1, A2) const volatile) { + attach(obj, func); + } + + /** Attach a static function + * @param func Static function to attach + */ + void attach(R (*func)(A0, A1, A2)) { + struct local { + static R _thunk(void*, const void *func, A0 a0, A1 a1, A2 a2) { + return (*static_cast<R (*const *)(A0, A1, A2)>(func))( + a0, a1, a2); + } + }; + + memset(&_func, 0, sizeof _func); + memcpy(&_func, &func, sizeof func); + _obj = 0; + _thunk = func ? &local::_thunk : 0; + } + + /** Attach a Callback + * @param func The Callback to attach + */ + void attach(const Callback<R(A0, A1, A2)> &func) { + memset(&_func, 0, sizeof _func); + memcpy(&_func, &func._func, sizeof func); + _obj = func._obj; + _thunk = func._thunk; + } + + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ + void attach(void *obj, R (*func)(void*, A0, A1, A2)) { + struct local { + static R _thunk(void *obj, const void *func, A0 a0, A1 a1, A2 a2) { + return (*static_cast<R (*const *)(void*, A0, A1, A2)>(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<R (*const *)(const void*, A0, A1, A2)>(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<R (*const *)(volatile void*, A0, A1, A2)>(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<R (*const *)(const volatile void*, A0, A1, A2)>(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 + */ + template <typename T> + void attach(T *obj, R (*func)(T*, A0, A1, A2)) { + struct local { + static R _thunk(void *obj, const void *func, A0 a0, A1 a1, A2 a2) { + return (*static_cast<R (*const *)(T*, A0, A1, A2)>(func))( + (T*)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 + */ + template <typename T> + void attach(const T *obj, R (*func)(const T*, A0, A1, A2)) { + struct local { + static R _thunk(void *obj, const void *func, A0 a0, A1 a1, A2 a2) { + return (*static_cast<R (*const *)(const T*, A0, A1, A2)>(func))( + (const T*)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 + */ + template <typename T> + void attach(volatile T *obj, R (*func)(volatile T*, A0, A1, A2)) { + struct local { + static R _thunk(void *obj, const void *func, A0 a0, A1 a1, A2 a2) { + return (*static_cast<R (*const *)(volatile T*, A0, A1, A2)>(func))( + (volatile T*)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 + */ + template <typename T> + void attach(const volatile T *obj, R (*func)(const volatile T*, A0, A1, A2)) { + struct local { + static R _thunk(void *obj, const void *func, A0 a0, A1 a1, A2 a2) { + return (*static_cast<R (*const *)(const volatile T*, A0, A1, A2)>(func))( + (const volatile T*)obj, a0, a1, a2); + } + }; + + memset(&_func, 0, sizeof _func); + memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; + _thunk = &local::_thunk; + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ + template<typename T> + void attach(T *obj, R (T::*func)(A0, A1, A2)) { + struct local { + static R _thunk(void *obj, const void *func, A0 a0, A1 a1, A2 a2) { + return (((T*)obj)->* + (*static_cast<R (T::*const *)(A0, A1, A2)>(func)))( + a0, a1, a2); + } + }; + + memset(&_func, 0, sizeof _func); + memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; + _thunk = &local::_thunk; + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ + template<typename T> + void attach(const T *obj, R (T::*func)(A0, A1, A2) const) { + struct local { + static R _thunk(void *obj, const void *func, A0 a0, A1 a1, A2 a2) { + return (((const T*)obj)->* + (*static_cast<R (T::*const *)(A0, A1, A2) const>(func)))( + a0, a1, a2); + } + }; + + memset(&_func, 0, sizeof _func); + memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; + _thunk = &local::_thunk; + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ + template<typename T> + void attach(volatile T *obj, R (T::*func)(A0, A1, A2) volatile) { + struct local { + static R _thunk(void *obj, const void *func, A0 a0, A1 a1, A2 a2) { + return (((volatile T*)obj)->* + (*static_cast<R (T::*const *)(A0, A1, A2) volatile>(func)))( + a0, a1, a2); + } + }; + + memset(&_func, 0, sizeof _func); + memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; + _thunk = &local::_thunk; + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ + template<typename T> + void attach(const volatile T *obj, R (T::*func)(A0, A1, A2) const volatile) { + struct local { + static R _thunk(void *obj, const void *func, A0 a0, A1 a1, A2 a2) { + return (((const volatile T*)obj)->* + (*static_cast<R (T::*const *)(A0, A1, A2) const volatile>(func)))( + a0, a1, a2); + } + }; + + memset(&_func, 0, sizeof _func); + memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; + _thunk = &local::_thunk; + } + + /** Call the attached function + */ + R call(A0 a0, A1 a1, A2 a2) const { + MBED_ASSERT(_thunk); + return _thunk(_obj, &_func, a0, a1, a2); + } + + /** Call the attached function + */ + R operator()(A0 a0, A1 a1, A2 a2) const { + return call(a0, a1, a2); + } + + /** Test if function has been attached + */ + operator bool() const { + return _thunk; + } + + /** Test for equality + */ + friend bool operator==(const Callback &l, const Callback &r) { + return memcmp(&l, &r, sizeof(Callback)) == 0; + } + + /** Test for inequality + */ + friend bool operator!=(const Callback &l, const Callback &r) { + return !(l == r); + } + + /** Static thunk for passing as C-style function + * @param func Callback to call passed as void pointer + */ + 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: + // 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*, const void*, A0, A1, A2); +}; + +/** Callback class based on template specialization + * + * @Note Synchronization level: Not protected + */ +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 + */ + 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 + */ + template<typename T> + Callback(T *obj, R (*func)(T*, A0, A1, A2, A3)) { + attach(obj, func); + } + + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ + template<typename T> + Callback(const T *obj, R (*func)(const T*, A0, A1, A2, A3)) { + attach(obj, func); + } + + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ + template<typename T> + Callback(volatile T *obj, R (*func)(volatile T*, A0, A1, A2, A3)) { + attach(obj, func); + } + + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ + template<typename T> + Callback(const volatile T *obj, R (*func)(const volatile 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 a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ + template<typename T> + Callback(const T *obj, R (T::*func)(A0, A1, A2, A3) const) { + attach(obj, func); + } + + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ + template<typename T> + Callback(volatile T *obj, R (T::*func)(A0, A1, A2, A3) volatile) { + attach(obj, func); + } + + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ + template<typename T> + Callback(const volatile T *obj, R (T::*func)(A0, A1, A2, A3) const volatile) { + attach(obj, func); + } + + /** Attach a static function + * @param func Static function to attach + */ + void attach(R (*func)(A0, A1, A2, A3)) { + struct local { + static R _thunk(void*, const void *func, A0 a0, A1 a1, A2 a2, A3 a3) { + return (*static_cast<R (*const *)(A0, A1, A2, A3)>(func))( + a0, a1, a2, a3); + } + }; + + memset(&_func, 0, sizeof _func); + memcpy(&_func, &func, sizeof func); + _obj = 0; + _thunk = func ? &local::_thunk : 0; + } + + /** Attach a Callback + * @param func The Callback to attach + */ + void attach(const Callback<R(A0, A1, A2, A3)> &func) { + memset(&_func, 0, sizeof _func); + memcpy(&_func, &func._func, sizeof func); + _obj = func._obj; + _thunk = func._thunk; + } + + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ + void attach(void *obj, R (*func)(void*, A0, A1, A2, A3)) { + struct local { + static R _thunk(void *obj, const void *func, A0 a0, A1 a1, A2 a2, A3 a3) { + return (*static_cast<R (*const *)(void*, A0, A1, A2, A3)>(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<R (*const *)(const void*, A0, A1, A2, A3)>(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<R (*const *)(volatile void*, A0, A1, A2, A3)>(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<R (*const *)(const volatile void*, A0, A1, A2, A3)>(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 + */ + template <typename T> + void attach(T *obj, R (*func)(T*, 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<R (*const *)(T*, A0, A1, A2, A3)>(func))( + (T*)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 + */ + template <typename T> + void attach(const T *obj, R (*func)(const T*, 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<R (*const *)(const T*, A0, A1, A2, A3)>(func))( + (const T*)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 + */ + template <typename T> + void attach(volatile T *obj, R (*func)(volatile T*, 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<R (*const *)(volatile T*, A0, A1, A2, A3)>(func))( + (volatile T*)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 + */ + template <typename T> + void attach(const volatile T *obj, R (*func)(const volatile T*, 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<R (*const *)(const volatile T*, A0, A1, A2, A3)>(func))( + (const volatile T*)obj, a0, a1, a2, a3); + } + }; + + memset(&_func, 0, sizeof _func); + memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; + _thunk = &local::_thunk; + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ + template<typename T> + void attach(T *obj, R (T::*func)(A0, A1, A2, A3)) { + struct local { + static R _thunk(void *obj, const void *func, A0 a0, A1 a1, A2 a2, A3 a3) { + return (((T*)obj)->* + (*static_cast<R (T::*const *)(A0, A1, A2, A3)>(func)))( + a0, a1, a2, a3); + } + }; + + memset(&_func, 0, sizeof _func); + memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; + _thunk = &local::_thunk; + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ + template<typename T> + void attach(const T *obj, R (T::*func)(A0, A1, A2, A3) const) { + struct local { + static R _thunk(void *obj, const void *func, A0 a0, A1 a1, A2 a2, A3 a3) { + return (((const T*)obj)->* + (*static_cast<R (T::*const *)(A0, A1, A2, A3) const>(func)))( + a0, a1, a2, a3); + } + }; + + memset(&_func, 0, sizeof _func); + memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; + _thunk = &local::_thunk; + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ + template<typename T> + void attach(volatile T *obj, R (T::*func)(A0, A1, A2, A3) volatile) { + struct local { + static R _thunk(void *obj, const void *func, A0 a0, A1 a1, A2 a2, A3 a3) { + return (((volatile T*)obj)->* + (*static_cast<R (T::*const *)(A0, A1, A2, A3) volatile>(func)))( + a0, a1, a2, a3); + } + }; + + memset(&_func, 0, sizeof _func); + memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; + _thunk = &local::_thunk; + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ + template<typename T> + void attach(const volatile T *obj, R (T::*func)(A0, A1, A2, A3) const volatile) { + struct local { + static R _thunk(void *obj, const void *func, A0 a0, A1 a1, A2 a2, A3 a3) { + return (((const volatile T*)obj)->* + (*static_cast<R (T::*const *)(A0, A1, A2, A3) const volatile>(func)))( + a0, a1, a2, a3); + } + }; + + memset(&_func, 0, sizeof _func); + memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; + _thunk = &local::_thunk; + } + + /** Call the attached function + */ + R call(A0 a0, A1 a1, A2 a2, A3 a3) const { + MBED_ASSERT(_thunk); + return _thunk(_obj, &_func, a0, a1, a2, a3); + } + + /** Call the attached function + */ + R operator()(A0 a0, A1 a1, A2 a2, A3 a3) const { + return call(a0, a1, a2, a3); + } + + /** Test if function has been attached + */ + operator bool() const { + return _thunk; + } + + /** Test for equality + */ + friend bool operator==(const Callback &l, const Callback &r) { + return memcmp(&l, &r, sizeof(Callback)) == 0; + } + + /** Test for inequality + */ + friend bool operator!=(const Callback &l, const Callback &r) { + return !(l == r); + } + + /** Static thunk for passing as C-style function + * @param func Callback to call passed as void pointer + */ + 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: + // 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*, const void*, A0, A1, A2, A3); +}; + +/** Callback class based on template specialization + * + * @Note Synchronization level: Not protected + */ +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 + */ + 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 + */ + template<typename T> + Callback(T *obj, R (*func)(T*, A0, A1, A2, A3, A4)) { + attach(obj, func); + } + + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ + template<typename T> + Callback(const T *obj, R (*func)(const T*, A0, A1, A2, A3, A4)) { + attach(obj, func); + } + + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ + template<typename T> + Callback(volatile T *obj, R (*func)(volatile T*, A0, A1, A2, A3, A4)) { + attach(obj, func); + } + + /** Create a Callback with a static function and bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ + template<typename T> + Callback(const volatile T *obj, R (*func)(const volatile 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 a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ + template<typename T> + Callback(const T *obj, R (T::*func)(A0, A1, A2, A3, A4) const) { + attach(obj, func); + } + + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ + template<typename T> + Callback(volatile T *obj, R (T::*func)(A0, A1, A2, A3, A4) volatile) { + attach(obj, func); + } + + /** Create a Callback with a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ + template<typename T> + Callback(const volatile T *obj, R (T::*func)(A0, A1, A2, A3, A4) const volatile) { + attach(obj, func); + } + + /** Attach a static function + * @param func Static function to attach + */ + void attach(R (*func)(A0, A1, A2, A3, A4)) { + struct local { + static R _thunk(void*, const void *func, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) { + return (*static_cast<R (*const *)(A0, A1, A2, A3, A4)>(func))( + a0, a1, a2, a3, a4); + } + }; + + memset(&_func, 0, sizeof _func); + memcpy(&_func, &func, sizeof func); + _obj = 0; + _thunk = func ? &local::_thunk : 0; + } + + /** Attach a Callback + * @param func The Callback to attach + */ + void attach(const Callback<R(A0, A1, A2, A3, A4)> &func) { + memset(&_func, 0, sizeof _func); + memcpy(&_func, &func._func, sizeof func); + _obj = func._obj; + _thunk = func._thunk; + } + + /** Attach a static function with a bound pointer + * @param obj Pointer to object to bind to function + * @param func Static function to attach + */ + void attach(void *obj, R (*func)(void*, A0, A1, A2, A3, A4)) { + struct local { + static R _thunk(void *obj, const void *func, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) { + return (*static_cast<R (*const *)(void*, A0, A1, A2, A3, A4)>(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<R (*const *)(const void*, A0, A1, A2, A3, A4)>(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<R (*const *)(volatile void*, A0, A1, A2, A3, A4)>(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<R (*const *)(const volatile void*, A0, A1, A2, A3, A4)>(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 + */ + template <typename T> + void attach(T *obj, R (*func)(T*, 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<R (*const *)(T*, A0, A1, A2, A3, A4)>(func))( + (T*)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 + */ + template <typename T> + void attach(const T *obj, R (*func)(const T*, 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<R (*const *)(const T*, A0, A1, A2, A3, A4)>(func))( + (const T*)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 + */ + template <typename T> + void attach(volatile T *obj, R (*func)(volatile T*, 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<R (*const *)(volatile T*, A0, A1, A2, A3, A4)>(func))( + (volatile T*)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 + */ + template <typename T> + void attach(const volatile T *obj, R (*func)(const volatile T*, 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<R (*const *)(const volatile T*, A0, A1, A2, A3, A4)>(func))( + (const volatile T*)obj, a0, a1, a2, a3, a4); + } + }; + + memset(&_func, 0, sizeof _func); + memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; + _thunk = &local::_thunk; + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ + template<typename T> + void attach(T *obj, R (T::*func)(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 (((T*)obj)->* + (*static_cast<R (T::*const *)(A0, A1, A2, A3, A4)>(func)))( + a0, a1, a2, a3, a4); + } + }; + + memset(&_func, 0, sizeof _func); + memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; + _thunk = &local::_thunk; + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ + template<typename T> + void attach(const T *obj, R (T::*func)(A0, A1, A2, A3, A4) const) { + struct local { + static R _thunk(void *obj, const void *func, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) { + return (((const T*)obj)->* + (*static_cast<R (T::*const *)(A0, A1, A2, A3, A4) const>(func)))( + a0, a1, a2, a3, a4); + } + }; + + memset(&_func, 0, sizeof _func); + memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; + _thunk = &local::_thunk; + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ + template<typename T> + void attach(volatile T *obj, R (T::*func)(A0, A1, A2, A3, A4) volatile) { + struct local { + static R _thunk(void *obj, const void *func, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) { + return (((volatile T*)obj)->* + (*static_cast<R (T::*const *)(A0, A1, A2, A3, A4) volatile>(func)))( + a0, a1, a2, a3, a4); + } + }; + + memset(&_func, 0, sizeof _func); + memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; + _thunk = &local::_thunk; + } + + /** Attach a member function + * @param obj Pointer to object to invoke member function on + * @param func Member function to attach + */ + template<typename T> + void attach(const volatile T *obj, R (T::*func)(A0, A1, A2, A3, A4) const volatile) { + struct local { + static R _thunk(void *obj, const void *func, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) { + return (((const volatile T*)obj)->* + (*static_cast<R (T::*const *)(A0, A1, A2, A3, A4) const volatile>(func)))( + a0, a1, a2, a3, a4); + } + }; + + memset(&_func, 0, sizeof _func); + memcpy(&_func, &func, sizeof func); + _obj = (void*)obj; + _thunk = &local::_thunk; + } + + /** Call the attached function + */ + R call(A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) const { + MBED_ASSERT(_thunk); + return _thunk(_obj, &_func, a0, a1, a2, a3, a4); + } + + /** Call the attached function + */ + R operator()(A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) const { + return call(a0, a1, a2, a3, a4); + } + + /** Test if function has been attached + */ + operator bool() const { + return _thunk; + } + + /** Test for equality + */ + friend bool operator==(const Callback &l, const Callback &r) { + return memcmp(&l, &r, sizeof(Callback)) == 0; + } + + /** Test for inequality + */ + friend bool operator!=(const Callback &l, const Callback &r) { + return !(l == r); + } + + /** Static thunk for passing as C-style function + * @param func Callback to call passed as void pointer + */ + 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: + // 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*, const void*, A0, A1, A2, A3, A4); +}; + +// Internally used event type +typedef Callback<void(int)> event_callback_t; + + +/** Create a callback class with type infered from the arguments + * + * @param func Static function to attach + * @return Callback with infered type + */ +template <typename R> +Callback<R()> callback(R (*func)() = 0) { + return Callback<R()>(func); +} + +/** Create a callback class with type infered from the arguments + * + * @param func Static function to attach + * @return Callback with infered type + */ +template <typename R> +Callback<R()> callback(const Callback<R()> &func) { + return Callback<R()>(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 <typename R> +Callback<R()> callback(void *obj, R (*func)(void*)) { + return Callback<R()>(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 <typename R> +Callback<R()> callback(const void *obj, R (*func)(const void*)) { + return Callback<R()>(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 <typename R> +Callback<R()> callback(volatile void *obj, R (*func)(volatile void*)) { + return Callback<R()>(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 <typename R> +Callback<R()> callback(const volatile void *obj, R (*func)(const volatile void*)) { + return Callback<R()>(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 <typename T, typename R> +Callback<R()> callback(T *obj, R (*func)(T*)) { + return Callback<R()>(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 <typename T, typename R> +Callback<R()> callback(const T *obj, R (*func)(const T*)) { + return Callback<R()>(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 <typename T, typename R> +Callback<R()> callback(volatile T *obj, R (*func)(volatile T*)) { + return Callback<R()>(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 <typename T, typename R> +Callback<R()> callback(const volatile T *obj, R (*func)(const volatile T*)) { + return Callback<R()>(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<typename T, typename R> +Callback<R()> callback(T *obj, R (T::*func)()) { + return Callback<R()>(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<typename T, typename R> +Callback<R()> callback(const T *obj, R (T::*func)() const) { + return Callback<R()>(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<typename T, typename R> +Callback<R()> callback(volatile T *obj, R (T::*func)() volatile) { + return Callback<R()>(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<typename T, typename R> +Callback<R()> callback(const volatile T *obj, R (T::*func)() const volatile) { + return Callback<R()>(obj, func); +} + + +/** Create a callback class with type infered from the arguments + * + * @param func Static function to attach + * @return Callback with infered type + */ +template <typename R, typename A0> +Callback<R(A0)> callback(R (*func)(A0) = 0) { + return Callback<R(A0)>(func); +} + +/** Create a callback class with type infered from the arguments + * + * @param func Static function to attach + * @return Callback with infered type + */ +template <typename R, typename A0> +Callback<R(A0)> callback(const Callback<R(A0)> &func) { + return Callback<R(A0)>(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 <typename R, typename A0> +Callback<R(A0)> callback(void *obj, R (*func)(void*, A0)) { + return Callback<R(A0)>(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 <typename R, typename A0> +Callback<R(A0)> callback(const void *obj, R (*func)(const void*, A0)) { + return Callback<R(A0)>(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 <typename R, typename A0> +Callback<R(A0)> callback(volatile void *obj, R (*func)(volatile void*, A0)) { + return Callback<R(A0)>(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 <typename R, typename A0> +Callback<R(A0)> callback(const volatile void *obj, R (*func)(const volatile void*, A0)) { + return Callback<R(A0)>(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 <typename T, typename R, typename A0> +Callback<R(A0)> callback(T *obj, R (*func)(T*, A0)) { + return Callback<R(A0)>(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 <typename T, typename R, typename A0> +Callback<R(A0)> callback(const T *obj, R (*func)(const T*, A0)) { + return Callback<R(A0)>(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 <typename T, typename R, typename A0> +Callback<R(A0)> callback(volatile T *obj, R (*func)(volatile T*, A0)) { + return Callback<R(A0)>(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 <typename T, typename R, typename A0> +Callback<R(A0)> callback(const volatile T *obj, R (*func)(const volatile T*, A0)) { + return Callback<R(A0)>(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<typename T, typename R, typename A0> +Callback<R(A0)> callback(T *obj, R (T::*func)(A0)) { + return Callback<R(A0)>(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<typename T, typename R, typename A0> +Callback<R(A0)> callback(const T *obj, R (T::*func)(A0) const) { + return Callback<R(A0)>(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<typename T, typename R, typename A0> +Callback<R(A0)> callback(volatile T *obj, R (T::*func)(A0) volatile) { + return Callback<R(A0)>(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<typename T, typename R, typename A0> +Callback<R(A0)> callback(const volatile T *obj, R (T::*func)(A0) const volatile) { + return Callback<R(A0)>(obj, func); +} + + +/** Create a callback class with type infered from the arguments + * + * @param func Static function to attach + * @return Callback with infered type + */ +template <typename R, typename A0, typename A1> +Callback<R(A0, A1)> callback(R (*func)(A0, A1) = 0) { + return Callback<R(A0, A1)>(func); +} + +/** Create a callback class with type infered from the arguments + * + * @param func Static function to attach + * @return Callback with infered type + */ +template <typename R, typename A0, typename A1> +Callback<R(A0, A1)> callback(const Callback<R(A0, A1)> &func) { + return Callback<R(A0, A1)>(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 <typename R, typename A0, typename A1> +Callback<R(A0, A1)> callback(void *obj, R (*func)(void*, A0, A1)) { + return Callback<R(A0, A1)>(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 <typename R, typename A0, typename A1> +Callback<R(A0, A1)> callback(const void *obj, R (*func)(const void*, A0, A1)) { + return Callback<R(A0, A1)>(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 <typename R, typename A0, typename A1> +Callback<R(A0, A1)> callback(volatile void *obj, R (*func)(volatile void*, A0, A1)) { + return Callback<R(A0, A1)>(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 <typename R, typename A0, typename A1> +Callback<R(A0, A1)> callback(const volatile void *obj, R (*func)(const volatile void*, A0, A1)) { + return Callback<R(A0, A1)>(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 <typename T, typename R, typename A0, typename A1> +Callback<R(A0, A1)> callback(T *obj, R (*func)(T*, A0, A1)) { + return Callback<R(A0, A1)>(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 <typename T, typename R, typename A0, typename A1> +Callback<R(A0, A1)> callback(const T *obj, R (*func)(const T*, A0, A1)) { + return Callback<R(A0, A1)>(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 <typename T, typename R, typename A0, typename A1> +Callback<R(A0, A1)> callback(volatile T *obj, R (*func)(volatile T*, A0, A1)) { + return Callback<R(A0, A1)>(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 <typename T, typename R, typename A0, typename A1> +Callback<R(A0, A1)> callback(const volatile T *obj, R (*func)(const volatile T*, A0, A1)) { + return Callback<R(A0, A1)>(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<typename T, typename R, typename A0, typename A1> +Callback<R(A0, A1)> callback(T *obj, R (T::*func)(A0, A1)) { + return Callback<R(A0, A1)>(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<typename T, typename R, typename A0, typename A1> +Callback<R(A0, A1)> callback(const T *obj, R (T::*func)(A0, A1) const) { + return Callback<R(A0, A1)>(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<typename T, typename R, typename A0, typename A1> +Callback<R(A0, A1)> callback(volatile T *obj, R (T::*func)(A0, A1) volatile) { + return Callback<R(A0, A1)>(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<typename T, typename R, typename A0, typename A1> +Callback<R(A0, A1)> callback(const volatile T *obj, R (T::*func)(A0, A1) const volatile) { + return Callback<R(A0, A1)>(obj, func); +} + + +/** Create a callback class with type infered from the arguments + * + * @param func Static function to attach + * @return Callback with infered type + */ +template <typename R, typename A0, typename A1, typename A2> +Callback<R(A0, A1, A2)> callback(R (*func)(A0, A1, A2) = 0) { + return Callback<R(A0, A1, A2)>(func); +} + +/** Create a callback class with type infered from the arguments + * + * @param func Static function to attach + * @return Callback with infered type + */ +template <typename R, typename A0, typename A1, typename A2> +Callback<R(A0, A1, A2)> callback(const Callback<R(A0, A1, A2)> &func) { + return Callback<R(A0, A1, A2)>(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 <typename R, typename A0, typename A1, typename A2> +Callback<R(A0, A1, A2)> callback(void *obj, R (*func)(void*, A0, A1, A2)) { + return Callback<R(A0, A1, A2)>(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 <typename R, typename A0, typename A1, typename A2> +Callback<R(A0, A1, A2)> callback(const void *obj, R (*func)(const void*, A0, A1, A2)) { + return Callback<R(A0, A1, A2)>(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 <typename R, typename A0, typename A1, typename A2> +Callback<R(A0, A1, A2)> callback(volatile void *obj, R (*func)(volatile void*, A0, A1, A2)) { + return Callback<R(A0, A1, A2)>(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 <typename R, typename A0, typename A1, typename A2> +Callback<R(A0, A1, A2)> callback(const volatile void *obj, R (*func)(const volatile void*, A0, A1, A2)) { + return Callback<R(A0, A1, A2)>(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 <typename T, typename R, typename A0, typename A1, typename A2> +Callback<R(A0, A1, A2)> callback(T *obj, R (*func)(T*, A0, A1, A2)) { + return Callback<R(A0, A1, A2)>(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 <typename T, typename R, typename A0, typename A1, typename A2> +Callback<R(A0, A1, A2)> callback(const T *obj, R (*func)(const T*, A0, A1, A2)) { + return Callback<R(A0, A1, A2)>(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 <typename T, typename R, typename A0, typename A1, typename A2> +Callback<R(A0, A1, A2)> callback(volatile T *obj, R (*func)(volatile T*, A0, A1, A2)) { + return Callback<R(A0, A1, A2)>(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 <typename T, typename R, typename A0, typename A1, typename A2> +Callback<R(A0, A1, A2)> callback(const volatile T *obj, R (*func)(const volatile T*, A0, A1, A2)) { + return Callback<R(A0, A1, A2)>(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<typename T, typename R, typename A0, typename A1, typename A2> +Callback<R(A0, A1, A2)> callback(T *obj, R (T::*func)(A0, A1, A2)) { + return Callback<R(A0, A1, A2)>(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<typename T, typename R, typename A0, typename A1, typename A2> +Callback<R(A0, A1, A2)> callback(const T *obj, R (T::*func)(A0, A1, A2) const) { + return Callback<R(A0, A1, A2)>(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<typename T, typename R, typename A0, typename A1, typename A2> +Callback<R(A0, A1, A2)> callback(volatile T *obj, R (T::*func)(A0, A1, A2) volatile) { + return Callback<R(A0, A1, A2)>(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<typename T, typename R, typename A0, typename A1, typename A2> +Callback<R(A0, A1, A2)> callback(const volatile T *obj, R (T::*func)(A0, A1, A2) const volatile) { + return Callback<R(A0, A1, A2)>(obj, func); +} + + +/** Create a callback class with type infered from the arguments + * + * @param func Static function to attach + * @return Callback with infered type + */ +template <typename R, typename A0, typename A1, typename A2, typename A3> +Callback<R(A0, A1, A2, A3)> callback(R (*func)(A0, A1, A2, A3) = 0) { + return Callback<R(A0, A1, A2, A3)>(func); +} + +/** Create a callback class with type infered from the arguments + * + * @param func Static function to attach + * @return Callback with infered type + */ +template <typename R, typename A0, typename A1, typename A2, typename A3> +Callback<R(A0, A1, A2, A3)> callback(const Callback<R(A0, A1, A2, A3)> &func) { + return Callback<R(A0, A1, A2, A3)>(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 <typename R, typename A0, typename A1, typename A2, typename A3> +Callback<R(A0, A1, A2, A3)> callback(void *obj, R (*func)(void*, A0, A1, A2, A3)) { + return Callback<R(A0, A1, A2, A3)>(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 <typename R, typename A0, typename A1, typename A2, typename A3> +Callback<R(A0, A1, A2, A3)> callback(const void *obj, R (*func)(const void*, A0, A1, A2, A3)) { + return Callback<R(A0, A1, A2, A3)>(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 <typename R, typename A0, typename A1, typename A2, typename A3> +Callback<R(A0, A1, A2, A3)> callback(volatile void *obj, R (*func)(volatile void*, A0, A1, A2, A3)) { + return Callback<R(A0, A1, A2, A3)>(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 <typename R, typename A0, typename A1, typename A2, typename A3> +Callback<R(A0, A1, A2, A3)> callback(const volatile void *obj, R (*func)(const volatile void*, A0, A1, A2, A3)) { + return Callback<R(A0, A1, A2, A3)>(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 <typename T, typename R, typename A0, typename A1, typename A2, typename A3> +Callback<R(A0, A1, A2, A3)> callback(T *obj, R (*func)(T*, A0, A1, A2, A3)) { + return Callback<R(A0, A1, A2, A3)>(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 <typename T, typename R, typename A0, typename A1, typename A2, typename A3> +Callback<R(A0, A1, A2, A3)> callback(const T *obj, R (*func)(const T*, A0, A1, A2, A3)) { + return Callback<R(A0, A1, A2, A3)>(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 <typename T, typename R, typename A0, typename A1, typename A2, typename A3> +Callback<R(A0, A1, A2, A3)> callback(volatile T *obj, R (*func)(volatile T*, A0, A1, A2, A3)) { + return Callback<R(A0, A1, A2, A3)>(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 <typename T, typename R, typename A0, typename A1, typename A2, typename A3> +Callback<R(A0, A1, A2, A3)> callback(const volatile T *obj, R (*func)(const volatile T*, A0, A1, A2, A3)) { + return Callback<R(A0, A1, A2, A3)>(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<typename T, typename R, typename A0, typename A1, typename A2, typename A3> +Callback<R(A0, A1, A2, A3)> callback(T *obj, R (T::*func)(A0, A1, A2, A3)) { + return Callback<R(A0, A1, A2, A3)>(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<typename T, typename R, typename A0, typename A1, typename A2, typename A3> +Callback<R(A0, A1, A2, A3)> callback(const T *obj, R (T::*func)(A0, A1, A2, A3) const) { + return Callback<R(A0, A1, A2, A3)>(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<typename T, typename R, typename A0, typename A1, typename A2, typename A3> +Callback<R(A0, A1, A2, A3)> callback(volatile T *obj, R (T::*func)(A0, A1, A2, A3) volatile) { + return Callback<R(A0, A1, A2, A3)>(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<typename T, typename R, typename A0, typename A1, typename A2, typename A3> +Callback<R(A0, A1, A2, A3)> callback(const volatile T *obj, R (T::*func)(A0, A1, A2, A3) const volatile) { + return Callback<R(A0, A1, A2, A3)>(obj, func); +} + + +/** Create a callback class with type infered from the arguments + * + * @param func Static function to attach + * @return Callback with infered type + */ +template <typename R, typename A0, typename A1, typename A2, typename A3, typename A4> +Callback<R(A0, A1, A2, A3, A4)> callback(R (*func)(A0, A1, A2, A3, A4) = 0) { + return Callback<R(A0, A1, A2, A3, A4)>(func); +} + +/** Create a callback class with type infered from the arguments + * + * @param func Static function to attach + * @return Callback with infered type + */ +template <typename R, typename A0, typename A1, typename A2, typename A3, typename A4> +Callback<R(A0, A1, A2, A3, A4)> callback(const Callback<R(A0, A1, A2, A3, A4)> &func) { + return Callback<R(A0, A1, A2, A3, A4)>(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 <typename R, typename A0, typename A1, typename A2, typename A3, typename A4> +Callback<R(A0, A1, A2, A3, A4)> callback(void *obj, R (*func)(void*, A0, A1, A2, A3, A4)) { + return Callback<R(A0, A1, A2, A3, A4)>(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 <typename R, typename A0, typename A1, typename A2, typename A3, typename A4> +Callback<R(A0, A1, A2, A3, A4)> callback(const void *obj, R (*func)(const void*, A0, A1, A2, A3, A4)) { + return Callback<R(A0, A1, A2, A3, A4)>(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 <typename R, typename A0, typename A1, typename A2, typename A3, typename A4> +Callback<R(A0, A1, A2, A3, A4)> callback(volatile void *obj, R (*func)(volatile void*, A0, A1, A2, A3, A4)) { + return Callback<R(A0, A1, A2, A3, A4)>(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 <typename R, typename A0, typename A1, typename A2, typename A3, typename A4> +Callback<R(A0, A1, A2, A3, A4)> callback(const volatile void *obj, R (*func)(const volatile void*, A0, A1, A2, A3, A4)) { + return Callback<R(A0, A1, A2, A3, A4)>(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 <typename T, typename R, typename A0, typename A1, typename A2, typename A3, typename A4> +Callback<R(A0, A1, A2, A3, A4)> callback(T *obj, R (*func)(T*, A0, A1, A2, A3, A4)) { + return Callback<R(A0, A1, A2, A3, A4)>(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 <typename T, typename R, typename A0, typename A1, typename A2, typename A3, typename A4> +Callback<R(A0, A1, A2, A3, A4)> callback(const T *obj, R (*func)(const T*, A0, A1, A2, A3, A4)) { + return Callback<R(A0, A1, A2, A3, A4)>(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 <typename T, typename R, typename A0, typename A1, typename A2, typename A3, typename A4> +Callback<R(A0, A1, A2, A3, A4)> callback(volatile T *obj, R (*func)(volatile T*, A0, A1, A2, A3, A4)) { + return Callback<R(A0, A1, A2, A3, A4)>(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 <typename T, typename R, typename A0, typename A1, typename A2, typename A3, typename A4> +Callback<R(A0, A1, A2, A3, A4)> callback(const volatile T *obj, R (*func)(const volatile T*, A0, A1, A2, A3, A4)) { + return Callback<R(A0, A1, A2, A3, A4)>(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<typename T, typename R, typename A0, typename A1, typename A2, typename A3, typename A4> +Callback<R(A0, A1, A2, A3, A4)> callback(T *obj, R (T::*func)(A0, A1, A2, A3, A4)) { + return Callback<R(A0, A1, A2, A3, A4)>(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<typename T, typename R, typename A0, typename A1, typename A2, typename A3, typename A4> +Callback<R(A0, A1, A2, A3, A4)> callback(const T *obj, R (T::*func)(A0, A1, A2, A3, A4) const) { + return Callback<R(A0, A1, A2, A3, A4)>(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<typename T, typename R, typename A0, typename A1, typename A2, typename A3, typename A4> +Callback<R(A0, A1, A2, A3, A4)> callback(volatile T *obj, R (T::*func)(A0, A1, A2, A3, A4) volatile) { + return Callback<R(A0, A1, A2, A3, A4)>(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<typename T, typename R, typename A0, typename A1, typename A2, typename A3, typename A4> +Callback<R(A0, A1, A2, A3, A4)> callback(const volatile T *obj, R (T::*func)(A0, A1, A2, A3, A4) const volatile) { + return Callback<R(A0, A1, A2, A3, A4)>(obj, func); +} + + +} // namespace mbed + +#endif