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:34:58 2016 -0500
Revision:
1:9c28068feddc
Parent:
0:176c74479de2
Child:
2:56e1906f7103
Added thunk function for better interoperability with C

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