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 15:52:35 2016 -0500
Revision:
8:71037a47492d
Parent:
6:b5f0551273f6
Child:
11:035e0728d927
Standardized empty argument methods

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