/* 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 #include #include #include "platform/mbed_assert.h" #include "platform/toolchain.h" namespace mbed { /** Callback class based on template specialization * * @Note Synchronization level: Not protected */ template class Callback; // Internal sfinae declarations // // These are used to eliminate overloads based on type attributes // 1. Does a function object have a call operator // 2. Does a function object fit in the available storage // // These eliminations are handled cleanly by the compiler and avoid // massive and misleading error messages when confronted with an // invalid type (or worse, runtime failures) namespace detail { struct nil {}; template struct enable_if { typedef R type; }; template struct enable_if {}; template struct is_type { static const bool value = true; }; } /** Callback class based on template specialization * * @Note Synchronization level: Not protected */ template class Callback { public: /** Create a Callback with a static function * @param func Static function to attach */ Callback(R (*func)() = 0) { if (!func) { _ops = 0; } else { generate(func); } } /** Attach a Callback * @param func The Callback to attach */ Callback(const Callback &func) { if (func._ops) { func._ops->move(this, &func); } _ops = func._ops; } /** Create a Callback with a member function * @param obj Pointer to object to invoke member function on * @param method Member function to attach */ template Callback(T *obj, R (T::*method)()) { generate(method_context(obj, method)); } /** Create a Callback with a member function * @param obj Pointer to object to invoke member function on * @param method Member function to attach */ template Callback(const T *obj, R (T::*method)() const) { generate(method_context(obj, method)); } /** Create a Callback with a member function * @param obj Pointer to object to invoke member function on * @param method Member function to attach */ template Callback(volatile T *obj, R (T::*method)() volatile) { generate(method_context(obj, method)); } /** Create a Callback with a member function * @param obj Pointer to object to invoke member function on * @param method Member function to attach */ template Callback(const volatile T *obj, R (T::*method)() const volatile) { generate(method_context(obj, method)); } /** Create a Callback with a static function and bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ Callback(R (*func)(void*), void *arg) { generate(function_context(func, arg)); } /** Create a Callback with a static function and bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ Callback(R (*func)(const void*), const void *arg) { generate(function_context(func, arg)); } /** Create a Callback with a static function and bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ Callback(R (*func)(volatile void*), volatile void *arg) { generate(function_context(func, arg)); } /** Create a Callback with a static function and bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ Callback(R (*func)(const volatile void*), const volatile void *arg) { generate(function_context(func, arg)); } /** Create a Callback with a static function and bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ template Callback(R (*func)(T*), T *arg) { generate(function_context(func, arg)); } /** Create a Callback with a static function and bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ template Callback(R (*func)(const T*), const T *arg) { generate(function_context(func, arg)); } /** Create a Callback with a static function and bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ template Callback(R (*func)(volatile T*), volatile T *arg) { generate(function_context(func, arg)); } /** Create a Callback with a static function and bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ template Callback(R (*func)(const volatile T*), const volatile T *arg) { generate(function_context(func, arg)); } /** Create a Callback with a function object * @param func Function object to attach * @note The function object is limited to a single word of storage */ template Callback(F f, typename detail::enable_if< detail::is_type::value && sizeof(F) <= sizeof(uintptr_t) >::type = detail::nil()) { generate(f); } /** Create a Callback with a function object * @param func Function object to attach * @note The function object is limited to a single word of storage */ template Callback(const F f, typename detail::enable_if< detail::is_type::value && sizeof(F) <= sizeof(uintptr_t) >::type = detail::nil()) { generate(f); } /** Create a Callback with a function object * @param func Function object to attach * @note The function object is limited to a single word of storage */ template Callback(volatile F f, typename detail::enable_if< detail::is_type::value && sizeof(F) <= sizeof(uintptr_t) >::type = detail::nil()) { generate(f); } /** Create a Callback with a function object * @param func Function object to attach * @note The function object is limited to a single word of storage */ template Callback(const volatile F f, typename detail::enable_if< detail::is_type::value && sizeof(F) <= sizeof(uintptr_t) >::type = detail::nil()) { generate(f); } /** 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 * @deprecated * Arguments to callback have been reordered to Callback(func, arg) */ MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to Callback(func, arg)") Callback(void *obj, R (*func)(void*)) { new (this) Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to Callback(func, arg) */ MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to Callback(func, arg)") Callback(const void *obj, R (*func)(const void*)) { new (this) Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to Callback(func, arg) */ MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to Callback(func, arg)") Callback(volatile void *obj, R (*func)(volatile void*)) { new (this) Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to Callback(func, arg) */ MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to Callback(func, arg)") Callback(const volatile void *obj, R (*func)(const volatile void*)) { new (this) Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to Callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to Callback(func, arg)") Callback(T *obj, R (*func)(T*)) { new (this) Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to Callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to Callback(func, arg)") Callback(const T *obj, R (*func)(const T*)) { new (this) Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to Callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to Callback(func, arg)") Callback(volatile T *obj, R (*func)(volatile T*)) { new (this) Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to Callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to Callback(func, arg)") Callback(const volatile T *obj, R (*func)(const volatile T*)) { new (this) Callback(func, obj); } /** Destroy a callback */ ~Callback() { if (_ops) { _ops->dtor(this); } } /** Attach a static function * @param func Static function to attach */ void attach(R (*func)()) { this->~Callback(); new (this) Callback(func); } /** Attach a Callback * @param func The Callback to attach */ void attach(const Callback &func) { this->~Callback(); new (this) Callback(func); } /** Attach a member function * @param obj Pointer to object to invoke member function on * @param method Member function to attach */ template void attach(T *obj, R (T::*method)()) { this->~Callback(); new (this) Callback(obj, method); } /** Attach a member function * @param obj Pointer to object to invoke member function on * @param method Member function to attach */ template void attach(const T *obj, R (T::*method)() const) { this->~Callback(); new (this) Callback(obj, method); } /** Attach a member function * @param obj Pointer to object to invoke member function on * @param method Member function to attach */ template void attach(volatile T *obj, R (T::*method)() volatile) { this->~Callback(); new (this) Callback(obj, method); } /** Attach a member function * @param obj Pointer to object to invoke member function on * @param method Member function to attach */ template void attach(const volatile T *obj, R (T::*method)() const volatile) { this->~Callback(); new (this) Callback(obj, method); } /** Attach a static function with a bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ void attach(R (*func)(void*), void *arg) { this->~Callback(); new (this) Callback(func, arg); } /** Attach a static function with a bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ void attach(R (*func)(const void*), const void *arg) { this->~Callback(); new (this) Callback(func, arg); } /** Attach a static function with a bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ void attach(R (*func)(volatile void*), volatile void *arg) { this->~Callback(); new (this) Callback(func, arg); } /** Attach a static function with a bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ void attach(R (*func)(const volatile void*), const volatile void *arg) { this->~Callback(); new (this) Callback(func, arg); } /** Attach a static function with a bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ template void attach(R (*func)(T*), T *arg) { this->~Callback(); new (this) Callback(func, arg); } /** Attach a static function with a bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ template void attach(R (*func)(const T*), const T *arg) { this->~Callback(); new (this) Callback(func, arg); } /** Attach a static function with a bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ template void attach(R (*func)(volatile T*), volatile T *arg) { this->~Callback(); new (this) Callback(func, arg); } /** Attach a static function with a bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ template void attach(R (*func)(const volatile T*), const volatile T *arg) { this->~Callback(); new (this) Callback(func, arg); } /** Attach a function object * @param func Function object to attach * @note The function object is limited to a single word of storage */ template void attach(F f, typename detail::enable_if< detail::is_type::value && sizeof(F) <= sizeof(uintptr_t) >::type = detail::nil()) { this->~Callback(); new (this) Callback(f); } /** Attach a function object * @param func Function object to attach * @note The function object is limited to a single word of storage */ template void attach(const F f, typename detail::enable_if< detail::is_type::value && sizeof(F) <= sizeof(uintptr_t) >::type = detail::nil()) { this->~Callback(); new (this) Callback(f); } /** Attach a function object * @param func Function object to attach * @note The function object is limited to a single word of storage */ template void attach(volatile F f, typename detail::enable_if< detail::is_type::value && sizeof(F) <= sizeof(uintptr_t) >::type = detail::nil()) { this->~Callback(); new (this) Callback(f); } /** Attach a function object * @param func Function object to attach * @note The function object is limited to a single word of storage */ template void attach(const volatile F f, typename detail::enable_if< detail::is_type::value && sizeof(F) <= sizeof(uintptr_t) >::type = detail::nil()) { this->~Callback(); new (this) Callback(f); } /** Attach a static function with a bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach * @deprecated * Arguments to callback have been reordered to attach(func, arg) */ MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to attach(func, arg)") void attach(void *obj, R (*func)(void*)) { this->~Callback(); new (this) Callback(func, obj); } /** Attach a static function with a bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach * @deprecated * Arguments to callback have been reordered to attach(func, arg) */ MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to attach(func, arg)") void attach(const void *obj, R (*func)(const void*)) { this->~Callback(); new (this) Callback(func, obj); } /** Attach a static function with a bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach * @deprecated * Arguments to callback have been reordered to attach(func, arg) */ MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to attach(func, arg)") void attach(volatile void *obj, R (*func)(volatile void*)) { this->~Callback(); new (this) Callback(func, obj); } /** Attach a static function with a bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach * @deprecated * Arguments to callback have been reordered to attach(func, arg) */ MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to attach(func, arg)") void attach(const volatile void *obj, R (*func)(const volatile void*)) { this->~Callback(); new (this) Callback(func, obj); } /** Attach a static function with a bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach * @deprecated * Arguments to callback have been reordered to attach(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to attach(func, arg)") void attach(T *obj, R (*func)(T*)) { this->~Callback(); new (this) Callback(func, obj); } /** Attach a static function with a bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach * @deprecated * Arguments to callback have been reordered to attach(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to attach(func, arg)") void attach(const T *obj, R (*func)(const T*)) { this->~Callback(); new (this) Callback(func, obj); } /** Attach a static function with a bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach * @deprecated * Arguments to callback have been reordered to attach(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to attach(func, arg)") void attach(volatile T *obj, R (*func)(volatile T*)) { this->~Callback(); new (this) Callback(func, obj); } /** Attach a static function with a bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach * @deprecated * Arguments to callback have been reordered to attach(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to attach(func, arg)") void attach(const volatile T *obj, R (*func)(const volatile T*)) { this->~Callback(); new (this) Callback(func, obj); } /** Assign a callback */ Callback &operator=(const Callback &that) { if (this != &that) { this->~Callback(); new (this) Callback(that); } return *this; } /** Call the attached function */ R call() const { MBED_ASSERT(_ops); return _ops->call(this); } /** Call the attached function */ R operator()() const { return call(); } /** Test if function has been attached */ operator bool() const { return _ops; } /** 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(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; // Dynamically dispatched operations const struct ops { R (*call)(const void*); void (*move)(void*, const void*); void (*dtor)(void*); } *_ops; // Generate operations for function object template void generate(const F &f) { struct local { static R call(const void *p) { return (*(F*)p)(); } static void move(void *d, const void *p) { new (d) F(*(F*)p); } static void dtor(void *p) { ((F*)p)->~F(); } }; static const ops ops = { &local::call, &local::move, &local::dtor, }; MBED_ASSERT(sizeof(Callback) - sizeof(_ops) >= sizeof(F)); new (this) F(f); _ops = &ops; } // Wrappers for functions with context template struct method_context { M method; O *obj; method_context(O *obj, M method) : method(method), obj(obj) {} R operator()() const { return (obj->*method)(); } }; template struct function_context { F func; A *arg; function_context(F func, A *arg) : func(func), arg(arg) {} R operator()() const { return func(arg); } }; }; /** Callback class based on template specialization * * @Note Synchronization level: Not protected */ template class Callback { public: /** Create a Callback with a static function * @param func Static function to attach */ Callback(R (*func)(A0) = 0) { if (!func) { _ops = 0; } else { generate(func); } } /** Attach a Callback * @param func The Callback to attach */ Callback(const Callback &func) { if (func._ops) { func._ops->move(this, &func); } _ops = func._ops; } /** Create a Callback with a member function * @param obj Pointer to object to invoke member function on * @param method Member function to attach */ template Callback(T *obj, R (T::*method)(A0)) { generate(method_context(obj, method)); } /** Create a Callback with a member function * @param obj Pointer to object to invoke member function on * @param method Member function to attach */ template Callback(const T *obj, R (T::*method)(A0) const) { generate(method_context(obj, method)); } /** Create a Callback with a member function * @param obj Pointer to object to invoke member function on * @param method Member function to attach */ template Callback(volatile T *obj, R (T::*method)(A0) volatile) { generate(method_context(obj, method)); } /** Create a Callback with a member function * @param obj Pointer to object to invoke member function on * @param method Member function to attach */ template Callback(const volatile T *obj, R (T::*method)(A0) const volatile) { generate(method_context(obj, method)); } /** Create a Callback with a static function and bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ Callback(R (*func)(void*, A0), void *arg) { generate(function_context(func, arg)); } /** Create a Callback with a static function and bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ Callback(R (*func)(const void*, A0), const void *arg) { generate(function_context(func, arg)); } /** Create a Callback with a static function and bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ Callback(R (*func)(volatile void*, A0), volatile void *arg) { generate(function_context(func, arg)); } /** Create a Callback with a static function and bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ Callback(R (*func)(const volatile void*, A0), const volatile void *arg) { generate(function_context(func, arg)); } /** Create a Callback with a static function and bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ template Callback(R (*func)(T*, A0), T *arg) { generate(function_context(func, arg)); } /** Create a Callback with a static function and bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ template Callback(R (*func)(const T*, A0), const T *arg) { generate(function_context(func, arg)); } /** Create a Callback with a static function and bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ template Callback(R (*func)(volatile T*, A0), volatile T *arg) { generate(function_context(func, arg)); } /** Create a Callback with a static function and bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ template Callback(R (*func)(const volatile T*, A0), const volatile T *arg) { generate(function_context(func, arg)); } /** Create a Callback with a function object * @param func Function object to attach * @note The function object is limited to a single word of storage */ template Callback(F f, typename detail::enable_if< detail::is_type::value && sizeof(F) <= sizeof(uintptr_t) >::type = detail::nil()) { generate(f); } /** Create a Callback with a function object * @param func Function object to attach * @note The function object is limited to a single word of storage */ template Callback(const F f, typename detail::enable_if< detail::is_type::value && sizeof(F) <= sizeof(uintptr_t) >::type = detail::nil()) { generate(f); } /** Create a Callback with a function object * @param func Function object to attach * @note The function object is limited to a single word of storage */ template Callback(volatile F f, typename detail::enable_if< detail::is_type::value && sizeof(F) <= sizeof(uintptr_t) >::type = detail::nil()) { generate(f); } /** Create a Callback with a function object * @param func Function object to attach * @note The function object is limited to a single word of storage */ template Callback(const volatile F f, typename detail::enable_if< detail::is_type::value && sizeof(F) <= sizeof(uintptr_t) >::type = detail::nil()) { generate(f); } /** 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 * @deprecated * Arguments to callback have been reordered to Callback(func, arg) */ MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to Callback(func, arg)") Callback(void *obj, R (*func)(void*, A0)) { new (this) Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to Callback(func, arg) */ MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to Callback(func, arg)") Callback(const void *obj, R (*func)(const void*, A0)) { new (this) Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to Callback(func, arg) */ MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to Callback(func, arg)") Callback(volatile void *obj, R (*func)(volatile void*, A0)) { new (this) Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to Callback(func, arg) */ MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to Callback(func, arg)") Callback(const volatile void *obj, R (*func)(const volatile void*, A0)) { new (this) Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to Callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to Callback(func, arg)") Callback(T *obj, R (*func)(T*, A0)) { new (this) Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to Callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to Callback(func, arg)") Callback(const T *obj, R (*func)(const T*, A0)) { new (this) Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to Callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to Callback(func, arg)") Callback(volatile T *obj, R (*func)(volatile T*, A0)) { new (this) Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to Callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to Callback(func, arg)") Callback(const volatile T *obj, R (*func)(const volatile T*, A0)) { new (this) Callback(func, obj); } /** Destroy a callback */ ~Callback() { if (_ops) { _ops->dtor(this); } } /** Attach a static function * @param func Static function to attach */ void attach(R (*func)(A0)) { this->~Callback(); new (this) Callback(func); } /** Attach a Callback * @param func The Callback to attach */ void attach(const Callback &func) { this->~Callback(); new (this) Callback(func); } /** Attach a member function * @param obj Pointer to object to invoke member function on * @param method Member function to attach */ template void attach(T *obj, R (T::*method)(A0)) { this->~Callback(); new (this) Callback(obj, method); } /** Attach a member function * @param obj Pointer to object to invoke member function on * @param method Member function to attach */ template void attach(const T *obj, R (T::*method)(A0) const) { this->~Callback(); new (this) Callback(obj, method); } /** Attach a member function * @param obj Pointer to object to invoke member function on * @param method Member function to attach */ template void attach(volatile T *obj, R (T::*method)(A0) volatile) { this->~Callback(); new (this) Callback(obj, method); } /** Attach a member function * @param obj Pointer to object to invoke member function on * @param method Member function to attach */ template void attach(const volatile T *obj, R (T::*method)(A0) const volatile) { this->~Callback(); new (this) Callback(obj, method); } /** Attach a static function with a bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ void attach(R (*func)(void*, A0), void *arg) { this->~Callback(); new (this) Callback(func, arg); } /** Attach a static function with a bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ void attach(R (*func)(const void*, A0), const void *arg) { this->~Callback(); new (this) Callback(func, arg); } /** Attach a static function with a bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ void attach(R (*func)(volatile void*, A0), volatile void *arg) { this->~Callback(); new (this) Callback(func, arg); } /** Attach a static function with a bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ void attach(R (*func)(const volatile void*, A0), const volatile void *arg) { this->~Callback(); new (this) Callback(func, arg); } /** Attach a static function with a bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ template void attach(R (*func)(T*, A0), T *arg) { this->~Callback(); new (this) Callback(func, arg); } /** Attach a static function with a bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ template void attach(R (*func)(const T*, A0), const T *arg) { this->~Callback(); new (this) Callback(func, arg); } /** Attach a static function with a bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ template void attach(R (*func)(volatile T*, A0), volatile T *arg) { this->~Callback(); new (this) Callback(func, arg); } /** Attach a static function with a bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ template void attach(R (*func)(const volatile T*, A0), const volatile T *arg) { this->~Callback(); new (this) Callback(func, arg); } /** Attach a function object * @param func Function object to attach * @note The function object is limited to a single word of storage */ template void attach(F f, typename detail::enable_if< detail::is_type::value && sizeof(F) <= sizeof(uintptr_t) >::type = detail::nil()) { this->~Callback(); new (this) Callback(f); } /** Attach a function object * @param func Function object to attach * @note The function object is limited to a single word of storage */ template void attach(const F f, typename detail::enable_if< detail::is_type::value && sizeof(F) <= sizeof(uintptr_t) >::type = detail::nil()) { this->~Callback(); new (this) Callback(f); } /** Attach a function object * @param func Function object to attach * @note The function object is limited to a single word of storage */ template void attach(volatile F f, typename detail::enable_if< detail::is_type::value && sizeof(F) <= sizeof(uintptr_t) >::type = detail::nil()) { this->~Callback(); new (this) Callback(f); } /** Attach a function object * @param func Function object to attach * @note The function object is limited to a single word of storage */ template void attach(const volatile F f, typename detail::enable_if< detail::is_type::value && sizeof(F) <= sizeof(uintptr_t) >::type = detail::nil()) { this->~Callback(); new (this) Callback(f); } /** Attach a static function with a bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach * @deprecated * Arguments to callback have been reordered to attach(func, arg) */ MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to attach(func, arg)") void attach(void *obj, R (*func)(void*, A0)) { this->~Callback(); new (this) Callback(func, obj); } /** Attach a static function with a bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach * @deprecated * Arguments to callback have been reordered to attach(func, arg) */ MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to attach(func, arg)") void attach(const void *obj, R (*func)(const void*, A0)) { this->~Callback(); new (this) Callback(func, obj); } /** Attach a static function with a bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach * @deprecated * Arguments to callback have been reordered to attach(func, arg) */ MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to attach(func, arg)") void attach(volatile void *obj, R (*func)(volatile void*, A0)) { this->~Callback(); new (this) Callback(func, obj); } /** Attach a static function with a bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach * @deprecated * Arguments to callback have been reordered to attach(func, arg) */ MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to attach(func, arg)") void attach(const volatile void *obj, R (*func)(const volatile void*, A0)) { this->~Callback(); new (this) Callback(func, obj); } /** Attach a static function with a bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach * @deprecated * Arguments to callback have been reordered to attach(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to attach(func, arg)") void attach(T *obj, R (*func)(T*, A0)) { this->~Callback(); new (this) Callback(func, obj); } /** Attach a static function with a bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach * @deprecated * Arguments to callback have been reordered to attach(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to attach(func, arg)") void attach(const T *obj, R (*func)(const T*, A0)) { this->~Callback(); new (this) Callback(func, obj); } /** Attach a static function with a bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach * @deprecated * Arguments to callback have been reordered to attach(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to attach(func, arg)") void attach(volatile T *obj, R (*func)(volatile T*, A0)) { this->~Callback(); new (this) Callback(func, obj); } /** Attach a static function with a bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach * @deprecated * Arguments to callback have been reordered to attach(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to attach(func, arg)") void attach(const volatile T *obj, R (*func)(const volatile T*, A0)) { this->~Callback(); new (this) Callback(func, obj); } /** Assign a callback */ Callback &operator=(const Callback &that) { if (this != &that) { this->~Callback(); new (this) Callback(that); } return *this; } /** Call the attached function */ R call(A0 a0) const { MBED_ASSERT(_ops); return _ops->call(this, a0); } /** Call the attached function */ R operator()(A0 a0) const { return call(a0); } /** Test if function has been attached */ operator bool() const { return _ops; } /** 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(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)(A0); void (*_boundfunc)(_class*, A0); void (_class::*_methodfunc)(A0); } _func; void *_obj; // Dynamically dispatched operations const struct ops { R (*call)(const void*, A0); void (*move)(void*, const void*); void (*dtor)(void*); } *_ops; // Generate operations for function object template void generate(const F &f) { struct local { static R call(const void *p, A0 a0) { return (*(F*)p)(a0); } static void move(void *d, const void *p) { new (d) F(*(F*)p); } static void dtor(void *p) { ((F*)p)->~F(); } }; static const ops ops = { &local::call, &local::move, &local::dtor, }; MBED_ASSERT(sizeof(Callback) - sizeof(_ops) >= sizeof(F)); new (this) F(f); _ops = &ops; } // Wrappers for functions with context template struct method_context { M method; O *obj; method_context(O *obj, M method) : method(method), obj(obj) {} R operator()(A0 a0) const { return (obj->*method)(a0); } }; template struct function_context { F func; A *arg; function_context(F func, A *arg) : func(func), arg(arg) {} R operator()(A0 a0) const { return func(arg, a0); } }; }; /** Callback class based on template specialization * * @Note Synchronization level: Not protected */ template class Callback { public: /** Create a Callback with a static function * @param func Static function to attach */ Callback(R (*func)(A0, A1) = 0) { if (!func) { _ops = 0; } else { generate(func); } } /** Attach a Callback * @param func The Callback to attach */ Callback(const Callback &func) { if (func._ops) { func._ops->move(this, &func); } _ops = func._ops; } /** Create a Callback with a member function * @param obj Pointer to object to invoke member function on * @param method Member function to attach */ template Callback(T *obj, R (T::*method)(A0, A1)) { generate(method_context(obj, method)); } /** Create a Callback with a member function * @param obj Pointer to object to invoke member function on * @param method Member function to attach */ template Callback(const T *obj, R (T::*method)(A0, A1) const) { generate(method_context(obj, method)); } /** Create a Callback with a member function * @param obj Pointer to object to invoke member function on * @param method Member function to attach */ template Callback(volatile T *obj, R (T::*method)(A0, A1) volatile) { generate(method_context(obj, method)); } /** Create a Callback with a member function * @param obj Pointer to object to invoke member function on * @param method Member function to attach */ template Callback(const volatile T *obj, R (T::*method)(A0, A1) const volatile) { generate(method_context(obj, method)); } /** Create a Callback with a static function and bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ Callback(R (*func)(void*, A0, A1), void *arg) { generate(function_context(func, arg)); } /** Create a Callback with a static function and bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ Callback(R (*func)(const void*, A0, A1), const void *arg) { generate(function_context(func, arg)); } /** Create a Callback with a static function and bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ Callback(R (*func)(volatile void*, A0, A1), volatile void *arg) { generate(function_context(func, arg)); } /** Create a Callback with a static function and bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ Callback(R (*func)(const volatile void*, A0, A1), const volatile void *arg) { generate(function_context(func, arg)); } /** Create a Callback with a static function and bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ template Callback(R (*func)(T*, A0, A1), T *arg) { generate(function_context(func, arg)); } /** Create a Callback with a static function and bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ template Callback(R (*func)(const T*, A0, A1), const T *arg) { generate(function_context(func, arg)); } /** Create a Callback with a static function and bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ template Callback(R (*func)(volatile T*, A0, A1), volatile T *arg) { generate(function_context(func, arg)); } /** Create a Callback with a static function and bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ template Callback(R (*func)(const volatile T*, A0, A1), const volatile T *arg) { generate(function_context(func, arg)); } /** Create a Callback with a function object * @param func Function object to attach * @note The function object is limited to a single word of storage */ template Callback(F f, typename detail::enable_if< detail::is_type::value && sizeof(F) <= sizeof(uintptr_t) >::type = detail::nil()) { generate(f); } /** Create a Callback with a function object * @param func Function object to attach * @note The function object is limited to a single word of storage */ template Callback(const F f, typename detail::enable_if< detail::is_type::value && sizeof(F) <= sizeof(uintptr_t) >::type = detail::nil()) { generate(f); } /** Create a Callback with a function object * @param func Function object to attach * @note The function object is limited to a single word of storage */ template Callback(volatile F f, typename detail::enable_if< detail::is_type::value && sizeof(F) <= sizeof(uintptr_t) >::type = detail::nil()) { generate(f); } /** Create a Callback with a function object * @param func Function object to attach * @note The function object is limited to a single word of storage */ template Callback(const volatile F f, typename detail::enable_if< detail::is_type::value && sizeof(F) <= sizeof(uintptr_t) >::type = detail::nil()) { generate(f); } /** 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 * @deprecated * Arguments to callback have been reordered to Callback(func, arg) */ MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to Callback(func, arg)") Callback(void *obj, R (*func)(void*, A0, A1)) { new (this) Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to Callback(func, arg) */ MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to Callback(func, arg)") Callback(const void *obj, R (*func)(const void*, A0, A1)) { new (this) Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to Callback(func, arg) */ MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to Callback(func, arg)") Callback(volatile void *obj, R (*func)(volatile void*, A0, A1)) { new (this) Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to Callback(func, arg) */ MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to Callback(func, arg)") Callback(const volatile void *obj, R (*func)(const volatile void*, A0, A1)) { new (this) Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to Callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to Callback(func, arg)") Callback(T *obj, R (*func)(T*, A0, A1)) { new (this) Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to Callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to Callback(func, arg)") Callback(const T *obj, R (*func)(const T*, A0, A1)) { new (this) Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to Callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to Callback(func, arg)") Callback(volatile T *obj, R (*func)(volatile T*, A0, A1)) { new (this) Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to Callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to Callback(func, arg)") Callback(const volatile T *obj, R (*func)(const volatile T*, A0, A1)) { new (this) Callback(func, obj); } /** Destroy a callback */ ~Callback() { if (_ops) { _ops->dtor(this); } } /** Attach a static function * @param func Static function to attach */ void attach(R (*func)(A0, A1)) { this->~Callback(); new (this) Callback(func); } /** Attach a Callback * @param func The Callback to attach */ void attach(const Callback &func) { this->~Callback(); new (this) Callback(func); } /** Attach a member function * @param obj Pointer to object to invoke member function on * @param method Member function to attach */ template void attach(T *obj, R (T::*method)(A0, A1)) { this->~Callback(); new (this) Callback(obj, method); } /** Attach a member function * @param obj Pointer to object to invoke member function on * @param method Member function to attach */ template void attach(const T *obj, R (T::*method)(A0, A1) const) { this->~Callback(); new (this) Callback(obj, method); } /** Attach a member function * @param obj Pointer to object to invoke member function on * @param method Member function to attach */ template void attach(volatile T *obj, R (T::*method)(A0, A1) volatile) { this->~Callback(); new (this) Callback(obj, method); } /** Attach a member function * @param obj Pointer to object to invoke member function on * @param method Member function to attach */ template void attach(const volatile T *obj, R (T::*method)(A0, A1) const volatile) { this->~Callback(); new (this) Callback(obj, method); } /** Attach a static function with a bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ void attach(R (*func)(void*, A0, A1), void *arg) { this->~Callback(); new (this) Callback(func, arg); } /** Attach a static function with a bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ void attach(R (*func)(const void*, A0, A1), const void *arg) { this->~Callback(); new (this) Callback(func, arg); } /** Attach a static function with a bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ void attach(R (*func)(volatile void*, A0, A1), volatile void *arg) { this->~Callback(); new (this) Callback(func, arg); } /** Attach a static function with a bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ void attach(R (*func)(const volatile void*, A0, A1), const volatile void *arg) { this->~Callback(); new (this) Callback(func, arg); } /** Attach a static function with a bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ template void attach(R (*func)(T*, A0, A1), T *arg) { this->~Callback(); new (this) Callback(func, arg); } /** Attach a static function with a bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ template void attach(R (*func)(const T*, A0, A1), const T *arg) { this->~Callback(); new (this) Callback(func, arg); } /** Attach a static function with a bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ template void attach(R (*func)(volatile T*, A0, A1), volatile T *arg) { this->~Callback(); new (this) Callback(func, arg); } /** Attach a static function with a bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ template void attach(R (*func)(const volatile T*, A0, A1), const volatile T *arg) { this->~Callback(); new (this) Callback(func, arg); } /** Attach a function object * @param func Function object to attach * @note The function object is limited to a single word of storage */ template void attach(F f, typename detail::enable_if< detail::is_type::value && sizeof(F) <= sizeof(uintptr_t) >::type = detail::nil()) { this->~Callback(); new (this) Callback(f); } /** Attach a function object * @param func Function object to attach * @note The function object is limited to a single word of storage */ template void attach(const F f, typename detail::enable_if< detail::is_type::value && sizeof(F) <= sizeof(uintptr_t) >::type = detail::nil()) { this->~Callback(); new (this) Callback(f); } /** Attach a function object * @param func Function object to attach * @note The function object is limited to a single word of storage */ template void attach(volatile F f, typename detail::enable_if< detail::is_type::value && sizeof(F) <= sizeof(uintptr_t) >::type = detail::nil()) { this->~Callback(); new (this) Callback(f); } /** Attach a function object * @param func Function object to attach * @note The function object is limited to a single word of storage */ template void attach(const volatile F f, typename detail::enable_if< detail::is_type::value && sizeof(F) <= sizeof(uintptr_t) >::type = detail::nil()) { this->~Callback(); new (this) Callback(f); } /** Attach a static function with a bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach * @deprecated * Arguments to callback have been reordered to attach(func, arg) */ MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to attach(func, arg)") void attach(void *obj, R (*func)(void*, A0, A1)) { this->~Callback(); new (this) Callback(func, obj); } /** Attach a static function with a bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach * @deprecated * Arguments to callback have been reordered to attach(func, arg) */ MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to attach(func, arg)") void attach(const void *obj, R (*func)(const void*, A0, A1)) { this->~Callback(); new (this) Callback(func, obj); } /** Attach a static function with a bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach * @deprecated * Arguments to callback have been reordered to attach(func, arg) */ MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to attach(func, arg)") void attach(volatile void *obj, R (*func)(volatile void*, A0, A1)) { this->~Callback(); new (this) Callback(func, obj); } /** Attach a static function with a bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach * @deprecated * Arguments to callback have been reordered to attach(func, arg) */ MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to attach(func, arg)") void attach(const volatile void *obj, R (*func)(const volatile void*, A0, A1)) { this->~Callback(); new (this) Callback(func, obj); } /** Attach a static function with a bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach * @deprecated * Arguments to callback have been reordered to attach(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to attach(func, arg)") void attach(T *obj, R (*func)(T*, A0, A1)) { this->~Callback(); new (this) Callback(func, obj); } /** Attach a static function with a bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach * @deprecated * Arguments to callback have been reordered to attach(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to attach(func, arg)") void attach(const T *obj, R (*func)(const T*, A0, A1)) { this->~Callback(); new (this) Callback(func, obj); } /** Attach a static function with a bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach * @deprecated * Arguments to callback have been reordered to attach(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to attach(func, arg)") void attach(volatile T *obj, R (*func)(volatile T*, A0, A1)) { this->~Callback(); new (this) Callback(func, obj); } /** Attach a static function with a bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach * @deprecated * Arguments to callback have been reordered to attach(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to attach(func, arg)") void attach(const volatile T *obj, R (*func)(const volatile T*, A0, A1)) { this->~Callback(); new (this) Callback(func, obj); } /** Assign a callback */ Callback &operator=(const Callback &that) { if (this != &that) { this->~Callback(); new (this) Callback(that); } return *this; } /** Call the attached function */ R call(A0 a0, A1 a1) const { MBED_ASSERT(_ops); return _ops->call(this, 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 _ops; } /** 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(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)(A0, A1); void (*_boundfunc)(_class*, A0, A1); void (_class::*_methodfunc)(A0, A1); } _func; void *_obj; // Dynamically dispatched operations const struct ops { R (*call)(const void*, A0, A1); void (*move)(void*, const void*); void (*dtor)(void*); } *_ops; // Generate operations for function object template void generate(const F &f) { struct local { static R call(const void *p, A0 a0, A1 a1) { return (*(F*)p)(a0, a1); } static void move(void *d, const void *p) { new (d) F(*(F*)p); } static void dtor(void *p) { ((F*)p)->~F(); } }; static const ops ops = { &local::call, &local::move, &local::dtor, }; MBED_ASSERT(sizeof(Callback) - sizeof(_ops) >= sizeof(F)); new (this) F(f); _ops = &ops; } // Wrappers for functions with context template struct method_context { M method; O *obj; method_context(O *obj, M method) : method(method), obj(obj) {} R operator()(A0 a0, A1 a1) const { return (obj->*method)(a0, a1); } }; template struct function_context { F func; A *arg; function_context(F func, A *arg) : func(func), arg(arg) {} R operator()(A0 a0, A1 a1) const { return func(arg, a0, a1); } }; }; /** Callback class based on template specialization * * @Note Synchronization level: Not protected */ template class Callback { public: /** Create a Callback with a static function * @param func Static function to attach */ Callback(R (*func)(A0, A1, A2) = 0) { if (!func) { _ops = 0; } else { generate(func); } } /** Attach a Callback * @param func The Callback to attach */ Callback(const Callback &func) { if (func._ops) { func._ops->move(this, &func); } _ops = func._ops; } /** Create a Callback with a member function * @param obj Pointer to object to invoke member function on * @param method Member function to attach */ template Callback(T *obj, R (T::*method)(A0, A1, A2)) { generate(method_context(obj, method)); } /** Create a Callback with a member function * @param obj Pointer to object to invoke member function on * @param method Member function to attach */ template Callback(const T *obj, R (T::*method)(A0, A1, A2) const) { generate(method_context(obj, method)); } /** Create a Callback with a member function * @param obj Pointer to object to invoke member function on * @param method Member function to attach */ template Callback(volatile T *obj, R (T::*method)(A0, A1, A2) volatile) { generate(method_context(obj, method)); } /** Create a Callback with a member function * @param obj Pointer to object to invoke member function on * @param method Member function to attach */ template Callback(const volatile T *obj, R (T::*method)(A0, A1, A2) const volatile) { generate(method_context(obj, method)); } /** Create a Callback with a static function and bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ Callback(R (*func)(void*, A0, A1, A2), void *arg) { generate(function_context(func, arg)); } /** Create a Callback with a static function and bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ Callback(R (*func)(const void*, A0, A1, A2), const void *arg) { generate(function_context(func, arg)); } /** Create a Callback with a static function and bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ Callback(R (*func)(volatile void*, A0, A1, A2), volatile void *arg) { generate(function_context(func, arg)); } /** Create a Callback with a static function and bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ Callback(R (*func)(const volatile void*, A0, A1, A2), const volatile void *arg) { generate(function_context(func, arg)); } /** Create a Callback with a static function and bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ template Callback(R (*func)(T*, A0, A1, A2), T *arg) { generate(function_context(func, arg)); } /** Create a Callback with a static function and bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ template Callback(R (*func)(const T*, A0, A1, A2), const T *arg) { generate(function_context(func, arg)); } /** Create a Callback with a static function and bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ template Callback(R (*func)(volatile T*, A0, A1, A2), volatile T *arg) { generate(function_context(func, arg)); } /** Create a Callback with a static function and bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ template Callback(R (*func)(const volatile T*, A0, A1, A2), const volatile T *arg) { generate(function_context(func, arg)); } /** Create a Callback with a function object * @param func Function object to attach * @note The function object is limited to a single word of storage */ template Callback(F f, typename detail::enable_if< detail::is_type::value && sizeof(F) <= sizeof(uintptr_t) >::type = detail::nil()) { generate(f); } /** Create a Callback with a function object * @param func Function object to attach * @note The function object is limited to a single word of storage */ template Callback(const F f, typename detail::enable_if< detail::is_type::value && sizeof(F) <= sizeof(uintptr_t) >::type = detail::nil()) { generate(f); } /** Create a Callback with a function object * @param func Function object to attach * @note The function object is limited to a single word of storage */ template Callback(volatile F f, typename detail::enable_if< detail::is_type::value && sizeof(F) <= sizeof(uintptr_t) >::type = detail::nil()) { generate(f); } /** Create a Callback with a function object * @param func Function object to attach * @note The function object is limited to a single word of storage */ template Callback(const volatile F f, typename detail::enable_if< detail::is_type::value && sizeof(F) <= sizeof(uintptr_t) >::type = detail::nil()) { generate(f); } /** 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 * @deprecated * Arguments to callback have been reordered to Callback(func, arg) */ MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to Callback(func, arg)") Callback(void *obj, R (*func)(void*, A0, A1, A2)) { new (this) Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to Callback(func, arg) */ MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to Callback(func, arg)") Callback(const void *obj, R (*func)(const void*, A0, A1, A2)) { new (this) Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to Callback(func, arg) */ MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to Callback(func, arg)") Callback(volatile void *obj, R (*func)(volatile void*, A0, A1, A2)) { new (this) Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to Callback(func, arg) */ MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to Callback(func, arg)") Callback(const volatile void *obj, R (*func)(const volatile void*, A0, A1, A2)) { new (this) Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to Callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to Callback(func, arg)") Callback(T *obj, R (*func)(T*, A0, A1, A2)) { new (this) Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to Callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to Callback(func, arg)") Callback(const T *obj, R (*func)(const T*, A0, A1, A2)) { new (this) Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to Callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to Callback(func, arg)") Callback(volatile T *obj, R (*func)(volatile T*, A0, A1, A2)) { new (this) Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to Callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to Callback(func, arg)") Callback(const volatile T *obj, R (*func)(const volatile T*, A0, A1, A2)) { new (this) Callback(func, obj); } /** Destroy a callback */ ~Callback() { if (_ops) { _ops->dtor(this); } } /** Attach a static function * @param func Static function to attach */ void attach(R (*func)(A0, A1, A2)) { this->~Callback(); new (this) Callback(func); } /** Attach a Callback * @param func The Callback to attach */ void attach(const Callback &func) { this->~Callback(); new (this) Callback(func); } /** Attach a member function * @param obj Pointer to object to invoke member function on * @param method Member function to attach */ template void attach(T *obj, R (T::*method)(A0, A1, A2)) { this->~Callback(); new (this) Callback(obj, method); } /** Attach a member function * @param obj Pointer to object to invoke member function on * @param method Member function to attach */ template void attach(const T *obj, R (T::*method)(A0, A1, A2) const) { this->~Callback(); new (this) Callback(obj, method); } /** Attach a member function * @param obj Pointer to object to invoke member function on * @param method Member function to attach */ template void attach(volatile T *obj, R (T::*method)(A0, A1, A2) volatile) { this->~Callback(); new (this) Callback(obj, method); } /** Attach a member function * @param obj Pointer to object to invoke member function on * @param method Member function to attach */ template void attach(const volatile T *obj, R (T::*method)(A0, A1, A2) const volatile) { this->~Callback(); new (this) Callback(obj, method); } /** Attach a static function with a bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ void attach(R (*func)(void*, A0, A1, A2), void *arg) { this->~Callback(); new (this) Callback(func, arg); } /** Attach a static function with a bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ void attach(R (*func)(const void*, A0, A1, A2), const void *arg) { this->~Callback(); new (this) Callback(func, arg); } /** Attach a static function with a bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ void attach(R (*func)(volatile void*, A0, A1, A2), volatile void *arg) { this->~Callback(); new (this) Callback(func, arg); } /** Attach a static function with a bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ void attach(R (*func)(const volatile void*, A0, A1, A2), const volatile void *arg) { this->~Callback(); new (this) Callback(func, arg); } /** Attach a static function with a bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ template void attach(R (*func)(T*, A0, A1, A2), T *arg) { this->~Callback(); new (this) Callback(func, arg); } /** Attach a static function with a bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ template void attach(R (*func)(const T*, A0, A1, A2), const T *arg) { this->~Callback(); new (this) Callback(func, arg); } /** Attach a static function with a bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ template void attach(R (*func)(volatile T*, A0, A1, A2), volatile T *arg) { this->~Callback(); new (this) Callback(func, arg); } /** Attach a static function with a bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ template void attach(R (*func)(const volatile T*, A0, A1, A2), const volatile T *arg) { this->~Callback(); new (this) Callback(func, arg); } /** Attach a function object * @param func Function object to attach * @note The function object is limited to a single word of storage */ template void attach(F f, typename detail::enable_if< detail::is_type::value && sizeof(F) <= sizeof(uintptr_t) >::type = detail::nil()) { this->~Callback(); new (this) Callback(f); } /** Attach a function object * @param func Function object to attach * @note The function object is limited to a single word of storage */ template void attach(const F f, typename detail::enable_if< detail::is_type::value && sizeof(F) <= sizeof(uintptr_t) >::type = detail::nil()) { this->~Callback(); new (this) Callback(f); } /** Attach a function object * @param func Function object to attach * @note The function object is limited to a single word of storage */ template void attach(volatile F f, typename detail::enable_if< detail::is_type::value && sizeof(F) <= sizeof(uintptr_t) >::type = detail::nil()) { this->~Callback(); new (this) Callback(f); } /** Attach a function object * @param func Function object to attach * @note The function object is limited to a single word of storage */ template void attach(const volatile F f, typename detail::enable_if< detail::is_type::value && sizeof(F) <= sizeof(uintptr_t) >::type = detail::nil()) { this->~Callback(); new (this) Callback(f); } /** Attach a static function with a bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach * @deprecated * Arguments to callback have been reordered to attach(func, arg) */ MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to attach(func, arg)") void attach(void *obj, R (*func)(void*, A0, A1, A2)) { this->~Callback(); new (this) Callback(func, obj); } /** Attach a static function with a bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach * @deprecated * Arguments to callback have been reordered to attach(func, arg) */ MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to attach(func, arg)") void attach(const void *obj, R (*func)(const void*, A0, A1, A2)) { this->~Callback(); new (this) Callback(func, obj); } /** Attach a static function with a bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach * @deprecated * Arguments to callback have been reordered to attach(func, arg) */ MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to attach(func, arg)") void attach(volatile void *obj, R (*func)(volatile void*, A0, A1, A2)) { this->~Callback(); new (this) Callback(func, obj); } /** Attach a static function with a bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach * @deprecated * Arguments to callback have been reordered to attach(func, arg) */ MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to attach(func, arg)") void attach(const volatile void *obj, R (*func)(const volatile void*, A0, A1, A2)) { this->~Callback(); new (this) Callback(func, obj); } /** Attach a static function with a bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach * @deprecated * Arguments to callback have been reordered to attach(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to attach(func, arg)") void attach(T *obj, R (*func)(T*, A0, A1, A2)) { this->~Callback(); new (this) Callback(func, obj); } /** Attach a static function with a bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach * @deprecated * Arguments to callback have been reordered to attach(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to attach(func, arg)") void attach(const T *obj, R (*func)(const T*, A0, A1, A2)) { this->~Callback(); new (this) Callback(func, obj); } /** Attach a static function with a bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach * @deprecated * Arguments to callback have been reordered to attach(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to attach(func, arg)") void attach(volatile T *obj, R (*func)(volatile T*, A0, A1, A2)) { this->~Callback(); new (this) Callback(func, obj); } /** Attach a static function with a bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach * @deprecated * Arguments to callback have been reordered to attach(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to attach(func, arg)") void attach(const volatile T *obj, R (*func)(const volatile T*, A0, A1, A2)) { this->~Callback(); new (this) Callback(func, obj); } /** Assign a callback */ Callback &operator=(const Callback &that) { if (this != &that) { this->~Callback(); new (this) Callback(that); } return *this; } /** Call the attached function */ R call(A0 a0, A1 a1, A2 a2) const { MBED_ASSERT(_ops); return _ops->call(this, 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 _ops; } /** 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(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)(A0, A1, A2); void (*_boundfunc)(_class*, A0, A1, A2); void (_class::*_methodfunc)(A0, A1, A2); } _func; void *_obj; // Dynamically dispatched operations const struct ops { R (*call)(const void*, A0, A1, A2); void (*move)(void*, const void*); void (*dtor)(void*); } *_ops; // Generate operations for function object template void generate(const F &f) { struct local { static R call(const void *p, A0 a0, A1 a1, A2 a2) { return (*(F*)p)(a0, a1, a2); } static void move(void *d, const void *p) { new (d) F(*(F*)p); } static void dtor(void *p) { ((F*)p)->~F(); } }; static const ops ops = { &local::call, &local::move, &local::dtor, }; MBED_ASSERT(sizeof(Callback) - sizeof(_ops) >= sizeof(F)); new (this) F(f); _ops = &ops; } // Wrappers for functions with context template struct method_context { M method; O *obj; method_context(O *obj, M method) : method(method), obj(obj) {} R operator()(A0 a0, A1 a1, A2 a2) const { return (obj->*method)(a0, a1, a2); } }; template struct function_context { F func; A *arg; function_context(F func, A *arg) : func(func), arg(arg) {} R operator()(A0 a0, A1 a1, A2 a2) const { return func(arg, a0, a1, a2); } }; }; /** Callback class based on template specialization * * @Note Synchronization level: Not protected */ template class Callback { public: /** Create a Callback with a static function * @param func Static function to attach */ Callback(R (*func)(A0, A1, A2, A3) = 0) { if (!func) { _ops = 0; } else { generate(func); } } /** Attach a Callback * @param func The Callback to attach */ Callback(const Callback &func) { if (func._ops) { func._ops->move(this, &func); } _ops = func._ops; } /** Create a Callback with a member function * @param obj Pointer to object to invoke member function on * @param method Member function to attach */ template Callback(T *obj, R (T::*method)(A0, A1, A2, A3)) { generate(method_context(obj, method)); } /** Create a Callback with a member function * @param obj Pointer to object to invoke member function on * @param method Member function to attach */ template Callback(const T *obj, R (T::*method)(A0, A1, A2, A3) const) { generate(method_context(obj, method)); } /** Create a Callback with a member function * @param obj Pointer to object to invoke member function on * @param method Member function to attach */ template Callback(volatile T *obj, R (T::*method)(A0, A1, A2, A3) volatile) { generate(method_context(obj, method)); } /** Create a Callback with a member function * @param obj Pointer to object to invoke member function on * @param method Member function to attach */ template Callback(const volatile T *obj, R (T::*method)(A0, A1, A2, A3) const volatile) { generate(method_context(obj, method)); } /** Create a Callback with a static function and bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ Callback(R (*func)(void*, A0, A1, A2, A3), void *arg) { generate(function_context(func, arg)); } /** Create a Callback with a static function and bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ Callback(R (*func)(const void*, A0, A1, A2, A3), const void *arg) { generate(function_context(func, arg)); } /** Create a Callback with a static function and bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ Callback(R (*func)(volatile void*, A0, A1, A2, A3), volatile void *arg) { generate(function_context(func, arg)); } /** Create a Callback with a static function and bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ Callback(R (*func)(const volatile void*, A0, A1, A2, A3), const volatile void *arg) { generate(function_context(func, arg)); } /** Create a Callback with a static function and bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ template Callback(R (*func)(T*, A0, A1, A2, A3), T *arg) { generate(function_context(func, arg)); } /** Create a Callback with a static function and bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ template Callback(R (*func)(const T*, A0, A1, A2, A3), const T *arg) { generate(function_context(func, arg)); } /** Create a Callback with a static function and bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ template Callback(R (*func)(volatile T*, A0, A1, A2, A3), volatile T *arg) { generate(function_context(func, arg)); } /** Create a Callback with a static function and bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ template Callback(R (*func)(const volatile T*, A0, A1, A2, A3), const volatile T *arg) { generate(function_context(func, arg)); } /** Create a Callback with a function object * @param func Function object to attach * @note The function object is limited to a single word of storage */ template Callback(F f, typename detail::enable_if< detail::is_type::value && sizeof(F) <= sizeof(uintptr_t) >::type = detail::nil()) { generate(f); } /** Create a Callback with a function object * @param func Function object to attach * @note The function object is limited to a single word of storage */ template Callback(const F f, typename detail::enable_if< detail::is_type::value && sizeof(F) <= sizeof(uintptr_t) >::type = detail::nil()) { generate(f); } /** Create a Callback with a function object * @param func Function object to attach * @note The function object is limited to a single word of storage */ template Callback(volatile F f, typename detail::enable_if< detail::is_type::value && sizeof(F) <= sizeof(uintptr_t) >::type = detail::nil()) { generate(f); } /** Create a Callback with a function object * @param func Function object to attach * @note The function object is limited to a single word of storage */ template Callback(const volatile F f, typename detail::enable_if< detail::is_type::value && sizeof(F) <= sizeof(uintptr_t) >::type = detail::nil()) { generate(f); } /** 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 * @deprecated * Arguments to callback have been reordered to Callback(func, arg) */ MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to Callback(func, arg)") Callback(void *obj, R (*func)(void*, A0, A1, A2, A3)) { new (this) Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to Callback(func, arg) */ MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to Callback(func, arg)") Callback(const void *obj, R (*func)(const void*, A0, A1, A2, A3)) { new (this) Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to Callback(func, arg) */ MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to Callback(func, arg)") Callback(volatile void *obj, R (*func)(volatile void*, A0, A1, A2, A3)) { new (this) Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to Callback(func, arg) */ MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to Callback(func, arg)") Callback(const volatile void *obj, R (*func)(const volatile void*, A0, A1, A2, A3)) { new (this) Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to Callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to Callback(func, arg)") Callback(T *obj, R (*func)(T*, A0, A1, A2, A3)) { new (this) Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to Callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to Callback(func, arg)") Callback(const T *obj, R (*func)(const T*, A0, A1, A2, A3)) { new (this) Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to Callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to Callback(func, arg)") Callback(volatile T *obj, R (*func)(volatile T*, A0, A1, A2, A3)) { new (this) Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to Callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to Callback(func, arg)") Callback(const volatile T *obj, R (*func)(const volatile T*, A0, A1, A2, A3)) { new (this) Callback(func, obj); } /** Destroy a callback */ ~Callback() { if (_ops) { _ops->dtor(this); } } /** Attach a static function * @param func Static function to attach */ void attach(R (*func)(A0, A1, A2, A3)) { this->~Callback(); new (this) Callback(func); } /** Attach a Callback * @param func The Callback to attach */ void attach(const Callback &func) { this->~Callback(); new (this) Callback(func); } /** Attach a member function * @param obj Pointer to object to invoke member function on * @param method Member function to attach */ template void attach(T *obj, R (T::*method)(A0, A1, A2, A3)) { this->~Callback(); new (this) Callback(obj, method); } /** Attach a member function * @param obj Pointer to object to invoke member function on * @param method Member function to attach */ template void attach(const T *obj, R (T::*method)(A0, A1, A2, A3) const) { this->~Callback(); new (this) Callback(obj, method); } /** Attach a member function * @param obj Pointer to object to invoke member function on * @param method Member function to attach */ template void attach(volatile T *obj, R (T::*method)(A0, A1, A2, A3) volatile) { this->~Callback(); new (this) Callback(obj, method); } /** Attach a member function * @param obj Pointer to object to invoke member function on * @param method Member function to attach */ template void attach(const volatile T *obj, R (T::*method)(A0, A1, A2, A3) const volatile) { this->~Callback(); new (this) Callback(obj, method); } /** Attach a static function with a bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ void attach(R (*func)(void*, A0, A1, A2, A3), void *arg) { this->~Callback(); new (this) Callback(func, arg); } /** Attach a static function with a bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ void attach(R (*func)(const void*, A0, A1, A2, A3), const void *arg) { this->~Callback(); new (this) Callback(func, arg); } /** Attach a static function with a bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ void attach(R (*func)(volatile void*, A0, A1, A2, A3), volatile void *arg) { this->~Callback(); new (this) Callback(func, arg); } /** Attach a static function with a bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ void attach(R (*func)(const volatile void*, A0, A1, A2, A3), const volatile void *arg) { this->~Callback(); new (this) Callback(func, arg); } /** Attach a static function with a bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ template void attach(R (*func)(T*, A0, A1, A2, A3), T *arg) { this->~Callback(); new (this) Callback(func, arg); } /** Attach a static function with a bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ template void attach(R (*func)(const T*, A0, A1, A2, A3), const T *arg) { this->~Callback(); new (this) Callback(func, arg); } /** Attach a static function with a bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ template void attach(R (*func)(volatile T*, A0, A1, A2, A3), volatile T *arg) { this->~Callback(); new (this) Callback(func, arg); } /** Attach a static function with a bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ template void attach(R (*func)(const volatile T*, A0, A1, A2, A3), const volatile T *arg) { this->~Callback(); new (this) Callback(func, arg); } /** Attach a function object * @param func Function object to attach * @note The function object is limited to a single word of storage */ template void attach(F f, typename detail::enable_if< detail::is_type::value && sizeof(F) <= sizeof(uintptr_t) >::type = detail::nil()) { this->~Callback(); new (this) Callback(f); } /** Attach a function object * @param func Function object to attach * @note The function object is limited to a single word of storage */ template void attach(const F f, typename detail::enable_if< detail::is_type::value && sizeof(F) <= sizeof(uintptr_t) >::type = detail::nil()) { this->~Callback(); new (this) Callback(f); } /** Attach a function object * @param func Function object to attach * @note The function object is limited to a single word of storage */ template void attach(volatile F f, typename detail::enable_if< detail::is_type::value && sizeof(F) <= sizeof(uintptr_t) >::type = detail::nil()) { this->~Callback(); new (this) Callback(f); } /** Attach a function object * @param func Function object to attach * @note The function object is limited to a single word of storage */ template void attach(const volatile F f, typename detail::enable_if< detail::is_type::value && sizeof(F) <= sizeof(uintptr_t) >::type = detail::nil()) { this->~Callback(); new (this) Callback(f); } /** Attach a static function with a bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach * @deprecated * Arguments to callback have been reordered to attach(func, arg) */ MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to attach(func, arg)") void attach(void *obj, R (*func)(void*, A0, A1, A2, A3)) { this->~Callback(); new (this) Callback(func, obj); } /** Attach a static function with a bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach * @deprecated * Arguments to callback have been reordered to attach(func, arg) */ MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to attach(func, arg)") void attach(const void *obj, R (*func)(const void*, A0, A1, A2, A3)) { this->~Callback(); new (this) Callback(func, obj); } /** Attach a static function with a bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach * @deprecated * Arguments to callback have been reordered to attach(func, arg) */ MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to attach(func, arg)") void attach(volatile void *obj, R (*func)(volatile void*, A0, A1, A2, A3)) { this->~Callback(); new (this) Callback(func, obj); } /** Attach a static function with a bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach * @deprecated * Arguments to callback have been reordered to attach(func, arg) */ MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to attach(func, arg)") void attach(const volatile void *obj, R (*func)(const volatile void*, A0, A1, A2, A3)) { this->~Callback(); new (this) Callback(func, obj); } /** Attach a static function with a bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach * @deprecated * Arguments to callback have been reordered to attach(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to attach(func, arg)") void attach(T *obj, R (*func)(T*, A0, A1, A2, A3)) { this->~Callback(); new (this) Callback(func, obj); } /** Attach a static function with a bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach * @deprecated * Arguments to callback have been reordered to attach(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to attach(func, arg)") void attach(const T *obj, R (*func)(const T*, A0, A1, A2, A3)) { this->~Callback(); new (this) Callback(func, obj); } /** Attach a static function with a bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach * @deprecated * Arguments to callback have been reordered to attach(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to attach(func, arg)") void attach(volatile T *obj, R (*func)(volatile T*, A0, A1, A2, A3)) { this->~Callback(); new (this) Callback(func, obj); } /** Attach a static function with a bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach * @deprecated * Arguments to callback have been reordered to attach(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to attach(func, arg)") void attach(const volatile T *obj, R (*func)(const volatile T*, A0, A1, A2, A3)) { this->~Callback(); new (this) Callback(func, obj); } /** Assign a callback */ Callback &operator=(const Callback &that) { if (this != &that) { this->~Callback(); new (this) Callback(that); } return *this; } /** Call the attached function */ R call(A0 a0, A1 a1, A2 a2, A3 a3) const { MBED_ASSERT(_ops); return _ops->call(this, 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 _ops; } /** 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(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)(A0, A1, A2, A3); void (*_boundfunc)(_class*, A0, A1, A2, A3); void (_class::*_methodfunc)(A0, A1, A2, A3); } _func; void *_obj; // Dynamically dispatched operations const struct ops { R (*call)(const void*, A0, A1, A2, A3); void (*move)(void*, const void*); void (*dtor)(void*); } *_ops; // Generate operations for function object template void generate(const F &f) { struct local { static R call(const void *p, A0 a0, A1 a1, A2 a2, A3 a3) { return (*(F*)p)(a0, a1, a2, a3); } static void move(void *d, const void *p) { new (d) F(*(F*)p); } static void dtor(void *p) { ((F*)p)->~F(); } }; static const ops ops = { &local::call, &local::move, &local::dtor, }; MBED_ASSERT(sizeof(Callback) - sizeof(_ops) >= sizeof(F)); new (this) F(f); _ops = &ops; } // Wrappers for functions with context template struct method_context { M method; O *obj; method_context(O *obj, M method) : method(method), obj(obj) {} R operator()(A0 a0, A1 a1, A2 a2, A3 a3) const { return (obj->*method)(a0, a1, a2, a3); } }; template struct function_context { F func; A *arg; function_context(F func, A *arg) : func(func), arg(arg) {} R operator()(A0 a0, A1 a1, A2 a2, A3 a3) const { return func(arg, a0, a1, a2, a3); } }; }; /** Callback class based on template specialization * * @Note Synchronization level: Not protected */ template class Callback { public: /** Create a Callback with a static function * @param func Static function to attach */ Callback(R (*func)(A0, A1, A2, A3, A4) = 0) { if (!func) { _ops = 0; } else { generate(func); } } /** Attach a Callback * @param func The Callback to attach */ Callback(const Callback &func) { if (func._ops) { func._ops->move(this, &func); } _ops = func._ops; } /** Create a Callback with a member function * @param obj Pointer to object to invoke member function on * @param method Member function to attach */ template Callback(T *obj, R (T::*method)(A0, A1, A2, A3, A4)) { generate(method_context(obj, method)); } /** Create a Callback with a member function * @param obj Pointer to object to invoke member function on * @param method Member function to attach */ template Callback(const T *obj, R (T::*method)(A0, A1, A2, A3, A4) const) { generate(method_context(obj, method)); } /** Create a Callback with a member function * @param obj Pointer to object to invoke member function on * @param method Member function to attach */ template Callback(volatile T *obj, R (T::*method)(A0, A1, A2, A3, A4) volatile) { generate(method_context(obj, method)); } /** Create a Callback with a member function * @param obj Pointer to object to invoke member function on * @param method Member function to attach */ template Callback(const volatile T *obj, R (T::*method)(A0, A1, A2, A3, A4) const volatile) { generate(method_context(obj, method)); } /** Create a Callback with a static function and bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ Callback(R (*func)(void*, A0, A1, A2, A3, A4), void *arg) { generate(function_context(func, arg)); } /** Create a Callback with a static function and bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ Callback(R (*func)(const void*, A0, A1, A2, A3, A4), const void *arg) { generate(function_context(func, arg)); } /** Create a Callback with a static function and bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ Callback(R (*func)(volatile void*, A0, A1, A2, A3, A4), volatile void *arg) { generate(function_context(func, arg)); } /** Create a Callback with a static function and bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ Callback(R (*func)(const volatile void*, A0, A1, A2, A3, A4), const volatile void *arg) { generate(function_context(func, arg)); } /** Create a Callback with a static function and bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ template Callback(R (*func)(T*, A0, A1, A2, A3, A4), T *arg) { generate(function_context(func, arg)); } /** Create a Callback with a static function and bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ template Callback(R (*func)(const T*, A0, A1, A2, A3, A4), const T *arg) { generate(function_context(func, arg)); } /** Create a Callback with a static function and bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ template Callback(R (*func)(volatile T*, A0, A1, A2, A3, A4), volatile T *arg) { generate(function_context(func, arg)); } /** Create a Callback with a static function and bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ template Callback(R (*func)(const volatile T*, A0, A1, A2, A3, A4), const volatile T *arg) { generate(function_context(func, arg)); } /** Create a Callback with a function object * @param func Function object to attach * @note The function object is limited to a single word of storage */ template Callback(F f, typename detail::enable_if< detail::is_type::value && sizeof(F) <= sizeof(uintptr_t) >::type = detail::nil()) { generate(f); } /** Create a Callback with a function object * @param func Function object to attach * @note The function object is limited to a single word of storage */ template Callback(const F f, typename detail::enable_if< detail::is_type::value && sizeof(F) <= sizeof(uintptr_t) >::type = detail::nil()) { generate(f); } /** Create a Callback with a function object * @param func Function object to attach * @note The function object is limited to a single word of storage */ template Callback(volatile F f, typename detail::enable_if< detail::is_type::value && sizeof(F) <= sizeof(uintptr_t) >::type = detail::nil()) { generate(f); } /** Create a Callback with a function object * @param func Function object to attach * @note The function object is limited to a single word of storage */ template Callback(const volatile F f, typename detail::enable_if< detail::is_type::value && sizeof(F) <= sizeof(uintptr_t) >::type = detail::nil()) { generate(f); } /** 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 * @deprecated * Arguments to callback have been reordered to Callback(func, arg) */ MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to Callback(func, arg)") Callback(void *obj, R (*func)(void*, A0, A1, A2, A3, A4)) { new (this) Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to Callback(func, arg) */ MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to Callback(func, arg)") Callback(const void *obj, R (*func)(const void*, A0, A1, A2, A3, A4)) { new (this) Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to Callback(func, arg) */ MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to Callback(func, arg)") Callback(volatile void *obj, R (*func)(volatile void*, A0, A1, A2, A3, A4)) { new (this) Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to Callback(func, arg) */ MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to Callback(func, arg)") Callback(const volatile void *obj, R (*func)(const volatile void*, A0, A1, A2, A3, A4)) { new (this) Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to Callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to Callback(func, arg)") Callback(T *obj, R (*func)(T*, A0, A1, A2, A3, A4)) { new (this) Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to Callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to Callback(func, arg)") Callback(const T *obj, R (*func)(const T*, A0, A1, A2, A3, A4)) { new (this) Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to Callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to Callback(func, arg)") Callback(volatile T *obj, R (*func)(volatile T*, A0, A1, A2, A3, A4)) { new (this) Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to Callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to Callback(func, arg)") Callback(const volatile T *obj, R (*func)(const volatile T*, A0, A1, A2, A3, A4)) { new (this) Callback(func, obj); } /** Destroy a callback */ ~Callback() { if (_ops) { _ops->dtor(this); } } /** Attach a static function * @param func Static function to attach */ void attach(R (*func)(A0, A1, A2, A3, A4)) { this->~Callback(); new (this) Callback(func); } /** Attach a Callback * @param func The Callback to attach */ void attach(const Callback &func) { this->~Callback(); new (this) Callback(func); } /** Attach a member function * @param obj Pointer to object to invoke member function on * @param method Member function to attach */ template void attach(T *obj, R (T::*method)(A0, A1, A2, A3, A4)) { this->~Callback(); new (this) Callback(obj, method); } /** Attach a member function * @param obj Pointer to object to invoke member function on * @param method Member function to attach */ template void attach(const T *obj, R (T::*method)(A0, A1, A2, A3, A4) const) { this->~Callback(); new (this) Callback(obj, method); } /** Attach a member function * @param obj Pointer to object to invoke member function on * @param method Member function to attach */ template void attach(volatile T *obj, R (T::*method)(A0, A1, A2, A3, A4) volatile) { this->~Callback(); new (this) Callback(obj, method); } /** Attach a member function * @param obj Pointer to object to invoke member function on * @param method Member function to attach */ template void attach(const volatile T *obj, R (T::*method)(A0, A1, A2, A3, A4) const volatile) { this->~Callback(); new (this) Callback(obj, method); } /** Attach a static function with a bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ void attach(R (*func)(void*, A0, A1, A2, A3, A4), void *arg) { this->~Callback(); new (this) Callback(func, arg); } /** Attach a static function with a bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ void attach(R (*func)(const void*, A0, A1, A2, A3, A4), const void *arg) { this->~Callback(); new (this) Callback(func, arg); } /** Attach a static function with a bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ void attach(R (*func)(volatile void*, A0, A1, A2, A3, A4), volatile void *arg) { this->~Callback(); new (this) Callback(func, arg); } /** Attach a static function with a bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ void attach(R (*func)(const volatile void*, A0, A1, A2, A3, A4), const volatile void *arg) { this->~Callback(); new (this) Callback(func, arg); } /** Attach a static function with a bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ template void attach(R (*func)(T*, A0, A1, A2, A3, A4), T *arg) { this->~Callback(); new (this) Callback(func, arg); } /** Attach a static function with a bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ template void attach(R (*func)(const T*, A0, A1, A2, A3, A4), const T *arg) { this->~Callback(); new (this) Callback(func, arg); } /** Attach a static function with a bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ template void attach(R (*func)(volatile T*, A0, A1, A2, A3, A4), volatile T *arg) { this->~Callback(); new (this) Callback(func, arg); } /** Attach a static function with a bound pointer * @param func Static function to attach * @param arg Pointer argument to function */ template void attach(R (*func)(const volatile T*, A0, A1, A2, A3, A4), const volatile T *arg) { this->~Callback(); new (this) Callback(func, arg); } /** Attach a function object * @param func Function object to attach * @note The function object is limited to a single word of storage */ template void attach(F f, typename detail::enable_if< detail::is_type::value && sizeof(F) <= sizeof(uintptr_t) >::type = detail::nil()) { this->~Callback(); new (this) Callback(f); } /** Attach a function object * @param func Function object to attach * @note The function object is limited to a single word of storage */ template void attach(const F f, typename detail::enable_if< detail::is_type::value && sizeof(F) <= sizeof(uintptr_t) >::type = detail::nil()) { this->~Callback(); new (this) Callback(f); } /** Attach a function object * @param func Function object to attach * @note The function object is limited to a single word of storage */ template void attach(volatile F f, typename detail::enable_if< detail::is_type::value && sizeof(F) <= sizeof(uintptr_t) >::type = detail::nil()) { this->~Callback(); new (this) Callback(f); } /** Attach a function object * @param func Function object to attach * @note The function object is limited to a single word of storage */ template void attach(const volatile F f, typename detail::enable_if< detail::is_type::value && sizeof(F) <= sizeof(uintptr_t) >::type = detail::nil()) { this->~Callback(); new (this) Callback(f); } /** Attach a static function with a bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach * @deprecated * Arguments to callback have been reordered to attach(func, arg) */ MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to attach(func, arg)") void attach(void *obj, R (*func)(void*, A0, A1, A2, A3, A4)) { this->~Callback(); new (this) Callback(func, obj); } /** Attach a static function with a bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach * @deprecated * Arguments to callback have been reordered to attach(func, arg) */ MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to attach(func, arg)") void attach(const void *obj, R (*func)(const void*, A0, A1, A2, A3, A4)) { this->~Callback(); new (this) Callback(func, obj); } /** Attach a static function with a bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach * @deprecated * Arguments to callback have been reordered to attach(func, arg) */ MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to attach(func, arg)") void attach(volatile void *obj, R (*func)(volatile void*, A0, A1, A2, A3, A4)) { this->~Callback(); new (this) Callback(func, obj); } /** Attach a static function with a bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach * @deprecated * Arguments to callback have been reordered to attach(func, arg) */ MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to attach(func, arg)") void attach(const volatile void *obj, R (*func)(const volatile void*, A0, A1, A2, A3, A4)) { this->~Callback(); new (this) Callback(func, obj); } /** Attach a static function with a bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach * @deprecated * Arguments to callback have been reordered to attach(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to attach(func, arg)") void attach(T *obj, R (*func)(T*, A0, A1, A2, A3, A4)) { this->~Callback(); new (this) Callback(func, obj); } /** Attach a static function with a bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach * @deprecated * Arguments to callback have been reordered to attach(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to attach(func, arg)") void attach(const T *obj, R (*func)(const T*, A0, A1, A2, A3, A4)) { this->~Callback(); new (this) Callback(func, obj); } /** Attach a static function with a bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach * @deprecated * Arguments to callback have been reordered to attach(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to attach(func, arg)") void attach(volatile T *obj, R (*func)(volatile T*, A0, A1, A2, A3, A4)) { this->~Callback(); new (this) Callback(func, obj); } /** Attach a static function with a bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach * @deprecated * Arguments to callback have been reordered to attach(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to attach(func, arg)") void attach(const volatile T *obj, R (*func)(const volatile T*, A0, A1, A2, A3, A4)) { this->~Callback(); new (this) Callback(func, obj); } /** Assign a callback */ Callback &operator=(const Callback &that) { if (this != &that) { this->~Callback(); new (this) Callback(that); } return *this; } /** Call the attached function */ R call(A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) const { MBED_ASSERT(_ops); return _ops->call(this, 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 _ops; } /** 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(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)(A0, A1, A2, A3, A4); void (*_boundfunc)(_class*, A0, A1, A2, A3, A4); void (_class::*_methodfunc)(A0, A1, A2, A3, A4); } _func; void *_obj; // Dynamically dispatched operations const struct ops { R (*call)(const void*, A0, A1, A2, A3, A4); void (*move)(void*, const void*); void (*dtor)(void*); } *_ops; // Generate operations for function object template void generate(const F &f) { struct local { static R call(const void *p, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) { return (*(F*)p)(a0, a1, a2, a3, a4); } static void move(void *d, const void *p) { new (d) F(*(F*)p); } static void dtor(void *p) { ((F*)p)->~F(); } }; static const ops ops = { &local::call, &local::move, &local::dtor, }; MBED_ASSERT(sizeof(Callback) - sizeof(_ops) >= sizeof(F)); new (this) F(f); _ops = &ops; } // Wrappers for functions with context template struct method_context { M method; O *obj; method_context(O *obj, M method) : method(method), obj(obj) {} R operator()(A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) const { return (obj->*method)(a0, a1, a2, a3, a4); } }; template struct function_context { F func; A *arg; function_context(F func, A *arg) : func(func), arg(arg) {} R operator()(A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) const { return func(arg, a0, a1, a2, a3, a4); } }; }; // Internally used event type typedef Callback event_callback_t; /** Create a callback class with type infered from the arguments * * @param func Static function to attach * @return Callback with infered type */ template Callback callback(R (*func)() = 0) { return Callback(func); } /** Create a callback class with type infered from the arguments * * @param func Static function to attach * @return Callback with infered type */ template Callback callback(const Callback &func) { return Callback(func); } /** Create a callback class with type infered from the arguments * * @param obj Optional pointer to object to bind to function * @param method Member function to attach * @return Callback with infered type */ template Callback callback(T *obj, R (T::*func)()) { return Callback(obj, func); } /** Create a callback class with type infered from the arguments * * @param obj Optional pointer to object to bind to function * @param method Member function to attach * @return Callback with infered type */ template Callback callback(const T *obj, R (T::*func)() const) { return Callback(obj, func); } /** Create a callback class with type infered from the arguments * * @param obj Optional pointer to object to bind to function * @param method Member function to attach * @return Callback with infered type */ template Callback callback(volatile T *obj, R (T::*func)() volatile) { return Callback(obj, func); } /** Create a callback class with type infered from the arguments * * @param obj Optional pointer to object to bind to function * @param method Member function to attach * @return Callback with infered type */ template Callback callback(const volatile T *obj, R (T::*func)() const volatile) { return Callback(obj, func); } /** Create a callback class with type infered from the arguments * * @param func Static function to attach * @param arg Pointer argument to function * @return Callback with infered type */ template Callback callback(R (*func)(void*), void *arg) { return Callback(func, arg); } /** Create a callback class with type infered from the arguments * * @param func Static function to attach * @param arg Pointer argument to function * @return Callback with infered type */ template Callback callback(R (*func)(const void*), const void *arg) { return Callback(func, arg); } /** Create a callback class with type infered from the arguments * * @param func Static function to attach * @param arg Pointer argument to function * @return Callback with infered type */ template Callback callback(R (*func)(volatile void*), volatile void *arg) { return Callback(func, arg); } /** Create a callback class with type infered from the arguments * * @param func Static function to attach * @param arg Pointer argument to function * @return Callback with infered type */ template Callback callback(R (*func)(const volatile void*), const volatile void *arg) { return Callback(func, arg); } /** Create a callback class with type infered from the arguments * * @param func Static function to attach * @param arg Pointer argument to function * @return Callback with infered type */ template Callback callback(R (*func)(T*), T *arg) { return Callback(func, arg); } /** Create a callback class with type infered from the arguments * * @param func Static function to attach * @param arg Pointer argument to function * @return Callback with infered type */ template Callback callback(R (*func)(const T*), const T *arg) { return Callback(func, arg); } /** Create a callback class with type infered from the arguments * * @param func Static function to attach * @param arg Pointer argument to function * @return Callback with infered type */ template Callback callback(R (*func)(volatile T*), volatile T *arg) { return Callback(func, arg); } /** Create a callback class with type infered from the arguments * * @param func Static function to attach * @param arg Pointer argument to function * @return Callback with infered type */ template Callback callback(R (*func)(const volatile T*), const volatile T *arg) { return Callback(func, arg); } /** 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 * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to callback(func, arg)") Callback callback(void *obj, R (*func)(void*)) { return Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to callback(func, arg)") Callback callback(const void *obj, R (*func)(const void*)) { return Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to callback(func, arg)") Callback callback(volatile void *obj, R (*func)(volatile void*)) { return Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to callback(func, arg)") Callback callback(const volatile void *obj, R (*func)(const volatile void*)) { return Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to callback(func, arg)") Callback callback(T *obj, R (*func)(T*)) { return Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to callback(func, arg)") Callback callback(const T *obj, R (*func)(const T*)) { return Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to callback(func, arg)") Callback callback(volatile T *obj, R (*func)(volatile T*)) { return Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to callback(func, arg)") Callback callback(const volatile T *obj, R (*func)(const volatile T*)) { return Callback(func, obj); } /** Create a callback class with type infered from the arguments * * @param func Static function to attach * @return Callback with infered type */ template Callback callback(R (*func)(A0) = 0) { return Callback(func); } /** Create a callback class with type infered from the arguments * * @param func Static function to attach * @return Callback with infered type */ template Callback callback(const Callback &func) { return Callback(func); } /** Create a callback class with type infered from the arguments * * @param obj Optional pointer to object to bind to function * @param method Member function to attach * @return Callback with infered type */ template Callback callback(T *obj, R (T::*func)(A0)) { return Callback(obj, func); } /** Create a callback class with type infered from the arguments * * @param obj Optional pointer to object to bind to function * @param method Member function to attach * @return Callback with infered type */ template Callback callback(const T *obj, R (T::*func)(A0) const) { return Callback(obj, func); } /** Create a callback class with type infered from the arguments * * @param obj Optional pointer to object to bind to function * @param method Member function to attach * @return Callback with infered type */ template Callback callback(volatile T *obj, R (T::*func)(A0) volatile) { return Callback(obj, func); } /** Create a callback class with type infered from the arguments * * @param obj Optional pointer to object to bind to function * @param method Member function to attach * @return Callback with infered type */ template Callback callback(const volatile T *obj, R (T::*func)(A0) const volatile) { return Callback(obj, func); } /** Create a callback class with type infered from the arguments * * @param func Static function to attach * @param arg Pointer argument to function * @return Callback with infered type */ template Callback callback(R (*func)(void*, A0), void *arg) { return Callback(func, arg); } /** Create a callback class with type infered from the arguments * * @param func Static function to attach * @param arg Pointer argument to function * @return Callback with infered type */ template Callback callback(R (*func)(const void*, A0), const void *arg) { return Callback(func, arg); } /** Create a callback class with type infered from the arguments * * @param func Static function to attach * @param arg Pointer argument to function * @return Callback with infered type */ template Callback callback(R (*func)(volatile void*, A0), volatile void *arg) { return Callback(func, arg); } /** Create a callback class with type infered from the arguments * * @param func Static function to attach * @param arg Pointer argument to function * @return Callback with infered type */ template Callback callback(R (*func)(const volatile void*, A0), const volatile void *arg) { return Callback(func, arg); } /** Create a callback class with type infered from the arguments * * @param func Static function to attach * @param arg Pointer argument to function * @return Callback with infered type */ template Callback callback(R (*func)(T*, A0), T *arg) { return Callback(func, arg); } /** Create a callback class with type infered from the arguments * * @param func Static function to attach * @param arg Pointer argument to function * @return Callback with infered type */ template Callback callback(R (*func)(const T*, A0), const T *arg) { return Callback(func, arg); } /** Create a callback class with type infered from the arguments * * @param func Static function to attach * @param arg Pointer argument to function * @return Callback with infered type */ template Callback callback(R (*func)(volatile T*, A0), volatile T *arg) { return Callback(func, arg); } /** Create a callback class with type infered from the arguments * * @param func Static function to attach * @param arg Pointer argument to function * @return Callback with infered type */ template Callback callback(R (*func)(const volatile T*, A0), const volatile T *arg) { return Callback(func, arg); } /** 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 * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to callback(func, arg)") Callback callback(void *obj, R (*func)(void*, A0)) { return Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to callback(func, arg)") Callback callback(const void *obj, R (*func)(const void*, A0)) { return Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to callback(func, arg)") Callback callback(volatile void *obj, R (*func)(volatile void*, A0)) { return Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to callback(func, arg)") Callback callback(const volatile void *obj, R (*func)(const volatile void*, A0)) { return Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to callback(func, arg)") Callback callback(T *obj, R (*func)(T*, A0)) { return Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to callback(func, arg)") Callback callback(const T *obj, R (*func)(const T*, A0)) { return Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to callback(func, arg)") Callback callback(volatile T *obj, R (*func)(volatile T*, A0)) { return Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to callback(func, arg)") Callback callback(const volatile T *obj, R (*func)(const volatile T*, A0)) { return Callback(func, obj); } /** Create a callback class with type infered from the arguments * * @param func Static function to attach * @return Callback with infered type */ template Callback callback(R (*func)(A0, A1) = 0) { return Callback(func); } /** Create a callback class with type infered from the arguments * * @param func Static function to attach * @return Callback with infered type */ template Callback callback(const Callback &func) { return Callback(func); } /** Create a callback class with type infered from the arguments * * @param obj Optional pointer to object to bind to function * @param method Member function to attach * @return Callback with infered type */ template Callback callback(T *obj, R (T::*func)(A0, A1)) { return Callback(obj, func); } /** Create a callback class with type infered from the arguments * * @param obj Optional pointer to object to bind to function * @param method Member function to attach * @return Callback with infered type */ template Callback callback(const T *obj, R (T::*func)(A0, A1) const) { return Callback(obj, func); } /** Create a callback class with type infered from the arguments * * @param obj Optional pointer to object to bind to function * @param method Member function to attach * @return Callback with infered type */ template Callback callback(volatile T *obj, R (T::*func)(A0, A1) volatile) { return Callback(obj, func); } /** Create a callback class with type infered from the arguments * * @param obj Optional pointer to object to bind to function * @param method Member function to attach * @return Callback with infered type */ template Callback callback(const volatile T *obj, R (T::*func)(A0, A1) const volatile) { return Callback(obj, func); } /** Create a callback class with type infered from the arguments * * @param func Static function to attach * @param arg Pointer argument to function * @return Callback with infered type */ template Callback callback(R (*func)(void*, A0, A1), void *arg) { return Callback(func, arg); } /** Create a callback class with type infered from the arguments * * @param func Static function to attach * @param arg Pointer argument to function * @return Callback with infered type */ template Callback callback(R (*func)(const void*, A0, A1), const void *arg) { return Callback(func, arg); } /** Create a callback class with type infered from the arguments * * @param func Static function to attach * @param arg Pointer argument to function * @return Callback with infered type */ template Callback callback(R (*func)(volatile void*, A0, A1), volatile void *arg) { return Callback(func, arg); } /** Create a callback class with type infered from the arguments * * @param func Static function to attach * @param arg Pointer argument to function * @return Callback with infered type */ template Callback callback(R (*func)(const volatile void*, A0, A1), const volatile void *arg) { return Callback(func, arg); } /** Create a callback class with type infered from the arguments * * @param func Static function to attach * @param arg Pointer argument to function * @return Callback with infered type */ template Callback callback(R (*func)(T*, A0, A1), T *arg) { return Callback(func, arg); } /** Create a callback class with type infered from the arguments * * @param func Static function to attach * @param arg Pointer argument to function * @return Callback with infered type */ template Callback callback(R (*func)(const T*, A0, A1), const T *arg) { return Callback(func, arg); } /** Create a callback class with type infered from the arguments * * @param func Static function to attach * @param arg Pointer argument to function * @return Callback with infered type */ template Callback callback(R (*func)(volatile T*, A0, A1), volatile T *arg) { return Callback(func, arg); } /** Create a callback class with type infered from the arguments * * @param func Static function to attach * @param arg Pointer argument to function * @return Callback with infered type */ template Callback callback(R (*func)(const volatile T*, A0, A1), const volatile T *arg) { return Callback(func, arg); } /** 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 * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to callback(func, arg)") Callback callback(void *obj, R (*func)(void*, A0, A1)) { return Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to callback(func, arg)") Callback callback(const void *obj, R (*func)(const void*, A0, A1)) { return Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to callback(func, arg)") Callback callback(volatile void *obj, R (*func)(volatile void*, A0, A1)) { return Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to callback(func, arg)") Callback callback(const volatile void *obj, R (*func)(const volatile void*, A0, A1)) { return Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to callback(func, arg)") Callback callback(T *obj, R (*func)(T*, A0, A1)) { return Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to callback(func, arg)") Callback callback(const T *obj, R (*func)(const T*, A0, A1)) { return Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to callback(func, arg)") Callback callback(volatile T *obj, R (*func)(volatile T*, A0, A1)) { return Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to callback(func, arg)") Callback callback(const volatile T *obj, R (*func)(const volatile T*, A0, A1)) { return Callback(func, obj); } /** Create a callback class with type infered from the arguments * * @param func Static function to attach * @return Callback with infered type */ template Callback callback(R (*func)(A0, A1, A2) = 0) { return Callback(func); } /** Create a callback class with type infered from the arguments * * @param func Static function to attach * @return Callback with infered type */ template Callback callback(const Callback &func) { return Callback(func); } /** Create a callback class with type infered from the arguments * * @param obj Optional pointer to object to bind to function * @param method Member function to attach * @return Callback with infered type */ template Callback callback(T *obj, R (T::*func)(A0, A1, A2)) { return Callback(obj, func); } /** Create a callback class with type infered from the arguments * * @param obj Optional pointer to object to bind to function * @param method Member function to attach * @return Callback with infered type */ template Callback callback(const T *obj, R (T::*func)(A0, A1, A2) const) { return Callback(obj, func); } /** Create a callback class with type infered from the arguments * * @param obj Optional pointer to object to bind to function * @param method Member function to attach * @return Callback with infered type */ template Callback callback(volatile T *obj, R (T::*func)(A0, A1, A2) volatile) { return Callback(obj, func); } /** Create a callback class with type infered from the arguments * * @param obj Optional pointer to object to bind to function * @param method Member function to attach * @return Callback with infered type */ template Callback callback(const volatile T *obj, R (T::*func)(A0, A1, A2) const volatile) { return Callback(obj, func); } /** Create a callback class with type infered from the arguments * * @param func Static function to attach * @param arg Pointer argument to function * @return Callback with infered type */ template Callback callback(R (*func)(void*, A0, A1, A2), void *arg) { return Callback(func, arg); } /** Create a callback class with type infered from the arguments * * @param func Static function to attach * @param arg Pointer argument to function * @return Callback with infered type */ template Callback callback(R (*func)(const void*, A0, A1, A2), const void *arg) { return Callback(func, arg); } /** Create a callback class with type infered from the arguments * * @param func Static function to attach * @param arg Pointer argument to function * @return Callback with infered type */ template Callback callback(R (*func)(volatile void*, A0, A1, A2), volatile void *arg) { return Callback(func, arg); } /** Create a callback class with type infered from the arguments * * @param func Static function to attach * @param arg Pointer argument to function * @return Callback with infered type */ template Callback callback(R (*func)(const volatile void*, A0, A1, A2), const volatile void *arg) { return Callback(func, arg); } /** Create a callback class with type infered from the arguments * * @param func Static function to attach * @param arg Pointer argument to function * @return Callback with infered type */ template Callback callback(R (*func)(T*, A0, A1, A2), T *arg) { return Callback(func, arg); } /** Create a callback class with type infered from the arguments * * @param func Static function to attach * @param arg Pointer argument to function * @return Callback with infered type */ template Callback callback(R (*func)(const T*, A0, A1, A2), const T *arg) { return Callback(func, arg); } /** Create a callback class with type infered from the arguments * * @param func Static function to attach * @param arg Pointer argument to function * @return Callback with infered type */ template Callback callback(R (*func)(volatile T*, A0, A1, A2), volatile T *arg) { return Callback(func, arg); } /** Create a callback class with type infered from the arguments * * @param func Static function to attach * @param arg Pointer argument to function * @return Callback with infered type */ template Callback callback(R (*func)(const volatile T*, A0, A1, A2), const volatile T *arg) { return Callback(func, arg); } /** 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 * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to callback(func, arg)") Callback callback(void *obj, R (*func)(void*, A0, A1, A2)) { return Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to callback(func, arg)") Callback callback(const void *obj, R (*func)(const void*, A0, A1, A2)) { return Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to callback(func, arg)") Callback callback(volatile void *obj, R (*func)(volatile void*, A0, A1, A2)) { return Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to callback(func, arg)") Callback callback(const volatile void *obj, R (*func)(const volatile void*, A0, A1, A2)) { return Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to callback(func, arg)") Callback callback(T *obj, R (*func)(T*, A0, A1, A2)) { return Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to callback(func, arg)") Callback callback(const T *obj, R (*func)(const T*, A0, A1, A2)) { return Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to callback(func, arg)") Callback callback(volatile T *obj, R (*func)(volatile T*, A0, A1, A2)) { return Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to callback(func, arg)") Callback callback(const volatile T *obj, R (*func)(const volatile T*, A0, A1, A2)) { return Callback(func, obj); } /** Create a callback class with type infered from the arguments * * @param func Static function to attach * @return Callback with infered type */ template Callback callback(R (*func)(A0, A1, A2, A3) = 0) { return Callback(func); } /** Create a callback class with type infered from the arguments * * @param func Static function to attach * @return Callback with infered type */ template Callback callback(const Callback &func) { return Callback(func); } /** Create a callback class with type infered from the arguments * * @param obj Optional pointer to object to bind to function * @param method Member function to attach * @return Callback with infered type */ template Callback callback(T *obj, R (T::*func)(A0, A1, A2, A3)) { return Callback(obj, func); } /** Create a callback class with type infered from the arguments * * @param obj Optional pointer to object to bind to function * @param method Member function to attach * @return Callback with infered type */ template Callback callback(const T *obj, R (T::*func)(A0, A1, A2, A3) const) { return Callback(obj, func); } /** Create a callback class with type infered from the arguments * * @param obj Optional pointer to object to bind to function * @param method Member function to attach * @return Callback with infered type */ template Callback callback(volatile T *obj, R (T::*func)(A0, A1, A2, A3) volatile) { return Callback(obj, func); } /** Create a callback class with type infered from the arguments * * @param obj Optional pointer to object to bind to function * @param method Member function to attach * @return Callback with infered type */ template Callback callback(const volatile T *obj, R (T::*func)(A0, A1, A2, A3) const volatile) { return Callback(obj, func); } /** Create a callback class with type infered from the arguments * * @param func Static function to attach * @param arg Pointer argument to function * @return Callback with infered type */ template Callback callback(R (*func)(void*, A0, A1, A2, A3), void *arg) { return Callback(func, arg); } /** Create a callback class with type infered from the arguments * * @param func Static function to attach * @param arg Pointer argument to function * @return Callback with infered type */ template Callback callback(R (*func)(const void*, A0, A1, A2, A3), const void *arg) { return Callback(func, arg); } /** Create a callback class with type infered from the arguments * * @param func Static function to attach * @param arg Pointer argument to function * @return Callback with infered type */ template Callback callback(R (*func)(volatile void*, A0, A1, A2, A3), volatile void *arg) { return Callback(func, arg); } /** Create a callback class with type infered from the arguments * * @param func Static function to attach * @param arg Pointer argument to function * @return Callback with infered type */ template Callback callback(R (*func)(const volatile void*, A0, A1, A2, A3), const volatile void *arg) { return Callback(func, arg); } /** Create a callback class with type infered from the arguments * * @param func Static function to attach * @param arg Pointer argument to function * @return Callback with infered type */ template Callback callback(R (*func)(T*, A0, A1, A2, A3), T *arg) { return Callback(func, arg); } /** Create a callback class with type infered from the arguments * * @param func Static function to attach * @param arg Pointer argument to function * @return Callback with infered type */ template Callback callback(R (*func)(const T*, A0, A1, A2, A3), const T *arg) { return Callback(func, arg); } /** Create a callback class with type infered from the arguments * * @param func Static function to attach * @param arg Pointer argument to function * @return Callback with infered type */ template Callback callback(R (*func)(volatile T*, A0, A1, A2, A3), volatile T *arg) { return Callback(func, arg); } /** Create a callback class with type infered from the arguments * * @param func Static function to attach * @param arg Pointer argument to function * @return Callback with infered type */ template Callback callback(R (*func)(const volatile T*, A0, A1, A2, A3), const volatile T *arg) { return Callback(func, arg); } /** 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 * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to callback(func, arg)") Callback callback(void *obj, R (*func)(void*, A0, A1, A2, A3)) { return Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to callback(func, arg)") Callback callback(const void *obj, R (*func)(const void*, A0, A1, A2, A3)) { return Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to callback(func, arg)") Callback callback(volatile void *obj, R (*func)(volatile void*, A0, A1, A2, A3)) { return Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to callback(func, arg)") Callback callback(const volatile void *obj, R (*func)(const volatile void*, A0, A1, A2, A3)) { return Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to callback(func, arg)") Callback callback(T *obj, R (*func)(T*, A0, A1, A2, A3)) { return Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to callback(func, arg)") Callback callback(const T *obj, R (*func)(const T*, A0, A1, A2, A3)) { return Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to callback(func, arg)") Callback callback(volatile T *obj, R (*func)(volatile T*, A0, A1, A2, A3)) { return Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to callback(func, arg)") Callback callback(const volatile T *obj, R (*func)(const volatile T*, A0, A1, A2, A3)) { return Callback(func, obj); } /** Create a callback class with type infered from the arguments * * @param func Static function to attach * @return Callback with infered type */ template Callback callback(R (*func)(A0, A1, A2, A3, A4) = 0) { return Callback(func); } /** Create a callback class with type infered from the arguments * * @param func Static function to attach * @return Callback with infered type */ template Callback callback(const Callback &func) { return Callback(func); } /** Create a callback class with type infered from the arguments * * @param obj Optional pointer to object to bind to function * @param method Member function to attach * @return Callback with infered type */ template Callback callback(T *obj, R (T::*func)(A0, A1, A2, A3, A4)) { return Callback(obj, func); } /** Create a callback class with type infered from the arguments * * @param obj Optional pointer to object to bind to function * @param method Member function to attach * @return Callback with infered type */ template Callback callback(const T *obj, R (T::*func)(A0, A1, A2, A3, A4) const) { return Callback(obj, func); } /** Create a callback class with type infered from the arguments * * @param obj Optional pointer to object to bind to function * @param method Member function to attach * @return Callback with infered type */ template Callback callback(volatile T *obj, R (T::*func)(A0, A1, A2, A3, A4) volatile) { return Callback(obj, func); } /** Create a callback class with type infered from the arguments * * @param obj Optional pointer to object to bind to function * @param method Member function to attach * @return Callback with infered type */ template Callback callback(const volatile T *obj, R (T::*func)(A0, A1, A2, A3, A4) const volatile) { return Callback(obj, func); } /** Create a callback class with type infered from the arguments * * @param func Static function to attach * @param arg Pointer argument to function * @return Callback with infered type */ template Callback callback(R (*func)(void*, A0, A1, A2, A3, A4), void *arg) { return Callback(func, arg); } /** Create a callback class with type infered from the arguments * * @param func Static function to attach * @param arg Pointer argument to function * @return Callback with infered type */ template Callback callback(R (*func)(const void*, A0, A1, A2, A3, A4), const void *arg) { return Callback(func, arg); } /** Create a callback class with type infered from the arguments * * @param func Static function to attach * @param arg Pointer argument to function * @return Callback with infered type */ template Callback callback(R (*func)(volatile void*, A0, A1, A2, A3, A4), volatile void *arg) { return Callback(func, arg); } /** Create a callback class with type infered from the arguments * * @param func Static function to attach * @param arg Pointer argument to function * @return Callback with infered type */ template Callback callback(R (*func)(const volatile void*, A0, A1, A2, A3, A4), const volatile void *arg) { return Callback(func, arg); } /** Create a callback class with type infered from the arguments * * @param func Static function to attach * @param arg Pointer argument to function * @return Callback with infered type */ template Callback callback(R (*func)(T*, A0, A1, A2, A3, A4), T *arg) { return Callback(func, arg); } /** Create a callback class with type infered from the arguments * * @param func Static function to attach * @param arg Pointer argument to function * @return Callback with infered type */ template Callback callback(R (*func)(const T*, A0, A1, A2, A3, A4), const T *arg) { return Callback(func, arg); } /** Create a callback class with type infered from the arguments * * @param func Static function to attach * @param arg Pointer argument to function * @return Callback with infered type */ template Callback callback(R (*func)(volatile T*, A0, A1, A2, A3, A4), volatile T *arg) { return Callback(func, arg); } /** Create a callback class with type infered from the arguments * * @param func Static function to attach * @param arg Pointer argument to function * @return Callback with infered type */ template Callback callback(R (*func)(const volatile T*, A0, A1, A2, A3, A4), const volatile T *arg) { return Callback(func, arg); } /** 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 * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to callback(func, arg)") Callback callback(void *obj, R (*func)(void*, A0, A1, A2, A3, A4)) { return Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to callback(func, arg)") Callback callback(const void *obj, R (*func)(const void*, A0, A1, A2, A3, A4)) { return Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to callback(func, arg)") Callback callback(volatile void *obj, R (*func)(volatile void*, A0, A1, A2, A3, A4)) { return Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to callback(func, arg)") Callback callback(const volatile void *obj, R (*func)(const volatile void*, A0, A1, A2, A3, A4)) { return Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to callback(func, arg)") Callback callback(T *obj, R (*func)(T*, A0, A1, A2, A3, A4)) { return Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to callback(func, arg)") Callback callback(const T *obj, R (*func)(const T*, A0, A1, A2, A3, A4)) { return Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to callback(func, arg)") Callback callback(volatile T *obj, R (*func)(volatile T*, A0, A1, A2, A3, A4)) { return Callback(func, obj); } /** 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 * @deprecated * Arguments to callback have been reordered to callback(func, arg) */ template MBED_DEPRECATED_SINCE("mbed-os-5.1", "Arguments to callback have been reordered to callback(func, arg)") Callback callback(const volatile T *obj, R (*func)(const volatile T*, A0, A1, A2, A3, A4)) { return Callback(func, obj); } } // namespace mbed #endif