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 21:15:30 2016 -0500
Revision:
13:4d8a50d4967e
Parent:
11:035e0728d927
Child:
14:79be4e700cc9
Added funcptr namespace

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