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 13:25:33 2016 -0500
Revision:
0:176c74479de2
Child:
1:9c28068feddc
Added FuncPtr class

Who changed what in which revision?

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