Flexible templated function class and related utilities that avoid dynamic memory allocation without limiting functionality

Dependents:   SimpleHTTPExample

FuncPtr provides a flexible templated function class and related utilities while avoiding dynamic memory allocation and avoiding limited functionality.

FuncPtr provides an intuitive template interface:

FuncPtr<void(const char *)> func(puts);
func("hello!\n"); // prints hello!


Several function types are supported by FuncPtr:

// Simple C functions
void func();
FuncPtr<void()> fp(func);

// C++ Methods
struct Thing { void func(); };
Thing thing;
FuncPtr<void()> fp(&thing, &Thing::func);

// C functions with context
void func(Thing *);
FuncPtr<void()> fp(&thing, func);

// Function objects
struct Thing { void operator()(); };
Thing thing;
FuncPtr<void()> fp(&thing);


There is no dynamic memory allocation, managing memory is placed entirely on the user. More advanced function manipulation can be accomplished with statically allocated classes:

// Function binding
Binder<void(const char *), const char *> bind(putc, "hi!");
bind(); // prints hi!

// Function composition
Composer<int(const char *), const char *(int)> comp(puts, itoa);
comp(10); // prints 10

// Function chaining
Chainer<void(const char *), 2> chain;
chain.attach(puts);
chain.attach(puts);
chain("hi!\n"); // prints hi! twice


FuncPtr allows easy support of a large range of function types in C++ APIs with very few lines of code:

class Thing {
public:
    // The following two methods are sufficient for supporting 
    // every supported function type
    void attach(FuncPtr<void()> func) {
        _func.attach(func);
    }

    template<typename T, typename M>
    void attach(T *obj, M method) {
        attach(FuncPtr<void()>(obj, method));
    }

private:
    FuncPtr<void()> _func;
}


Additionally, FuncPtrs have several utilities for easy integration with C APIs:

// C style callbacks
void register_callback(void (*callback)(void *), void *data);

register_callback(&FuncPtr<void()>::thunk, &func);

// C style functions without context
void register_callback(void (*callback)());

Thunker thunk(func);
register_callback(thunk);

// mbed style callbacks
void register_callback(T *obj, void (T::*M)());

register_callback(&func, &FuncPtr<void()>::call);

Committer:
Christopher Haster
Date:
Sun Apr 17 23:38:04 2016 -0500
Revision:
18:a0fde14b6c39
Parent:
14:79be4e700cc9
Increase to 5 args

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Christopher Haster 2:56e1906f7103 1 /* FuncPtr
Christopher Haster 2:56e1906f7103 2 *
Christopher Haster 0:176c74479de2 3 * Flexible templated function class that avoids dynamic memory
Christopher Haster 0:176c74479de2 4 * allocation without limiting functionality
Christopher Haster 0:176c74479de2 5 */
Christopher Haster 0:176c74479de2 6 #ifndef FUNCPTR_H
Christopher Haster 0:176c74479de2 7 #define FUNCPTR_H
Christopher Haster 0:176c74479de2 8
Christopher Haster 0:176c74479de2 9 #include <string.h>
Christopher Haster 0:176c74479de2 10 #include <stdint.h>
Christopher Haster 0:176c74479de2 11
Christopher Haster 0:176c74479de2 12
Christopher Haster 0:176c74479de2 13 /** FuncPtr class based on template specialization
Christopher Haster 0:176c74479de2 14 */
Christopher Haster 0:176c74479de2 15 template <typename F>
Christopher Haster 0:176c74479de2 16 class FuncPtr;
Christopher Haster 0:176c74479de2 17
Christopher Haster 0:176c74479de2 18 /** Flexible templated function class
Christopher Haster 0:176c74479de2 19 */
Christopher Haster 18:a0fde14b6c39 20 template <typename R, typename A0, typename A1, typename A2, typename A3, typename A4>
Christopher Haster 18:a0fde14b6c39 21 class FuncPtr<R(A0, A1, A2, A3, A4)> {
Christopher Haster 18:a0fde14b6c39 22 public:
Christopher Haster 18:a0fde14b6c39 23 /** Create a FuncPtr with a static function
Christopher Haster 18:a0fde14b6c39 24 * @param func Static function to attach
Christopher Haster 18:a0fde14b6c39 25 */
Christopher Haster 18:a0fde14b6c39 26 FuncPtr(R (*func)(A0, A1, A2, A3, A4) = 0) {
Christopher Haster 18:a0fde14b6c39 27 attach(func);
Christopher Haster 18:a0fde14b6c39 28 }
Christopher Haster 18:a0fde14b6c39 29
Christopher Haster 18:a0fde14b6c39 30 /** Create a FuncPtr with a static function and bound pointer
Christopher Haster 18:a0fde14b6c39 31 * @param obj Pointer to object to bind to function
Christopher Haster 18:a0fde14b6c39 32 * @param func Static function to attach
Christopher Haster 18:a0fde14b6c39 33 */
Christopher Haster 18:a0fde14b6c39 34 template<typename T>
Christopher Haster 18:a0fde14b6c39 35 FuncPtr(T *obj, R (*func)(T*, A0, A1, A2, A3, A4)) {
Christopher Haster 18:a0fde14b6c39 36 attach(obj, func);
Christopher Haster 18:a0fde14b6c39 37 }
Christopher Haster 18:a0fde14b6c39 38
Christopher Haster 18:a0fde14b6c39 39 /** Create a FuncPtr with a method
Christopher Haster 18:a0fde14b6c39 40 * @param obj Pointer to object to invoke method on
Christopher Haster 18:a0fde14b6c39 41 * @param func Method to attach
Christopher Haster 18:a0fde14b6c39 42 */
Christopher Haster 18:a0fde14b6c39 43 template<typename T>
Christopher Haster 18:a0fde14b6c39 44 FuncPtr(T *obj, R (T::*func)(A0, A1, A2, A3, A4)) {
Christopher Haster 18:a0fde14b6c39 45 attach(obj, func);
Christopher Haster 18:a0fde14b6c39 46 }
Christopher Haster 18:a0fde14b6c39 47
Christopher Haster 18:a0fde14b6c39 48 /** Create a FuncPtr with a function object
Christopher Haster 18:a0fde14b6c39 49 * @param func Function object to attach
Christopher Haster 18:a0fde14b6c39 50 */
Christopher Haster 18:a0fde14b6c39 51 template<typename T>
Christopher Haster 18:a0fde14b6c39 52 FuncPtr(T *obj) {
Christopher Haster 18:a0fde14b6c39 53 attach(obj, &T::operator());
Christopher Haster 18:a0fde14b6c39 54 }
Christopher Haster 18:a0fde14b6c39 55
Christopher Haster 18:a0fde14b6c39 56 /** Create a FuncPtr with another FuncPtr
Christopher Haster 18:a0fde14b6c39 57 * @param func FuncPtr to attach
Christopher Haster 18:a0fde14b6c39 58 */
Christopher Haster 18:a0fde14b6c39 59 FuncPtr(const FuncPtr<R(A0, A1, A2, A3, A4)> &func) {
Christopher Haster 18:a0fde14b6c39 60 attach(func);
Christopher Haster 18:a0fde14b6c39 61 }
Christopher Haster 18:a0fde14b6c39 62
Christopher Haster 18:a0fde14b6c39 63 /** Attach a static function
Christopher Haster 18:a0fde14b6c39 64 * @param func Static function to attach
Christopher Haster 18:a0fde14b6c39 65 */
Christopher Haster 18:a0fde14b6c39 66 void attach(R (*func)(A0, A1, A2, A3, A4)) {
Christopher Haster 18:a0fde14b6c39 67 memcpy(&_func, &func, sizeof func);
Christopher Haster 18:a0fde14b6c39 68 _thunk = func ? &FuncPtr::_staticthunk : 0;
Christopher Haster 18:a0fde14b6c39 69 }
Christopher Haster 18:a0fde14b6c39 70
Christopher Haster 18:a0fde14b6c39 71 /** Attach a static function with a bound pointer
Christopher Haster 18:a0fde14b6c39 72 * @param obj Pointer to object to bind to function
Christopher Haster 18:a0fde14b6c39 73 * @param func Static function to attach
Christopher Haster 18:a0fde14b6c39 74 */
Christopher Haster 18:a0fde14b6c39 75 template <typename T>
Christopher Haster 18:a0fde14b6c39 76 void attach(T *obj, R (*func)(T*, A0, A1, A2, A3, A4)) {
Christopher Haster 18:a0fde14b6c39 77 _obj = static_cast<void*>(obj);
Christopher Haster 18:a0fde14b6c39 78 memcpy(&_func, &func, sizeof func);
Christopher Haster 18:a0fde14b6c39 79 _thunk = &FuncPtr::_boundthunk<T>;
Christopher Haster 18:a0fde14b6c39 80 }
Christopher Haster 18:a0fde14b6c39 81
Christopher Haster 18:a0fde14b6c39 82 /** Attach a method
Christopher Haster 18:a0fde14b6c39 83 * @param obj Pointer to object to invoke method on
Christopher Haster 18:a0fde14b6c39 84 * @param func Method to attach
Christopher Haster 18:a0fde14b6c39 85 */
Christopher Haster 18:a0fde14b6c39 86 template<typename T>
Christopher Haster 18:a0fde14b6c39 87 void attach(T *obj, R (T::*func)(A0, A1, A2, A3, A4)) {
Christopher Haster 18:a0fde14b6c39 88 _obj = static_cast<void*>(obj);
Christopher Haster 18:a0fde14b6c39 89 memcpy(&_func, &func, sizeof func);
Christopher Haster 18:a0fde14b6c39 90 _thunk = &FuncPtr::_methodthunk<T>;
Christopher Haster 18:a0fde14b6c39 91 }
Christopher Haster 18:a0fde14b6c39 92
Christopher Haster 18:a0fde14b6c39 93 /** Attach a function object
Christopher Haster 18:a0fde14b6c39 94 * @param func Function object to attach
Christopher Haster 18:a0fde14b6c39 95 */
Christopher Haster 18:a0fde14b6c39 96 template<typename T>
Christopher Haster 18:a0fde14b6c39 97 void attach(T *func) {
Christopher Haster 18:a0fde14b6c39 98 attach(func, &T::operator());
Christopher Haster 18:a0fde14b6c39 99 }
Christopher Haster 18:a0fde14b6c39 100
Christopher Haster 18:a0fde14b6c39 101 /** Attach a FuncPtr
Christopher Haster 18:a0fde14b6c39 102 * @param func The FuncPtr to attach
Christopher Haster 18:a0fde14b6c39 103 */
Christopher Haster 18:a0fde14b6c39 104 void attach(const FuncPtr<R(A0, A1, A2, A3, A4)> &func) {
Christopher Haster 18:a0fde14b6c39 105 _obj = func._obj;
Christopher Haster 18:a0fde14b6c39 106 memcpy(&_func, &func._func, sizeof _func);
Christopher Haster 18:a0fde14b6c39 107 _thunk = func._thunk;
Christopher Haster 18:a0fde14b6c39 108 }
Christopher Haster 18:a0fde14b6c39 109
Christopher Haster 18:a0fde14b6c39 110 /** Call the attached function
Christopher Haster 18:a0fde14b6c39 111 */
Christopher Haster 18:a0fde14b6c39 112 R call(A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) {
Christopher Haster 18:a0fde14b6c39 113 return _thunk(_obj, &_func, a0, a1, a2, a3, a4);
Christopher Haster 18:a0fde14b6c39 114 }
Christopher Haster 18:a0fde14b6c39 115
Christopher Haster 18:a0fde14b6c39 116 /** Call the attached function
Christopher Haster 18:a0fde14b6c39 117 */
Christopher Haster 18:a0fde14b6c39 118 R operator()(A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) {
Christopher Haster 18:a0fde14b6c39 119 return call(a0, a1, a2, a3, a4);
Christopher Haster 18:a0fde14b6c39 120 }
Christopher Haster 18:a0fde14b6c39 121
Christopher Haster 18:a0fde14b6c39 122 /** Test if function has been attached
Christopher Haster 18:a0fde14b6c39 123 */
Christopher Haster 18:a0fde14b6c39 124 operator bool() const {
Christopher Haster 18:a0fde14b6c39 125 return _thunk;
Christopher Haster 18:a0fde14b6c39 126 }
Christopher Haster 18:a0fde14b6c39 127
Christopher Haster 18:a0fde14b6c39 128 /** Static thunk for passing as C-style function
Christopher Haster 18:a0fde14b6c39 129 * @param func FuncPtr to call passed as void pointer
Christopher Haster 18:a0fde14b6c39 130 */
Christopher Haster 18:a0fde14b6c39 131 static R thunk(void *func, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) {
Christopher Haster 18:a0fde14b6c39 132 return static_cast<FuncPtr<R(A0, A1, A2, A3, A4)>*>(func)
Christopher Haster 18:a0fde14b6c39 133 ->call(a0, a1, a2, a3, a4);
Christopher Haster 18:a0fde14b6c39 134 }
Christopher Haster 18:a0fde14b6c39 135
Christopher Haster 18:a0fde14b6c39 136 private:
Christopher Haster 18:a0fde14b6c39 137 // Internal thunks for various function types
Christopher Haster 18:a0fde14b6c39 138 static R _staticthunk(void*, void *func, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) {
Christopher Haster 18:a0fde14b6c39 139 return (*reinterpret_cast<R (**)(A0, A1, A2, A3, A4)>(func))
Christopher Haster 18:a0fde14b6c39 140 (a0, a1, a2, a3, a4);
Christopher Haster 18:a0fde14b6c39 141 }
Christopher Haster 18:a0fde14b6c39 142
Christopher Haster 18:a0fde14b6c39 143 template<typename T>
Christopher Haster 18:a0fde14b6c39 144 static R _boundthunk(void *obj, void *func, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) {
Christopher Haster 18:a0fde14b6c39 145 return (*reinterpret_cast<R (**)(T*, A0, A1, A2, A3, A4)>(func))
Christopher Haster 18:a0fde14b6c39 146 (static_cast<T*>(obj), a0, a1, a2, a3, a4);
Christopher Haster 18:a0fde14b6c39 147 }
Christopher Haster 18:a0fde14b6c39 148
Christopher Haster 18:a0fde14b6c39 149 template<typename T>
Christopher Haster 18:a0fde14b6c39 150 static R _methodthunk(void *obj, void *func, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) {
Christopher Haster 18:a0fde14b6c39 151 return (static_cast<T*>(obj)->*
Christopher Haster 18:a0fde14b6c39 152 (*reinterpret_cast<R (T::**)(A0, A1, A2, A3, A4)>(func)))
Christopher Haster 18:a0fde14b6c39 153 (a0, a1, a2, a3, a4);
Christopher Haster 18:a0fde14b6c39 154 }
Christopher Haster 18:a0fde14b6c39 155
Christopher Haster 18:a0fde14b6c39 156 // Stored as pointer to function and pointer to optional object
Christopher Haster 18:a0fde14b6c39 157 // Function pointer is stored as union of possible function types
Christopher Haster 18:a0fde14b6c39 158 // to garuntee proper size and alignment
Christopher Haster 18:a0fde14b6c39 159 struct _class;
Christopher Haster 18:a0fde14b6c39 160 union {
Christopher Haster 18:a0fde14b6c39 161 void (*_staticfunc)();
Christopher Haster 18:a0fde14b6c39 162 void (*_boundfunc)(_class *);
Christopher Haster 18:a0fde14b6c39 163 void (_class::*_methodfunc)();
Christopher Haster 18:a0fde14b6c39 164 } _func;
Christopher Haster 18:a0fde14b6c39 165
Christopher Haster 18:a0fde14b6c39 166 void *_obj;
Christopher Haster 18:a0fde14b6c39 167
Christopher Haster 18:a0fde14b6c39 168 // Thunk registered on attach to dispatch calls
Christopher Haster 18:a0fde14b6c39 169 R (*_thunk)(void*, void*, A0, A1, A2, A3, A4);
Christopher Haster 18:a0fde14b6c39 170 };
Christopher Haster 18:a0fde14b6c39 171
Christopher Haster 18:a0fde14b6c39 172 /** Flexible templated function class
Christopher Haster 18:a0fde14b6c39 173 */
Christopher Haster 0:176c74479de2 174 template <typename R, typename A0, typename A1, typename A2, typename A3>
Christopher Haster 0:176c74479de2 175 class FuncPtr<R(A0, A1, A2, A3)> {
Christopher Haster 0:176c74479de2 176 public:
Christopher Haster 0:176c74479de2 177 /** Create a FuncPtr with a static function
Christopher Haster 0:176c74479de2 178 * @param func Static function to attach
Christopher Haster 0:176c74479de2 179 */
Christopher Haster 0:176c74479de2 180 FuncPtr(R (*func)(A0, A1, A2, A3) = 0) {
Christopher Haster 0:176c74479de2 181 attach(func);
Christopher Haster 0:176c74479de2 182 }
Christopher Haster 0:176c74479de2 183
Christopher Haster 0:176c74479de2 184 /** Create a FuncPtr with a static function and bound pointer
Christopher Haster 0:176c74479de2 185 * @param obj Pointer to object to bind to function
Christopher Haster 0:176c74479de2 186 * @param func Static function to attach
Christopher Haster 0:176c74479de2 187 */
Christopher Haster 0:176c74479de2 188 template<typename T>
Christopher Haster 0:176c74479de2 189 FuncPtr(T *obj, R (*func)(T*, A0, A1, A2, A3)) {
Christopher Haster 0:176c74479de2 190 attach(obj, func);
Christopher Haster 0:176c74479de2 191 }
Christopher Haster 0:176c74479de2 192
Christopher Haster 0:176c74479de2 193 /** Create a FuncPtr with a method
Christopher Haster 0:176c74479de2 194 * @param obj Pointer to object to invoke method on
Christopher Haster 0:176c74479de2 195 * @param func Method to attach
Christopher Haster 0:176c74479de2 196 */
Christopher Haster 0:176c74479de2 197 template<typename T>
Christopher Haster 0:176c74479de2 198 FuncPtr(T *obj, R (T::*func)(A0, A1, A2, A3)) {
Christopher Haster 0:176c74479de2 199 attach(obj, func);
Christopher Haster 0:176c74479de2 200 }
Christopher Haster 0:176c74479de2 201
Christopher Haster 0:176c74479de2 202 /** Create a FuncPtr with a function object
Christopher Haster 0:176c74479de2 203 * @param func Function object to attach
Christopher Haster 0:176c74479de2 204 */
Christopher Haster 0:176c74479de2 205 template<typename T>
Christopher Haster 0:176c74479de2 206 FuncPtr(T *obj) {
Christopher Haster 0:176c74479de2 207 attach(obj, &T::operator());
Christopher Haster 0:176c74479de2 208 }
Christopher Haster 0:176c74479de2 209
Christopher Haster 0:176c74479de2 210 /** Create a FuncPtr with another FuncPtr
Christopher Haster 0:176c74479de2 211 * @param func FuncPtr to attach
Christopher Haster 0:176c74479de2 212 */
Christopher Haster 0:176c74479de2 213 FuncPtr(const FuncPtr<R(A0, A1, A2, A3)> &func) {
Christopher Haster 0:176c74479de2 214 attach(func);
Christopher Haster 0:176c74479de2 215 }
Christopher Haster 0:176c74479de2 216
Christopher Haster 0:176c74479de2 217 /** Attach a static function
Christopher Haster 0:176c74479de2 218 * @param func Static function to attach
Christopher Haster 0:176c74479de2 219 */
Christopher Haster 0:176c74479de2 220 void attach(R (*func)(A0, A1, A2, A3)) {
Christopher Haster 0:176c74479de2 221 memcpy(&_func, &func, sizeof func);
Christopher Haster 6:b5f0551273f6 222 _thunk = func ? &FuncPtr::_staticthunk : 0;
Christopher Haster 0:176c74479de2 223 }
Christopher Haster 0:176c74479de2 224
Christopher Haster 0:176c74479de2 225 /** Attach a static function with a bound pointer
Christopher Haster 0:176c74479de2 226 * @param obj Pointer to object to bind to function
Christopher Haster 0:176c74479de2 227 * @param func Static function to attach
Christopher Haster 0:176c74479de2 228 */
Christopher Haster 0:176c74479de2 229 template <typename T>
Christopher Haster 0:176c74479de2 230 void attach(T *obj, R (*func)(T*, A0, A1, A2, A3)) {
Christopher Haster 0:176c74479de2 231 _obj = static_cast<void*>(obj);
Christopher Haster 0:176c74479de2 232 memcpy(&_func, &func, sizeof func);
Christopher Haster 0:176c74479de2 233 _thunk = &FuncPtr::_boundthunk<T>;
Christopher Haster 0:176c74479de2 234 }
Christopher Haster 0:176c74479de2 235
Christopher Haster 0:176c74479de2 236 /** Attach a method
Christopher Haster 0:176c74479de2 237 * @param obj Pointer to object to invoke method on
Christopher Haster 0:176c74479de2 238 * @param func Method to attach
Christopher Haster 0:176c74479de2 239 */
Christopher Haster 0:176c74479de2 240 template<typename T>
Christopher Haster 0:176c74479de2 241 void attach(T *obj, R (T::*func)(A0, A1, A2, A3)) {
Christopher Haster 0:176c74479de2 242 _obj = static_cast<void*>(obj);
Christopher Haster 0:176c74479de2 243 memcpy(&_func, &func, sizeof func);
Christopher Haster 0:176c74479de2 244 _thunk = &FuncPtr::_methodthunk<T>;
Christopher Haster 0:176c74479de2 245 }
Christopher Haster 0:176c74479de2 246
Christopher Haster 0:176c74479de2 247 /** Attach a function object
Christopher Haster 0:176c74479de2 248 * @param func Function object to attach
Christopher Haster 0:176c74479de2 249 */
Christopher Haster 0:176c74479de2 250 template<typename T>
Christopher Haster 0:176c74479de2 251 void attach(T *func) {
Christopher Haster 0:176c74479de2 252 attach(func, &T::operator());
Christopher Haster 0:176c74479de2 253 }
Christopher Haster 0:176c74479de2 254
Christopher Haster 0:176c74479de2 255 /** Attach a FuncPtr
Christopher Haster 0:176c74479de2 256 * @param func The FuncPtr to attach
Christopher Haster 0:176c74479de2 257 */
Christopher Haster 0:176c74479de2 258 void attach(const FuncPtr<R(A0, A1, A2, A3)> &func) {
Christopher Haster 0:176c74479de2 259 _obj = func._obj;
Christopher Haster 0:176c74479de2 260 memcpy(&_func, &func._func, sizeof _func);
Christopher Haster 0:176c74479de2 261 _thunk = func._thunk;
Christopher Haster 0:176c74479de2 262 }
Christopher Haster 0:176c74479de2 263
Christopher Haster 2:56e1906f7103 264 /** Call the attached function
Christopher Haster 0:176c74479de2 265 */
Christopher Haster 0:176c74479de2 266 R call(A0 a0, A1 a1, A2 a2, A3 a3) {
Christopher Haster 0:176c74479de2 267 return _thunk(_obj, &_func, a0, a1, a2, a3);
Christopher Haster 0:176c74479de2 268 }
Christopher Haster 0:176c74479de2 269
Christopher Haster 2:56e1906f7103 270 /** Call the attached function
Christopher Haster 0:176c74479de2 271 */
Christopher Haster 0:176c74479de2 272 R operator()(A0 a0, A1 a1, A2 a2, A3 a3) {
Christopher Haster 0:176c74479de2 273 return call(a0, a1, a2, a3);
Christopher Haster 0:176c74479de2 274 }
Christopher Haster 0:176c74479de2 275
Christopher Haster 0:176c74479de2 276 /** Test if function has been attached
Christopher Haster 0:176c74479de2 277 */
Christopher Haster 8:71037a47492d 278 operator bool() const {
Christopher Haster 6:b5f0551273f6 279 return _thunk;
Christopher Haster 0:176c74479de2 280 }
Christopher Haster 0:176c74479de2 281
Christopher Haster 1:9c28068feddc 282 /** Static thunk for passing as C-style function
Christopher Haster 2:56e1906f7103 283 * @param func FuncPtr to call passed as void pointer
Christopher Haster 1:9c28068feddc 284 */
Christopher Haster 2:56e1906f7103 285 static R thunk(void *func, A0 a0, A1 a1, A2 a2, A3 a3) {
Christopher Haster 2:56e1906f7103 286 return static_cast<FuncPtr<R(A0, A1, A2, A3)>*>(func)
Christopher Haster 1:9c28068feddc 287 ->call(a0, a1, a2, a3);
Christopher Haster 1:9c28068feddc 288 }
Christopher Haster 1:9c28068feddc 289
Christopher Haster 0:176c74479de2 290 private:
Christopher Haster 0:176c74479de2 291 // Internal thunks for various function types
Christopher Haster 0:176c74479de2 292 static R _staticthunk(void*, void *func, A0 a0, A1 a1, A2 a2, A3 a3) {
Christopher Haster 0:176c74479de2 293 return (*reinterpret_cast<R (**)(A0, A1, A2, A3)>(func))
Christopher Haster 0:176c74479de2 294 (a0, a1, a2, a3);
Christopher Haster 0:176c74479de2 295 }
Christopher Haster 0:176c74479de2 296
Christopher Haster 0:176c74479de2 297 template<typename T>
Christopher Haster 0:176c74479de2 298 static R _boundthunk(void *obj, void *func, A0 a0, A1 a1, A2 a2, A3 a3) {
Christopher Haster 0:176c74479de2 299 return (*reinterpret_cast<R (**)(T*, A0, A1, A2, A3)>(func))
Christopher Haster 0:176c74479de2 300 (static_cast<T*>(obj), a0, a1, a2, a3);
Christopher Haster 0:176c74479de2 301 }
Christopher Haster 0:176c74479de2 302
Christopher Haster 0:176c74479de2 303 template<typename T>
Christopher Haster 0:176c74479de2 304 static R _methodthunk(void *obj, void *func, A0 a0, A1 a1, A2 a2, A3 a3) {
Christopher Haster 0:176c74479de2 305 return (static_cast<T*>(obj)->*
Christopher Haster 0:176c74479de2 306 (*reinterpret_cast<R (T::**)(A0, A1, A2, A3)>(func)))
Christopher Haster 0:176c74479de2 307 (a0, a1, a2, a3);
Christopher Haster 0:176c74479de2 308 }
Christopher Haster 0:176c74479de2 309
Christopher Haster 0:176c74479de2 310 // Stored as pointer to function and pointer to optional object
Christopher Haster 0:176c74479de2 311 // Function pointer is stored as union of possible function types
Christopher Haster 0:176c74479de2 312 // to garuntee proper size and alignment
Christopher Haster 0:176c74479de2 313 struct _class;
Christopher Haster 0:176c74479de2 314 union {
Christopher Haster 0:176c74479de2 315 void (*_staticfunc)();
Christopher Haster 0:176c74479de2 316 void (*_boundfunc)(_class *);
Christopher Haster 0:176c74479de2 317 void (_class::*_methodfunc)();
Christopher Haster 0:176c74479de2 318 } _func;
Christopher Haster 0:176c74479de2 319
Christopher Haster 11:035e0728d927 320 void *_obj;
Christopher Haster 11:035e0728d927 321
Christopher Haster 0:176c74479de2 322 // Thunk registered on attach to dispatch calls
Christopher Haster 0:176c74479de2 323 R (*_thunk)(void*, void*, A0, A1, A2, A3);
Christopher Haster 0:176c74479de2 324 };
Christopher Haster 0:176c74479de2 325
Christopher Haster 0:176c74479de2 326 /** Flexible templated function class
Christopher Haster 0:176c74479de2 327 */
Christopher Haster 0:176c74479de2 328 template <typename R, typename A0, typename A1, typename A2>
Christopher Haster 0:176c74479de2 329 class FuncPtr<R(A0, A1, A2)> {
Christopher Haster 0:176c74479de2 330 public:
Christopher Haster 0:176c74479de2 331 /** Create a FuncPtr with a static function
Christopher Haster 0:176c74479de2 332 * @param func Static function to attach
Christopher Haster 0:176c74479de2 333 */
Christopher Haster 0:176c74479de2 334 FuncPtr(R (*func)(A0, A1, A2) = 0) {
Christopher Haster 0:176c74479de2 335 attach(func);
Christopher Haster 0:176c74479de2 336 }
Christopher Haster 0:176c74479de2 337
Christopher Haster 0:176c74479de2 338 /** Create a FuncPtr with a static function and bound pointer
Christopher Haster 0:176c74479de2 339 * @param obj Pointer to object to bind to function
Christopher Haster 0:176c74479de2 340 * @param func Static function to attach
Christopher Haster 0:176c74479de2 341 */
Christopher Haster 0:176c74479de2 342 template<typename T>
Christopher Haster 0:176c74479de2 343 FuncPtr(T *obj, R (*func)(T*, A0, A1, A2)) {
Christopher Haster 0:176c74479de2 344 attach(obj, func);
Christopher Haster 0:176c74479de2 345 }
Christopher Haster 0:176c74479de2 346
Christopher Haster 0:176c74479de2 347 /** Create a FuncPtr with a method
Christopher Haster 0:176c74479de2 348 * @param obj Pointer to object to invoke method on
Christopher Haster 0:176c74479de2 349 * @param func Method to attach
Christopher Haster 0:176c74479de2 350 */
Christopher Haster 0:176c74479de2 351 template<typename T>
Christopher Haster 0:176c74479de2 352 FuncPtr(T *obj, R (T::*func)(A0, A1, A2)) {
Christopher Haster 0:176c74479de2 353 attach(obj, func);
Christopher Haster 0:176c74479de2 354 }
Christopher Haster 0:176c74479de2 355
Christopher Haster 0:176c74479de2 356 /** Create a FuncPtr with a function object
Christopher Haster 0:176c74479de2 357 * @param func Function object to attach
Christopher Haster 0:176c74479de2 358 */
Christopher Haster 0:176c74479de2 359 template<typename T>
Christopher Haster 0:176c74479de2 360 FuncPtr(T *func) {
Christopher Haster 0:176c74479de2 361 attach(func, &T::operator());
Christopher Haster 0:176c74479de2 362 }
Christopher Haster 0:176c74479de2 363
Christopher Haster 0:176c74479de2 364 /** Create a FuncPtr with another FuncPtr
Christopher Haster 0:176c74479de2 365 * @param func FuncPtr to attach
Christopher Haster 0:176c74479de2 366 */
Christopher Haster 0:176c74479de2 367 FuncPtr(const FuncPtr<R(A0, A1, A2)> &func) {
Christopher Haster 0:176c74479de2 368 attach(func);
Christopher Haster 0:176c74479de2 369 }
Christopher Haster 0:176c74479de2 370
Christopher Haster 0:176c74479de2 371 /** Attach a static function
Christopher Haster 0:176c74479de2 372 * @param func Static function to attach
Christopher Haster 0:176c74479de2 373 */
Christopher Haster 0:176c74479de2 374 void attach(R (*func)(A0, A1, A2)) {
Christopher Haster 0:176c74479de2 375 memcpy(&_func, &func, sizeof func);
Christopher Haster 6:b5f0551273f6 376 _thunk = func ? &FuncPtr::_staticthunk : 0;
Christopher Haster 0:176c74479de2 377 }
Christopher Haster 0:176c74479de2 378
Christopher Haster 0:176c74479de2 379 /** Attach a static function with a bound pointer
Christopher Haster 0:176c74479de2 380 * @param obj Pointer to object to bind to function
Christopher Haster 0:176c74479de2 381 * @param func Static function to attach
Christopher Haster 0:176c74479de2 382 */
Christopher Haster 0:176c74479de2 383 template <typename T>
Christopher Haster 0:176c74479de2 384 void attach(T *obj, R (*func)(T*, A0, A1, A2)) {
Christopher Haster 0:176c74479de2 385 _obj = static_cast<void*>(obj);
Christopher Haster 0:176c74479de2 386 memcpy(&_func, &func, sizeof func);
Christopher Haster 0:176c74479de2 387 _thunk = &FuncPtr::_boundthunk<T>;
Christopher Haster 0:176c74479de2 388 }
Christopher Haster 0:176c74479de2 389
Christopher Haster 0:176c74479de2 390 /** Attach a method
Christopher Haster 0:176c74479de2 391 * @param obj Pointer to object to invoke method on
Christopher Haster 0:176c74479de2 392 * @param func Method to attach
Christopher Haster 0:176c74479de2 393 */
Christopher Haster 0:176c74479de2 394 template<typename T>
Christopher Haster 0:176c74479de2 395 void attach(T *obj, R (T::*func)(A0, A1, A2)) {
Christopher Haster 0:176c74479de2 396 _obj = static_cast<void*>(obj);
Christopher Haster 0:176c74479de2 397 memcpy(&_func, &func, sizeof func);
Christopher Haster 0:176c74479de2 398 _thunk = &FuncPtr::_methodthunk<T>;
Christopher Haster 0:176c74479de2 399 }
Christopher Haster 0:176c74479de2 400
Christopher Haster 0:176c74479de2 401 /** Attach a function object
Christopher Haster 0:176c74479de2 402 * @param func Function object to attach
Christopher Haster 0:176c74479de2 403 */
Christopher Haster 0:176c74479de2 404 template<typename T>
Christopher Haster 0:176c74479de2 405 void attach(T *func) {
Christopher Haster 0:176c74479de2 406 attach(func, &T::operator());
Christopher Haster 0:176c74479de2 407 }
Christopher Haster 0:176c74479de2 408
Christopher Haster 0:176c74479de2 409 /** Attach a FuncPtr
Christopher Haster 0:176c74479de2 410 * @param func The FuncPtr to attach
Christopher Haster 0:176c74479de2 411 */
Christopher Haster 0:176c74479de2 412 void attach(const FuncPtr<R(A0, A1, A2)> &func) {
Christopher Haster 0:176c74479de2 413 _obj = func._obj;
Christopher Haster 0:176c74479de2 414 memcpy(&_func, &func._func, sizeof _func);
Christopher Haster 0:176c74479de2 415 _thunk = func._thunk;
Christopher Haster 0:176c74479de2 416 }
Christopher Haster 0:176c74479de2 417
Christopher Haster 2:56e1906f7103 418 /** Call the attached function
Christopher Haster 0:176c74479de2 419 */
Christopher Haster 0:176c74479de2 420 R call(A0 a0, A1 a1, A2 a2) {
Christopher Haster 0:176c74479de2 421 return _thunk(_obj, &_func, a0, a1, a2);
Christopher Haster 0:176c74479de2 422 }
Christopher Haster 0:176c74479de2 423
Christopher Haster 2:56e1906f7103 424 /** Call the attached function
Christopher Haster 0:176c74479de2 425 */
Christopher Haster 0:176c74479de2 426 R operator()(A0 a0, A1 a1, A2 a2) {
Christopher Haster 0:176c74479de2 427 return call(a0, a1, a2);
Christopher Haster 0:176c74479de2 428 }
Christopher Haster 0:176c74479de2 429
Christopher Haster 0:176c74479de2 430 /** Test if function has been attached
Christopher Haster 0:176c74479de2 431 */
Christopher Haster 8:71037a47492d 432 operator bool() const {
Christopher Haster 6:b5f0551273f6 433 return _thunk;
Christopher Haster 0:176c74479de2 434 }
Christopher Haster 0:176c74479de2 435
Christopher Haster 1:9c28068feddc 436 /** Static thunk for passing as C-style function
Christopher Haster 2:56e1906f7103 437 * @param func FuncPtr to call passed as void pointer
Christopher Haster 1:9c28068feddc 438 */
Christopher Haster 2:56e1906f7103 439 static R thunk(void *func, A0 a0, A1 a1, A2 a2) {
Christopher Haster 2:56e1906f7103 440 return static_cast<FuncPtr<R(A0, A1, A2)>*>(func)
Christopher Haster 1:9c28068feddc 441 ->call(a0, a1, a2);
Christopher Haster 1:9c28068feddc 442 }
Christopher Haster 1:9c28068feddc 443
Christopher Haster 0:176c74479de2 444 private:
Christopher Haster 0:176c74479de2 445 // Internal thunks for various function types
Christopher Haster 0:176c74479de2 446 static R _staticthunk(void*, void *func, A0 a0, A1 a1, A2 a2) {
Christopher Haster 0:176c74479de2 447 return (*reinterpret_cast<R (**)(A0, A1, A2)>(func))
Christopher Haster 0:176c74479de2 448 (a0, a1, a2);
Christopher Haster 0:176c74479de2 449 }
Christopher Haster 0:176c74479de2 450
Christopher Haster 0:176c74479de2 451 template<typename T>
Christopher Haster 0:176c74479de2 452 static R _boundthunk(void *obj, void *func, A0 a0, A1 a1, A2 a2) {
Christopher Haster 0:176c74479de2 453 return (*reinterpret_cast<R (**)(T*, A0, A1, A2)>(func))
Christopher Haster 0:176c74479de2 454 (static_cast<T*>(obj), a0, a1, a2);
Christopher Haster 0:176c74479de2 455 }
Christopher Haster 0:176c74479de2 456
Christopher Haster 0:176c74479de2 457 template<typename T>
Christopher Haster 0:176c74479de2 458 static R _methodthunk(void *obj, void *func, A0 a0, A1 a1, A2 a2) {
Christopher Haster 0:176c74479de2 459 return (static_cast<T*>(obj)->*
Christopher Haster 0:176c74479de2 460 (*reinterpret_cast<R (T::**)(A0, A1, A2)>(func)))
Christopher Haster 0:176c74479de2 461 (a0, a1, a2);
Christopher Haster 0:176c74479de2 462 }
Christopher Haster 0:176c74479de2 463
Christopher Haster 0:176c74479de2 464 // Stored as pointer to function and pointer to optional object
Christopher Haster 0:176c74479de2 465 // Function pointer is stored as union of possible function types
Christopher Haster 0:176c74479de2 466 // to garuntee proper size and alignment
Christopher Haster 0:176c74479de2 467 struct _class;
Christopher Haster 0:176c74479de2 468 union {
Christopher Haster 0:176c74479de2 469 void (*_staticfunc)();
Christopher Haster 0:176c74479de2 470 void (*_boundfunc)(_class *);
Christopher Haster 0:176c74479de2 471 void (_class::*_methodfunc)();
Christopher Haster 0:176c74479de2 472 } _func;
Christopher Haster 0:176c74479de2 473
Christopher Haster 11:035e0728d927 474 void *_obj;
Christopher Haster 11:035e0728d927 475
Christopher Haster 0:176c74479de2 476 // Thunk registered on attach to dispatch calls
Christopher Haster 0:176c74479de2 477 R (*_thunk)(void*, void*, A0, A1, A2);
Christopher Haster 0:176c74479de2 478 };
Christopher Haster 0:176c74479de2 479
Christopher Haster 0:176c74479de2 480 /** Flexible templated function class
Christopher Haster 0:176c74479de2 481 */
Christopher Haster 0:176c74479de2 482 template <typename R, typename A0, typename A1>
Christopher Haster 0:176c74479de2 483 class FuncPtr<R(A0, A1)> {
Christopher Haster 0:176c74479de2 484 public:
Christopher Haster 0:176c74479de2 485 /** Create a FuncPtr with a static function
Christopher Haster 0:176c74479de2 486 * @param func Static function to attach
Christopher Haster 0:176c74479de2 487 */
Christopher Haster 0:176c74479de2 488 FuncPtr(R (*func)(A0, A1) = 0) {
Christopher Haster 0:176c74479de2 489 attach(func);
Christopher Haster 0:176c74479de2 490 }
Christopher Haster 0:176c74479de2 491
Christopher Haster 0:176c74479de2 492 /** Create a FuncPtr with a static function and bound pointer
Christopher Haster 0:176c74479de2 493 * @param obj Pointer to object to bind to function
Christopher Haster 0:176c74479de2 494 * @param func Static function to attach
Christopher Haster 0:176c74479de2 495 */
Christopher Haster 0:176c74479de2 496 template<typename T>
Christopher Haster 0:176c74479de2 497 FuncPtr(T *obj, R (*func)(T*, A0, A1)) {
Christopher Haster 0:176c74479de2 498 attach(obj, func);
Christopher Haster 0:176c74479de2 499 }
Christopher Haster 0:176c74479de2 500
Christopher Haster 0:176c74479de2 501 /** Create a FuncPtr with a method
Christopher Haster 0:176c74479de2 502 * @param obj Pointer to object to invoke method on
Christopher Haster 0:176c74479de2 503 * @param func Method to attach
Christopher Haster 0:176c74479de2 504 */
Christopher Haster 0:176c74479de2 505 template<typename T>
Christopher Haster 0:176c74479de2 506 FuncPtr(T *obj, R (T::*func)(A0, A1)) {
Christopher Haster 0:176c74479de2 507 attach(obj, func);
Christopher Haster 0:176c74479de2 508 }
Christopher Haster 0:176c74479de2 509
Christopher Haster 0:176c74479de2 510 /** Create a FuncPtr with a function object
Christopher Haster 0:176c74479de2 511 * @param func Function object to attach
Christopher Haster 0:176c74479de2 512 */
Christopher Haster 0:176c74479de2 513 template<typename T>
Christopher Haster 0:176c74479de2 514 FuncPtr(T *func) {
Christopher Haster 0:176c74479de2 515 attach(func, &T::operator());
Christopher Haster 0:176c74479de2 516 }
Christopher Haster 0:176c74479de2 517
Christopher Haster 0:176c74479de2 518 /** Create a FuncPtr with another FuncPtr
Christopher Haster 0:176c74479de2 519 * @param func FuncPtr to attach
Christopher Haster 0:176c74479de2 520 */
Christopher Haster 0:176c74479de2 521 FuncPtr(const FuncPtr<R(A0, A1)> &func) {
Christopher Haster 0:176c74479de2 522 attach(func);
Christopher Haster 0:176c74479de2 523 }
Christopher Haster 0:176c74479de2 524
Christopher Haster 0:176c74479de2 525 /** Attach a static function
Christopher Haster 0:176c74479de2 526 * @param func Static function to attach
Christopher Haster 0:176c74479de2 527 */
Christopher Haster 0:176c74479de2 528 void attach(R (*func)(A0, A1)) {
Christopher Haster 0:176c74479de2 529 memcpy(&_func, &func, sizeof func);
Christopher Haster 6:b5f0551273f6 530 _thunk = func ? &FuncPtr::_staticthunk : 0;
Christopher Haster 0:176c74479de2 531 }
Christopher Haster 0:176c74479de2 532
Christopher Haster 0:176c74479de2 533 /** Attach a static function with a bound pointer
Christopher Haster 0:176c74479de2 534 * @param obj Pointer to object to bind to function
Christopher Haster 0:176c74479de2 535 * @param func Static function to attach
Christopher Haster 0:176c74479de2 536 */
Christopher Haster 0:176c74479de2 537 template <typename T>
Christopher Haster 0:176c74479de2 538 void attach(T *obj, R (*func)(T*, A0, A1)) {
Christopher Haster 0:176c74479de2 539 _obj = static_cast<void*>(obj);
Christopher Haster 0:176c74479de2 540 memcpy(&_func, &func, sizeof func);
Christopher Haster 0:176c74479de2 541 _thunk = &FuncPtr::_boundthunk<T>;
Christopher Haster 0:176c74479de2 542 }
Christopher Haster 0:176c74479de2 543
Christopher Haster 0:176c74479de2 544 /** Attach a method
Christopher Haster 0:176c74479de2 545 * @param obj Pointer to object to invoke method on
Christopher Haster 0:176c74479de2 546 * @param func Method to attach
Christopher Haster 0:176c74479de2 547 */
Christopher Haster 0:176c74479de2 548 template<typename T>
Christopher Haster 0:176c74479de2 549 void attach(T *obj, R (T::*func)(A0, A1)) {
Christopher Haster 0:176c74479de2 550 _obj = static_cast<void*>(obj);
Christopher Haster 0:176c74479de2 551 memcpy(&_func, &func, sizeof func);
Christopher Haster 0:176c74479de2 552 _thunk = &FuncPtr::_methodthunk<T>;
Christopher Haster 0:176c74479de2 553 }
Christopher Haster 0:176c74479de2 554
Christopher Haster 0:176c74479de2 555 /** Attach a function object
Christopher Haster 0:176c74479de2 556 * @param func Function object to attach
Christopher Haster 0:176c74479de2 557 */
Christopher Haster 0:176c74479de2 558 template<typename T>
Christopher Haster 0:176c74479de2 559 void attach(T *func) {
Christopher Haster 0:176c74479de2 560 attach(func, &T::operator());
Christopher Haster 0:176c74479de2 561 }
Christopher Haster 0:176c74479de2 562
Christopher Haster 0:176c74479de2 563 /** Attach a FuncPtr
Christopher Haster 0:176c74479de2 564 * @param func The FuncPtr to attach
Christopher Haster 0:176c74479de2 565 */
Christopher Haster 0:176c74479de2 566 void attach(const FuncPtr<R(A0, A1)> &func) {
Christopher Haster 0:176c74479de2 567 _obj = func._obj;
Christopher Haster 0:176c74479de2 568 memcpy(&_func, &func._func, sizeof _func);
Christopher Haster 0:176c74479de2 569 _thunk = func._thunk;
Christopher Haster 0:176c74479de2 570 }
Christopher Haster 0:176c74479de2 571
Christopher Haster 2:56e1906f7103 572 /** Call the attached function
Christopher Haster 0:176c74479de2 573 */
Christopher Haster 0:176c74479de2 574 R call(A0 a0, A1 a1) {
Christopher Haster 0:176c74479de2 575 return _thunk(_obj, &_func, a0, a1);
Christopher Haster 0:176c74479de2 576 }
Christopher Haster 0:176c74479de2 577
Christopher Haster 2:56e1906f7103 578 /** Call the attached function
Christopher Haster 0:176c74479de2 579 */
Christopher Haster 0:176c74479de2 580 R operator()(A0 a0, A1 a1) {
Christopher Haster 0:176c74479de2 581 return call(a0, a1);
Christopher Haster 0:176c74479de2 582 }
Christopher Haster 0:176c74479de2 583
Christopher Haster 0:176c74479de2 584 /** Test if function has been attached
Christopher Haster 0:176c74479de2 585 */
Christopher Haster 8:71037a47492d 586 operator bool() const {
Christopher Haster 6:b5f0551273f6 587 return _thunk;
Christopher Haster 0:176c74479de2 588 }
Christopher Haster 0:176c74479de2 589
Christopher Haster 1:9c28068feddc 590 /** Static thunk for passing as C-style function
Christopher Haster 2:56e1906f7103 591 * @param func FuncPtr to call passed as void pointer
Christopher Haster 1:9c28068feddc 592 */
Christopher Haster 2:56e1906f7103 593 static R thunk(void *func, A0 a0, A1 a1) {
Christopher Haster 2:56e1906f7103 594 return static_cast<FuncPtr<R(A0, A1)>*>(func)
Christopher Haster 1:9c28068feddc 595 ->call(a0, a1);
Christopher Haster 1:9c28068feddc 596 }
Christopher Haster 1:9c28068feddc 597
Christopher Haster 0:176c74479de2 598 private:
Christopher Haster 0:176c74479de2 599 // Internal thunks for various function types
Christopher Haster 0:176c74479de2 600 static R _staticthunk(void*, void *func, A0 a0, A1 a1) {
Christopher Haster 0:176c74479de2 601 return (*reinterpret_cast<R (**)(A0, A1)>(func))
Christopher Haster 0:176c74479de2 602 (a0, a1);
Christopher Haster 0:176c74479de2 603 }
Christopher Haster 0:176c74479de2 604
Christopher Haster 0:176c74479de2 605 template<typename T>
Christopher Haster 0:176c74479de2 606 static R _boundthunk(void *obj, void *func, A0 a0, A1 a1) {
Christopher Haster 0:176c74479de2 607 return (*reinterpret_cast<R (**)(T*, A0, A1)>(func))
Christopher Haster 0:176c74479de2 608 (static_cast<T*>(obj), a0, a1);
Christopher Haster 0:176c74479de2 609 }
Christopher Haster 0:176c74479de2 610
Christopher Haster 0:176c74479de2 611 template<typename T>
Christopher Haster 0:176c74479de2 612 static R _methodthunk(void *obj, void *func, A0 a0, A1 a1) {
Christopher Haster 0:176c74479de2 613 return (static_cast<T*>(obj)->*
Christopher Haster 0:176c74479de2 614 (*reinterpret_cast<R (T::**)(A0, A1)>(func)))
Christopher Haster 0:176c74479de2 615 (a0, a1);
Christopher Haster 0:176c74479de2 616 }
Christopher Haster 0:176c74479de2 617
Christopher Haster 0:176c74479de2 618 // Stored as pointer to function and pointer to optional object
Christopher Haster 0:176c74479de2 619 // Function pointer is stored as union of possible function types
Christopher Haster 0:176c74479de2 620 // to garuntee proper size and alignment
Christopher Haster 0:176c74479de2 621 struct _class;
Christopher Haster 0:176c74479de2 622 union {
Christopher Haster 0:176c74479de2 623 void (*_staticfunc)();
Christopher Haster 0:176c74479de2 624 void (*_boundfunc)(_class *);
Christopher Haster 0:176c74479de2 625 void (_class::*_methodfunc)();
Christopher Haster 0:176c74479de2 626 } _func;
Christopher Haster 0:176c74479de2 627
Christopher Haster 11:035e0728d927 628 void *_obj;
Christopher Haster 11:035e0728d927 629
Christopher Haster 0:176c74479de2 630 // Thunk registered on attach to dispatch calls
Christopher Haster 0:176c74479de2 631 R (*_thunk)(void*, void*, A0, A1);
Christopher Haster 0:176c74479de2 632 };
Christopher Haster 0:176c74479de2 633
Christopher Haster 0:176c74479de2 634 /** Flexible templated function class
Christopher Haster 0:176c74479de2 635 */
Christopher Haster 0:176c74479de2 636 template <typename R, typename A0>
Christopher Haster 0:176c74479de2 637 class FuncPtr<R(A0)> {
Christopher Haster 0:176c74479de2 638 public:
Christopher Haster 0:176c74479de2 639 /** Create a FuncPtr with a static function
Christopher Haster 0:176c74479de2 640 * @param func Static function to attach
Christopher Haster 0:176c74479de2 641 */
Christopher Haster 0:176c74479de2 642 FuncPtr(R (*func)(A0) = 0) {
Christopher Haster 0:176c74479de2 643 attach(func);
Christopher Haster 0:176c74479de2 644 }
Christopher Haster 0:176c74479de2 645
Christopher Haster 0:176c74479de2 646 /** Create a FuncPtr with a static function and bound pointer
Christopher Haster 0:176c74479de2 647 * @param obj Pointer to object to bind to function
Christopher Haster 0:176c74479de2 648 * @param func Static function to attach
Christopher Haster 0:176c74479de2 649 */
Christopher Haster 0:176c74479de2 650 template<typename T>
Christopher Haster 0:176c74479de2 651 FuncPtr(T *obj, R (*func)(T*, A0)) {
Christopher Haster 0:176c74479de2 652 attach(obj, func);
Christopher Haster 0:176c74479de2 653 }
Christopher Haster 0:176c74479de2 654
Christopher Haster 0:176c74479de2 655 /** Create a FuncPtr with a method
Christopher Haster 0:176c74479de2 656 * @param obj Pointer to object to invoke method on
Christopher Haster 0:176c74479de2 657 * @param func Method to attach
Christopher Haster 0:176c74479de2 658 */
Christopher Haster 0:176c74479de2 659 template<typename T>
Christopher Haster 0:176c74479de2 660 FuncPtr(T *obj, R (T::*func)(A0)) {
Christopher Haster 0:176c74479de2 661 attach(obj, func);
Christopher Haster 0:176c74479de2 662 }
Christopher Haster 0:176c74479de2 663
Christopher Haster 0:176c74479de2 664 /** Create a FuncPtr with a function object
Christopher Haster 0:176c74479de2 665 * @param func Function object to attach
Christopher Haster 0:176c74479de2 666 */
Christopher Haster 0:176c74479de2 667 template<typename T>
Christopher Haster 0:176c74479de2 668 FuncPtr(T *func) {
Christopher Haster 0:176c74479de2 669 attach(func, &T::operator());
Christopher Haster 0:176c74479de2 670 }
Christopher Haster 0:176c74479de2 671
Christopher Haster 0:176c74479de2 672 /** Create a FuncPtr with another FuncPtr
Christopher Haster 0:176c74479de2 673 * @param func FuncPtr to attach
Christopher Haster 0:176c74479de2 674 */
Christopher Haster 0:176c74479de2 675 FuncPtr(const FuncPtr<R(A0)> &func) {
Christopher Haster 0:176c74479de2 676 attach(func);
Christopher Haster 0:176c74479de2 677 }
Christopher Haster 0:176c74479de2 678
Christopher Haster 0:176c74479de2 679 /** Attach a static function
Christopher Haster 0:176c74479de2 680 * @param func Static function to attach
Christopher Haster 0:176c74479de2 681 */
Christopher Haster 0:176c74479de2 682 void attach(R (*func)(A0)) {
Christopher Haster 0:176c74479de2 683 memcpy(&_func, &func, sizeof func);
Christopher Haster 6:b5f0551273f6 684 _thunk = func ? &FuncPtr::_staticthunk : 0;
Christopher Haster 0:176c74479de2 685 }
Christopher Haster 0:176c74479de2 686
Christopher Haster 0:176c74479de2 687 /** Attach a static function with a bound pointer
Christopher Haster 0:176c74479de2 688 * @param obj Pointer to object to bind to function
Christopher Haster 0:176c74479de2 689 * @param func Static function to attach
Christopher Haster 0:176c74479de2 690 */
Christopher Haster 0:176c74479de2 691 template <typename T>
Christopher Haster 0:176c74479de2 692 void attach(T *obj, R (*func)(T*, A0)) {
Christopher Haster 0:176c74479de2 693 _obj = static_cast<void*>(obj);
Christopher Haster 0:176c74479de2 694 memcpy(&_func, &func, sizeof func);
Christopher Haster 0:176c74479de2 695 _thunk = &FuncPtr::_boundthunk<T>;
Christopher Haster 0:176c74479de2 696 }
Christopher Haster 0:176c74479de2 697
Christopher Haster 0:176c74479de2 698 /** Attach a method
Christopher Haster 0:176c74479de2 699 * @param obj Pointer to object to invoke method on
Christopher Haster 0:176c74479de2 700 * @param func Method to attach
Christopher Haster 0:176c74479de2 701 */
Christopher Haster 0:176c74479de2 702 template<typename T>
Christopher Haster 0:176c74479de2 703 void attach(T *obj, R (T::*func)(A0)) {
Christopher Haster 0:176c74479de2 704 _obj = static_cast<void*>(obj);
Christopher Haster 0:176c74479de2 705 memcpy(&_func, &func, sizeof func);
Christopher Haster 0:176c74479de2 706 _thunk = &FuncPtr::_methodthunk<T>;
Christopher Haster 0:176c74479de2 707 }
Christopher Haster 0:176c74479de2 708
Christopher Haster 0:176c74479de2 709 /** Attach a function object
Christopher Haster 0:176c74479de2 710 * @param func Function object to attach
Christopher Haster 0:176c74479de2 711 */
Christopher Haster 0:176c74479de2 712 template<typename T>
Christopher Haster 0:176c74479de2 713 void attach(T *func) {
Christopher Haster 0:176c74479de2 714 attach(func, &T::operator());
Christopher Haster 0:176c74479de2 715 }
Christopher Haster 0:176c74479de2 716
Christopher Haster 0:176c74479de2 717 /** Attach a FuncPtr
Christopher Haster 0:176c74479de2 718 * @param func The FuncPtr to attach
Christopher Haster 0:176c74479de2 719 */
Christopher Haster 0:176c74479de2 720 void attach(const FuncPtr<R(A0)> &func) {
Christopher Haster 0:176c74479de2 721 _obj = func._obj;
Christopher Haster 0:176c74479de2 722 memcpy(&_func, &func._func, sizeof _func);
Christopher Haster 0:176c74479de2 723 _thunk = func._thunk;
Christopher Haster 0:176c74479de2 724 }
Christopher Haster 0:176c74479de2 725
Christopher Haster 2:56e1906f7103 726 /** Call the attached function
Christopher Haster 0:176c74479de2 727 */
Christopher Haster 0:176c74479de2 728 R call(A0 a0) {
Christopher Haster 0:176c74479de2 729 return _thunk(_obj, &_func, a0);
Christopher Haster 0:176c74479de2 730 }
Christopher Haster 0:176c74479de2 731
Christopher Haster 2:56e1906f7103 732 /** Call the attached function
Christopher Haster 0:176c74479de2 733 */
Christopher Haster 0:176c74479de2 734 R operator()(A0 a0) {
Christopher Haster 0:176c74479de2 735 return call(a0);
Christopher Haster 0:176c74479de2 736 }
Christopher Haster 0:176c74479de2 737
Christopher Haster 0:176c74479de2 738 /** Test if function has been attached
Christopher Haster 0:176c74479de2 739 */
Christopher Haster 8:71037a47492d 740 operator bool() const {
Christopher Haster 6:b5f0551273f6 741 return _thunk;
Christopher Haster 0:176c74479de2 742 }
Christopher Haster 0:176c74479de2 743
Christopher Haster 1:9c28068feddc 744 /** Static thunk for passing as C-style function
Christopher Haster 2:56e1906f7103 745 * @param func FuncPtr to call passed as void pointer
Christopher Haster 1:9c28068feddc 746 */
Christopher Haster 2:56e1906f7103 747 static R thunk(void *func, A0 a0) {
Christopher Haster 2:56e1906f7103 748 return static_cast<FuncPtr<R(A0)>*>(func)
Christopher Haster 1:9c28068feddc 749 ->call(a0);
Christopher Haster 1:9c28068feddc 750 }
Christopher Haster 1:9c28068feddc 751
Christopher Haster 0:176c74479de2 752 private:
Christopher Haster 0:176c74479de2 753 // Internal thunks for various function types
Christopher Haster 0:176c74479de2 754 static R _staticthunk(void*, void *func, A0 a0) {
Christopher Haster 0:176c74479de2 755 return (*reinterpret_cast<R (**)(A0)>(func))
Christopher Haster 0:176c74479de2 756 (a0);
Christopher Haster 0:176c74479de2 757 }
Christopher Haster 0:176c74479de2 758
Christopher Haster 0:176c74479de2 759 template<typename T>
Christopher Haster 0:176c74479de2 760 static R _boundthunk(void *obj, void *func, A0 a0) {
Christopher Haster 0:176c74479de2 761 return (*reinterpret_cast<R (**)(T*, A0)>(func))
Christopher Haster 0:176c74479de2 762 (static_cast<T*>(obj), a0);
Christopher Haster 0:176c74479de2 763 }
Christopher Haster 0:176c74479de2 764
Christopher Haster 0:176c74479de2 765 template<typename T>
Christopher Haster 0:176c74479de2 766 static R _methodthunk(void *obj, void *func, A0 a0) {
Christopher Haster 0:176c74479de2 767 return (static_cast<T*>(obj)->*
Christopher Haster 0:176c74479de2 768 (*reinterpret_cast<R (T::**)(A0)>(func)))
Christopher Haster 0:176c74479de2 769 (a0);
Christopher Haster 0:176c74479de2 770 }
Christopher Haster 0:176c74479de2 771
Christopher Haster 0:176c74479de2 772 // Stored as pointer to function and pointer to optional object
Christopher Haster 0:176c74479de2 773 // Function pointer is stored as union of possible function types
Christopher Haster 0:176c74479de2 774 // to garuntee proper size and alignment
Christopher Haster 0:176c74479de2 775 struct _class;
Christopher Haster 0:176c74479de2 776 union {
Christopher Haster 0:176c74479de2 777 void (*_staticfunc)();
Christopher Haster 0:176c74479de2 778 void (*_boundfunc)(_class *);
Christopher Haster 0:176c74479de2 779 void (_class::*_methodfunc)();
Christopher Haster 0:176c74479de2 780 } _func;
Christopher Haster 0:176c74479de2 781
Christopher Haster 11:035e0728d927 782 void *_obj;
Christopher Haster 11:035e0728d927 783
Christopher Haster 0:176c74479de2 784 // Thunk registered on attach to dispatch calls
Christopher Haster 0:176c74479de2 785 R (*_thunk)(void*, void*, A0);
Christopher Haster 0:176c74479de2 786 };
Christopher Haster 0:176c74479de2 787
Christopher Haster 0:176c74479de2 788 /** Flexible templated function class
Christopher Haster 0:176c74479de2 789 */
Christopher Haster 0:176c74479de2 790 template <typename R>
Christopher Haster 0:176c74479de2 791 class FuncPtr<R()> {
Christopher Haster 0:176c74479de2 792 public:
Christopher Haster 0:176c74479de2 793 /** Create a FuncPtr with a static function
Christopher Haster 0:176c74479de2 794 * @param func Static function to attach
Christopher Haster 0:176c74479de2 795 */
Christopher Haster 0:176c74479de2 796 FuncPtr(R (*func)() = 0) {
Christopher Haster 0:176c74479de2 797 attach(func);
Christopher Haster 0:176c74479de2 798 }
Christopher Haster 0:176c74479de2 799
Christopher Haster 0:176c74479de2 800 /** Create a FuncPtr with a static function and bound pointer
Christopher Haster 0:176c74479de2 801 * @param obj Pointer to object to bind to function
Christopher Haster 0:176c74479de2 802 * @param func Static function to attach
Christopher Haster 0:176c74479de2 803 */
Christopher Haster 0:176c74479de2 804 template<typename T>
Christopher Haster 0:176c74479de2 805 FuncPtr(T *obj, R (*func)(T*)) {
Christopher Haster 0:176c74479de2 806 attach(obj, func);
Christopher Haster 0:176c74479de2 807 }
Christopher Haster 0:176c74479de2 808
Christopher Haster 0:176c74479de2 809 /** Create a FuncPtr with a method
Christopher Haster 0:176c74479de2 810 * @param obj Pointer to object to invoke method on
Christopher Haster 0:176c74479de2 811 * @param func Method to attach
Christopher Haster 0:176c74479de2 812 */
Christopher Haster 0:176c74479de2 813 template<typename T>
Christopher Haster 0:176c74479de2 814 FuncPtr(T *obj, R (T::*func)()) {
Christopher Haster 0:176c74479de2 815 attach(obj, func);
Christopher Haster 0:176c74479de2 816 }
Christopher Haster 0:176c74479de2 817
Christopher Haster 0:176c74479de2 818 /** Create a FuncPtr with a function object
Christopher Haster 0:176c74479de2 819 * @param func Function object to attach
Christopher Haster 0:176c74479de2 820 */
Christopher Haster 0:176c74479de2 821 template<typename T>
Christopher Haster 0:176c74479de2 822 FuncPtr(T *func) {
Christopher Haster 0:176c74479de2 823 attach(func, &T::operator());
Christopher Haster 0:176c74479de2 824 }
Christopher Haster 0:176c74479de2 825
Christopher Haster 0:176c74479de2 826 /** Create a FuncPtr with another FuncPtr
Christopher Haster 0:176c74479de2 827 * @param func FuncPtr to attach
Christopher Haster 0:176c74479de2 828 */
Christopher Haster 0:176c74479de2 829 FuncPtr(const FuncPtr<R()> &func) {
Christopher Haster 0:176c74479de2 830 attach(func);
Christopher Haster 0:176c74479de2 831 }
Christopher Haster 0:176c74479de2 832
Christopher Haster 0:176c74479de2 833 /** Attach a static function
Christopher Haster 0:176c74479de2 834 * @param func Static function to attach
Christopher Haster 0:176c74479de2 835 */
Christopher Haster 0:176c74479de2 836 void attach(R (*func)()) {
Christopher Haster 0:176c74479de2 837 memcpy(&_func, &func, sizeof func);
Christopher Haster 6:b5f0551273f6 838 _thunk = func ? &FuncPtr::_staticthunk : 0;
Christopher Haster 0:176c74479de2 839 }
Christopher Haster 0:176c74479de2 840
Christopher Haster 0:176c74479de2 841 /** Attach a static function with a bound pointer
Christopher Haster 0:176c74479de2 842 * @param obj Pointer to object to bind to function
Christopher Haster 0:176c74479de2 843 * @param func Static function to attach
Christopher Haster 0:176c74479de2 844 */
Christopher Haster 0:176c74479de2 845 template <typename T>
Christopher Haster 0:176c74479de2 846 void attach(T *obj, R (*func)(T*)) {
Christopher Haster 0:176c74479de2 847 _obj = static_cast<void*>(obj);
Christopher Haster 0:176c74479de2 848 memcpy(&_func, &func, sizeof func);
Christopher Haster 0:176c74479de2 849 _thunk = &FuncPtr::_boundthunk<T>;
Christopher Haster 0:176c74479de2 850 }
Christopher Haster 0:176c74479de2 851
Christopher Haster 0:176c74479de2 852 /** Attach a method
Christopher Haster 0:176c74479de2 853 * @param obj Pointer to object to invoke method on
Christopher Haster 0:176c74479de2 854 * @param func Method to attach
Christopher Haster 0:176c74479de2 855 */
Christopher Haster 0:176c74479de2 856 template<typename T>
Christopher Haster 0:176c74479de2 857 void attach(T *obj, R (T::*func)()) {
Christopher Haster 0:176c74479de2 858 _obj = static_cast<void*>(obj);
Christopher Haster 0:176c74479de2 859 memcpy(&_func, &func, sizeof func);
Christopher Haster 0:176c74479de2 860 _thunk = &FuncPtr::_methodthunk<T>;
Christopher Haster 0:176c74479de2 861 }
Christopher Haster 0:176c74479de2 862
Christopher Haster 0:176c74479de2 863 /** Attach a function object
Christopher Haster 0:176c74479de2 864 * @param func Function object to attach
Christopher Haster 0:176c74479de2 865 */
Christopher Haster 0:176c74479de2 866 template<typename T>
Christopher Haster 0:176c74479de2 867 void attach(T *func) {
Christopher Haster 0:176c74479de2 868 attach(func, &T::operator());
Christopher Haster 0:176c74479de2 869 }
Christopher Haster 0:176c74479de2 870
Christopher Haster 0:176c74479de2 871 /** Attach a FuncPtr
Christopher Haster 0:176c74479de2 872 * @param func The FuncPtr to attach
Christopher Haster 0:176c74479de2 873 */
Christopher Haster 0:176c74479de2 874 void attach(const FuncPtr<R()> &func) {
Christopher Haster 0:176c74479de2 875 _obj = func._obj;
Christopher Haster 0:176c74479de2 876 memcpy(&_func, &func._func, sizeof _func);
Christopher Haster 0:176c74479de2 877 _thunk = func._thunk;
Christopher Haster 0:176c74479de2 878 }
Christopher Haster 0:176c74479de2 879
Christopher Haster 2:56e1906f7103 880 /** Call the attached function
Christopher Haster 0:176c74479de2 881 */
Christopher Haster 0:176c74479de2 882 R call() {
Christopher Haster 0:176c74479de2 883 return _thunk(_obj, &_func);
Christopher Haster 0:176c74479de2 884 }
Christopher Haster 0:176c74479de2 885
Christopher Haster 2:56e1906f7103 886 /** Call the attached function
Christopher Haster 0:176c74479de2 887 */
Christopher Haster 0:176c74479de2 888 R operator()() {
Christopher Haster 0:176c74479de2 889 return call();
Christopher Haster 0:176c74479de2 890 }
Christopher Haster 0:176c74479de2 891
Christopher Haster 0:176c74479de2 892 /** Test if function has been attached
Christopher Haster 0:176c74479de2 893 */
Christopher Haster 8:71037a47492d 894 operator bool() const {
Christopher Haster 6:b5f0551273f6 895 return _thunk;
Christopher Haster 0:176c74479de2 896 }
Christopher Haster 0:176c74479de2 897
Christopher Haster 1:9c28068feddc 898 /** Static thunk for passing as C-style function
Christopher Haster 2:56e1906f7103 899 * @param func FuncPtr to call passed as void pointer
Christopher Haster 1:9c28068feddc 900 */
Christopher Haster 2:56e1906f7103 901 static R thunk(void *func) {
Christopher Haster 2:56e1906f7103 902 return static_cast<FuncPtr<R()>*>(func)
Christopher Haster 1:9c28068feddc 903 ->call();
Christopher Haster 1:9c28068feddc 904 }
Christopher Haster 1:9c28068feddc 905
Christopher Haster 0:176c74479de2 906 private:
Christopher Haster 0:176c74479de2 907 // Internal thunks for various function types
Christopher Haster 0:176c74479de2 908 static R _staticthunk(void*, void *func) {
Christopher Haster 0:176c74479de2 909 return (*reinterpret_cast<R (**)()>(func))
Christopher Haster 0:176c74479de2 910 ();
Christopher Haster 0:176c74479de2 911 }
Christopher Haster 0:176c74479de2 912
Christopher Haster 0:176c74479de2 913 template<typename T>
Christopher Haster 0:176c74479de2 914 static R _boundthunk(void *obj, void *func) {
Christopher Haster 0:176c74479de2 915 return (*reinterpret_cast<R (**)(T*)>(func))
Christopher Haster 0:176c74479de2 916 (static_cast<T*>(obj));
Christopher Haster 0:176c74479de2 917 }
Christopher Haster 0:176c74479de2 918
Christopher Haster 0:176c74479de2 919 template<typename T>
Christopher Haster 0:176c74479de2 920 static R _methodthunk(void *obj, void *func) {
Christopher Haster 0:176c74479de2 921 return (static_cast<T*>(obj)->*
Christopher Haster 0:176c74479de2 922 (*reinterpret_cast<R (T::**)()>(func)))
Christopher Haster 0:176c74479de2 923 ();
Christopher Haster 0:176c74479de2 924 }
Christopher Haster 0:176c74479de2 925
Christopher Haster 0:176c74479de2 926 // Stored as pointer to function and pointer to optional object
Christopher Haster 0:176c74479de2 927 // Function pointer is stored as union of possible function types
Christopher Haster 0:176c74479de2 928 // to garuntee proper size and alignment
Christopher Haster 0:176c74479de2 929 struct _class;
Christopher Haster 0:176c74479de2 930 union {
Christopher Haster 0:176c74479de2 931 void (*_staticfunc)();
Christopher Haster 0:176c74479de2 932 void (*_boundfunc)(_class *);
Christopher Haster 0:176c74479de2 933 void (_class::*_methodfunc)();
Christopher Haster 0:176c74479de2 934 } _func;
Christopher Haster 0:176c74479de2 935
Christopher Haster 11:035e0728d927 936 void *_obj;
Christopher Haster 11:035e0728d927 937
Christopher Haster 0:176c74479de2 938 // Thunk registered on attach to dispatch calls
Christopher Haster 0:176c74479de2 939 R (*_thunk)(void*, void*);
Christopher Haster 0:176c74479de2 940 };
Christopher Haster 0:176c74479de2 941
Christopher Haster 0:176c74479de2 942
Christopher Haster 0:176c74479de2 943 #endif