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 20:51:55 2016 -0500
Revision:
11:035e0728d927
Parent:
8:71037a47492d
Child:
13:4d8a50d4967e
Rearranged FuncPtr to take better advantage of struct alignment

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 0:176c74479de2 20 template <typename R, typename A0, typename A1, typename A2, typename A3>
Christopher Haster 0:176c74479de2 21 class FuncPtr<R(A0, A1, A2, A3)> {
Christopher Haster 0:176c74479de2 22 public:
Christopher Haster 0:176c74479de2 23 /** Create a FuncPtr with a static function
Christopher Haster 0:176c74479de2 24 * @param func Static function to attach
Christopher Haster 0:176c74479de2 25 */
Christopher Haster 0:176c74479de2 26 FuncPtr(R (*func)(A0, A1, A2, A3) = 0) {
Christopher Haster 0:176c74479de2 27 attach(func);
Christopher Haster 0:176c74479de2 28 }
Christopher Haster 0:176c74479de2 29
Christopher Haster 0:176c74479de2 30 /** Create a FuncPtr with a static function and bound pointer
Christopher Haster 0:176c74479de2 31 * @param obj Pointer to object to bind to function
Christopher Haster 0:176c74479de2 32 * @param func Static function to attach
Christopher Haster 0:176c74479de2 33 */
Christopher Haster 0:176c74479de2 34 template<typename T>
Christopher Haster 0:176c74479de2 35 FuncPtr(T *obj, R (*func)(T*, A0, A1, A2, A3)) {
Christopher Haster 0:176c74479de2 36 attach(obj, func);
Christopher Haster 0:176c74479de2 37 }
Christopher Haster 0:176c74479de2 38
Christopher Haster 0:176c74479de2 39 /** Create a FuncPtr with a method
Christopher Haster 0:176c74479de2 40 * @param obj Pointer to object to invoke method on
Christopher Haster 0:176c74479de2 41 * @param func Method to attach
Christopher Haster 0:176c74479de2 42 */
Christopher Haster 0:176c74479de2 43 template<typename T>
Christopher Haster 0:176c74479de2 44 FuncPtr(T *obj, R (T::*func)(A0, A1, A2, A3)) {
Christopher Haster 0:176c74479de2 45 attach(obj, func);
Christopher Haster 0:176c74479de2 46 }
Christopher Haster 0:176c74479de2 47
Christopher Haster 0:176c74479de2 48 /** Create a FuncPtr with a function object
Christopher Haster 0:176c74479de2 49 * @param func Function object to attach
Christopher Haster 0:176c74479de2 50 */
Christopher Haster 0:176c74479de2 51 template<typename T>
Christopher Haster 0:176c74479de2 52 FuncPtr(T *obj) {
Christopher Haster 0:176c74479de2 53 attach(obj, &T::operator());
Christopher Haster 0:176c74479de2 54 }
Christopher Haster 0:176c74479de2 55
Christopher Haster 0:176c74479de2 56 /** Create a FuncPtr with another FuncPtr
Christopher Haster 0:176c74479de2 57 * @param func FuncPtr to attach
Christopher Haster 0:176c74479de2 58 */
Christopher Haster 0:176c74479de2 59 FuncPtr(const FuncPtr<R(A0, A1, A2, A3)> &func) {
Christopher Haster 0:176c74479de2 60 attach(func);
Christopher Haster 0:176c74479de2 61 }
Christopher Haster 0:176c74479de2 62
Christopher Haster 0:176c74479de2 63 /** Attach a static function
Christopher Haster 0:176c74479de2 64 * @param func Static function to attach
Christopher Haster 0:176c74479de2 65 */
Christopher Haster 0:176c74479de2 66 void attach(R (*func)(A0, A1, A2, A3)) {
Christopher Haster 0:176c74479de2 67 memcpy(&_func, &func, sizeof func);
Christopher Haster 6:b5f0551273f6 68 _thunk = func ? &FuncPtr::_staticthunk : 0;
Christopher Haster 0:176c74479de2 69 }
Christopher Haster 0:176c74479de2 70
Christopher Haster 0:176c74479de2 71 /** Attach a static function with a bound pointer
Christopher Haster 0:176c74479de2 72 * @param obj Pointer to object to bind to function
Christopher Haster 0:176c74479de2 73 * @param func Static function to attach
Christopher Haster 0:176c74479de2 74 */
Christopher Haster 0:176c74479de2 75 template <typename T>
Christopher Haster 0:176c74479de2 76 void attach(T *obj, R (*func)(T*, A0, A1, A2, A3)) {
Christopher Haster 0:176c74479de2 77 _obj = static_cast<void*>(obj);
Christopher Haster 0:176c74479de2 78 memcpy(&_func, &func, sizeof func);
Christopher Haster 0:176c74479de2 79 _thunk = &FuncPtr::_boundthunk<T>;
Christopher Haster 0:176c74479de2 80 }
Christopher Haster 0:176c74479de2 81
Christopher Haster 0:176c74479de2 82 /** Attach a method
Christopher Haster 0:176c74479de2 83 * @param obj Pointer to object to invoke method on
Christopher Haster 0:176c74479de2 84 * @param func Method to attach
Christopher Haster 0:176c74479de2 85 */
Christopher Haster 0:176c74479de2 86 template<typename T>
Christopher Haster 0:176c74479de2 87 void attach(T *obj, R (T::*func)(A0, A1, A2, A3)) {
Christopher Haster 0:176c74479de2 88 _obj = static_cast<void*>(obj);
Christopher Haster 0:176c74479de2 89 memcpy(&_func, &func, sizeof func);
Christopher Haster 0:176c74479de2 90 _thunk = &FuncPtr::_methodthunk<T>;
Christopher Haster 0:176c74479de2 91 }
Christopher Haster 0:176c74479de2 92
Christopher Haster 0:176c74479de2 93 /** Attach a function object
Christopher Haster 0:176c74479de2 94 * @param func Function object to attach
Christopher Haster 0:176c74479de2 95 */
Christopher Haster 0:176c74479de2 96 template<typename T>
Christopher Haster 0:176c74479de2 97 void attach(T *func) {
Christopher Haster 0:176c74479de2 98 attach(func, &T::operator());
Christopher Haster 0:176c74479de2 99 }
Christopher Haster 0:176c74479de2 100
Christopher Haster 0:176c74479de2 101 /** Attach a FuncPtr
Christopher Haster 0:176c74479de2 102 * @param func The FuncPtr to attach
Christopher Haster 0:176c74479de2 103 */
Christopher Haster 0:176c74479de2 104 void attach(const FuncPtr<R(A0, A1, A2, A3)> &func) {
Christopher Haster 0:176c74479de2 105 _obj = func._obj;
Christopher Haster 0:176c74479de2 106 memcpy(&_func, &func._func, sizeof _func);
Christopher Haster 0:176c74479de2 107 _thunk = func._thunk;
Christopher Haster 0:176c74479de2 108 }
Christopher Haster 0:176c74479de2 109
Christopher Haster 2:56e1906f7103 110 /** Call the attached function
Christopher Haster 0:176c74479de2 111 */
Christopher Haster 0:176c74479de2 112 R call(A0 a0, A1 a1, A2 a2, A3 a3) {
Christopher Haster 0:176c74479de2 113 return _thunk(_obj, &_func, a0, a1, a2, a3);
Christopher Haster 0:176c74479de2 114 }
Christopher Haster 0:176c74479de2 115
Christopher Haster 2:56e1906f7103 116 /** Call the attached function
Christopher Haster 0:176c74479de2 117 */
Christopher Haster 0:176c74479de2 118 R operator()(A0 a0, A1 a1, A2 a2, A3 a3) {
Christopher Haster 0:176c74479de2 119 return call(a0, a1, a2, a3);
Christopher Haster 0:176c74479de2 120 }
Christopher Haster 0:176c74479de2 121
Christopher Haster 0:176c74479de2 122 /** Test if function has been attached
Christopher Haster 0:176c74479de2 123 */
Christopher Haster 8:71037a47492d 124 operator bool() const {
Christopher Haster 6:b5f0551273f6 125 return _thunk;
Christopher Haster 0:176c74479de2 126 }
Christopher Haster 0:176c74479de2 127
Christopher Haster 1:9c28068feddc 128 /** Static thunk for passing as C-style function
Christopher Haster 2:56e1906f7103 129 * @param func FuncPtr to call passed as void pointer
Christopher Haster 1:9c28068feddc 130 */
Christopher Haster 2:56e1906f7103 131 static R thunk(void *func, A0 a0, A1 a1, A2 a2, A3 a3) {
Christopher Haster 2:56e1906f7103 132 return static_cast<FuncPtr<R(A0, A1, A2, A3)>*>(func)
Christopher Haster 1:9c28068feddc 133 ->call(a0, a1, a2, a3);
Christopher Haster 1:9c28068feddc 134 }
Christopher Haster 1:9c28068feddc 135
Christopher Haster 0:176c74479de2 136 private:
Christopher Haster 0:176c74479de2 137 // Internal thunks for various function types
Christopher Haster 0:176c74479de2 138 static R _staticthunk(void*, void *func, A0 a0, A1 a1, A2 a2, A3 a3) {
Christopher Haster 0:176c74479de2 139 return (*reinterpret_cast<R (**)(A0, A1, A2, A3)>(func))
Christopher Haster 0:176c74479de2 140 (a0, a1, a2, a3);
Christopher Haster 0:176c74479de2 141 }
Christopher Haster 0:176c74479de2 142
Christopher Haster 0:176c74479de2 143 template<typename T>
Christopher Haster 0:176c74479de2 144 static R _boundthunk(void *obj, void *func, A0 a0, A1 a1, A2 a2, A3 a3) {
Christopher Haster 0:176c74479de2 145 return (*reinterpret_cast<R (**)(T*, A0, A1, A2, A3)>(func))
Christopher Haster 0:176c74479de2 146 (static_cast<T*>(obj), a0, a1, a2, a3);
Christopher Haster 0:176c74479de2 147 }
Christopher Haster 0:176c74479de2 148
Christopher Haster 0:176c74479de2 149 template<typename T>
Christopher Haster 0:176c74479de2 150 static R _methodthunk(void *obj, void *func, A0 a0, A1 a1, A2 a2, A3 a3) {
Christopher Haster 0:176c74479de2 151 return (static_cast<T*>(obj)->*
Christopher Haster 0:176c74479de2 152 (*reinterpret_cast<R (T::**)(A0, A1, A2, A3)>(func)))
Christopher Haster 0:176c74479de2 153 (a0, a1, a2, a3);
Christopher Haster 0:176c74479de2 154 }
Christopher Haster 0:176c74479de2 155
Christopher Haster 0:176c74479de2 156 // Stored as pointer to function and pointer to optional object
Christopher Haster 0:176c74479de2 157 // Function pointer is stored as union of possible function types
Christopher Haster 0:176c74479de2 158 // to garuntee proper size and alignment
Christopher Haster 0:176c74479de2 159 struct _class;
Christopher Haster 0:176c74479de2 160 union {
Christopher Haster 0:176c74479de2 161 void (*_staticfunc)();
Christopher Haster 0:176c74479de2 162 void (*_boundfunc)(_class *);
Christopher Haster 0:176c74479de2 163 void (_class::*_methodfunc)();
Christopher Haster 0:176c74479de2 164 } _func;
Christopher Haster 0:176c74479de2 165
Christopher Haster 11:035e0728d927 166 void *_obj;
Christopher Haster 11:035e0728d927 167
Christopher Haster 0:176c74479de2 168 // Thunk registered on attach to dispatch calls
Christopher Haster 0:176c74479de2 169 R (*_thunk)(void*, void*, A0, A1, A2, A3);
Christopher Haster 0:176c74479de2 170 };
Christopher Haster 0:176c74479de2 171
Christopher Haster 0:176c74479de2 172 /** Flexible templated function class
Christopher Haster 0:176c74479de2 173 */
Christopher Haster 0:176c74479de2 174 template <typename R, typename A0, typename A1, typename A2>
Christopher Haster 0:176c74479de2 175 class FuncPtr<R(A0, A1, A2)> {
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) = 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)) {
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)) {
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 *func) {
Christopher Haster 0:176c74479de2 207 attach(func, &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)> &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)) {
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)) {
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)) {
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)> &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) {
Christopher Haster 0:176c74479de2 267 return _thunk(_obj, &_func, a0, a1, a2);
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) {
Christopher Haster 0:176c74479de2 273 return call(a0, a1, a2);
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) {
Christopher Haster 2:56e1906f7103 286 return static_cast<FuncPtr<R(A0, A1, A2)>*>(func)
Christopher Haster 1:9c28068feddc 287 ->call(a0, a1, a2);
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) {
Christopher Haster 0:176c74479de2 293 return (*reinterpret_cast<R (**)(A0, A1, A2)>(func))
Christopher Haster 0:176c74479de2 294 (a0, a1, a2);
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) {
Christopher Haster 0:176c74479de2 299 return (*reinterpret_cast<R (**)(T*, A0, A1, A2)>(func))
Christopher Haster 0:176c74479de2 300 (static_cast<T*>(obj), a0, a1, a2);
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) {
Christopher Haster 0:176c74479de2 305 return (static_cast<T*>(obj)->*
Christopher Haster 0:176c74479de2 306 (*reinterpret_cast<R (T::**)(A0, A1, A2)>(func)))
Christopher Haster 0:176c74479de2 307 (a0, a1, a2);
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);
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>
Christopher Haster 0:176c74479de2 329 class FuncPtr<R(A0, A1)> {
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) = 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)) {
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)) {
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)> &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)) {
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)) {
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)) {
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)> &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) {
Christopher Haster 0:176c74479de2 421 return _thunk(_obj, &_func, a0, a1);
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) {
Christopher Haster 0:176c74479de2 427 return call(a0, a1);
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) {
Christopher Haster 2:56e1906f7103 440 return static_cast<FuncPtr<R(A0, A1)>*>(func)
Christopher Haster 1:9c28068feddc 441 ->call(a0, a1);
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) {
Christopher Haster 0:176c74479de2 447 return (*reinterpret_cast<R (**)(A0, A1)>(func))
Christopher Haster 0:176c74479de2 448 (a0, a1);
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) {
Christopher Haster 0:176c74479de2 453 return (*reinterpret_cast<R (**)(T*, A0, A1)>(func))
Christopher Haster 0:176c74479de2 454 (static_cast<T*>(obj), a0, a1);
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) {
Christopher Haster 0:176c74479de2 459 return (static_cast<T*>(obj)->*
Christopher Haster 0:176c74479de2 460 (*reinterpret_cast<R (T::**)(A0, A1)>(func)))
Christopher Haster 0:176c74479de2 461 (a0, a1);
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);
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>
Christopher Haster 0:176c74479de2 483 class FuncPtr<R(A0)> {
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) = 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)) {
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)) {
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)> &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)) {
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)) {
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)) {
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)> &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) {
Christopher Haster 0:176c74479de2 575 return _thunk(_obj, &_func, a0);
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) {
Christopher Haster 0:176c74479de2 581 return call(a0);
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) {
Christopher Haster 2:56e1906f7103 594 return static_cast<FuncPtr<R(A0)>*>(func)
Christopher Haster 1:9c28068feddc 595 ->call(a0);
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) {
Christopher Haster 0:176c74479de2 601 return (*reinterpret_cast<R (**)(A0)>(func))
Christopher Haster 0:176c74479de2 602 (a0);
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) {
Christopher Haster 0:176c74479de2 607 return (*reinterpret_cast<R (**)(T*, A0)>(func))
Christopher Haster 0:176c74479de2 608 (static_cast<T*>(obj), a0);
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) {
Christopher Haster 0:176c74479de2 613 return (static_cast<T*>(obj)->*
Christopher Haster 0:176c74479de2 614 (*reinterpret_cast<R (T::**)(A0)>(func)))
Christopher Haster 0:176c74479de2 615 (a0);
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);
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>
Christopher Haster 0:176c74479de2 637 class FuncPtr<R()> {
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)() = 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*)) {
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)()) {
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()> &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)()) {
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*)) {
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)()) {
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()> &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() {
Christopher Haster 0:176c74479de2 729 return _thunk(_obj, &_func);
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()() {
Christopher Haster 0:176c74479de2 735 return call();
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) {
Christopher Haster 2:56e1906f7103 748 return static_cast<FuncPtr<R()>*>(func)
Christopher Haster 1:9c28068feddc 749 ->call();
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) {
Christopher Haster 0:176c74479de2 755 return (*reinterpret_cast<R (**)()>(func))
Christopher Haster 0:176c74479de2 756 ();
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) {
Christopher Haster 0:176c74479de2 761 return (*reinterpret_cast<R (**)(T*)>(func))
Christopher Haster 0:176c74479de2 762 (static_cast<T*>(obj));
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) {
Christopher Haster 0:176c74479de2 767 return (static_cast<T*>(obj)->*
Christopher Haster 0:176c74479de2 768 (*reinterpret_cast<R (T::**)()>(func)))
Christopher Haster 0:176c74479de2 769 ();
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*);
Christopher Haster 0:176c74479de2 786 };
Christopher Haster 0:176c74479de2 787
Christopher Haster 0:176c74479de2 788
Christopher Haster 0:176c74479de2 789 #endif