Flexible templated function class and related utilities that avoid dynamic memory allocation without limiting functionality
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);
Thunker.h@18:a0fde14b6c39, 2016-04-17 (annotated)
- Committer:
- Christopher Haster
- Date:
- Sun Apr 17 23:38:04 2016 -0500
- Revision:
- 18:a0fde14b6c39
- Parent:
- 14:79be4e700cc9
Increase to 5 args
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Christopher Haster |
9:89aeb1297779 | 1 | /* Thunker |
Christopher Haster |
9:89aeb1297779 | 2 | * Thunk generating class for calling function objects through |
Christopher Haster |
9:89aeb1297779 | 3 | * context-less functions |
Christopher Haster |
9:89aeb1297779 | 4 | */ |
Christopher Haster |
9:89aeb1297779 | 5 | #ifndef THUNKER_H |
Christopher Haster |
9:89aeb1297779 | 6 | #define THUNKER_H |
Christopher Haster |
9:89aeb1297779 | 7 | |
Christopher Haster |
9:89aeb1297779 | 8 | #include "FuncPtr.h" |
Christopher Haster |
9:89aeb1297779 | 9 | |
Christopher Haster |
12:a005f8ca5d36 | 10 | extern "C" { |
Christopher Haster |
12:a005f8ca5d36 | 11 | #include "trampoline.h" |
Christopher Haster |
9:89aeb1297779 | 12 | } |
Christopher Haster |
9:89aeb1297779 | 13 | |
Christopher Haster |
9:89aeb1297779 | 14 | |
Christopher Haster |
10:086f34a27a8d | 15 | /** Thunk generating class for calling function objects |
Christopher Haster |
9:89aeb1297779 | 16 | */ |
Christopher Haster |
9:89aeb1297779 | 17 | class Thunker { |
Christopher Haster |
9:89aeb1297779 | 18 | public: |
Christopher Haster |
9:89aeb1297779 | 19 | /** Create a Thunker around a function |
Christopher Haster |
9:89aeb1297779 | 20 | */ |
Christopher Haster |
9:89aeb1297779 | 21 | Thunker(FuncPtr<void()> func = 0) { |
Christopher Haster |
9:89aeb1297779 | 22 | attach(func); |
Christopher Haster |
9:89aeb1297779 | 23 | _entry = reinterpret_cast<void(*)()>( |
Christopher Haster |
9:89aeb1297779 | 24 | trampoline_init(&_trampoline, &Thunker::thunk, this)); |
Christopher Haster |
9:89aeb1297779 | 25 | } |
Christopher Haster |
9:89aeb1297779 | 26 | |
Christopher Haster |
9:89aeb1297779 | 27 | /** Create a Thunker around a method |
Christopher Haster |
9:89aeb1297779 | 28 | */ |
Christopher Haster |
9:89aeb1297779 | 29 | template <typename T, typename M> |
Christopher Haster |
9:89aeb1297779 | 30 | Thunker(T *obj, M method) { |
Christopher Haster |
9:89aeb1297779 | 31 | attach(obj, method); |
Christopher Haster |
9:89aeb1297779 | 32 | _entry = reinterpret_cast<void(*)()>( |
Christopher Haster |
9:89aeb1297779 | 33 | trampoline_init(&_trampoline, &Thunker::thunk, this)); |
Christopher Haster |
9:89aeb1297779 | 34 | } |
Christopher Haster |
9:89aeb1297779 | 35 | |
Christopher Haster |
9:89aeb1297779 | 36 | /** Attach a function |
Christopher Haster |
9:89aeb1297779 | 37 | */ |
Christopher Haster |
9:89aeb1297779 | 38 | void attach(FuncPtr<void()> func) { |
Christopher Haster |
9:89aeb1297779 | 39 | _func.attach(func); |
Christopher Haster |
9:89aeb1297779 | 40 | } |
Christopher Haster |
9:89aeb1297779 | 41 | |
Christopher Haster |
9:89aeb1297779 | 42 | /** Attach a method |
Christopher Haster |
9:89aeb1297779 | 43 | */ |
Christopher Haster |
9:89aeb1297779 | 44 | template <typename T, typename M> |
Christopher Haster |
9:89aeb1297779 | 45 | void attach(T *obj, M method) { |
Christopher Haster |
9:89aeb1297779 | 46 | attach(FuncPtr<void()>(obj, method)); |
Christopher Haster |
9:89aeb1297779 | 47 | } |
Christopher Haster |
9:89aeb1297779 | 48 | |
Christopher Haster |
9:89aeb1297779 | 49 | /** Call the attached function |
Christopher Haster |
9:89aeb1297779 | 50 | */ |
Christopher Haster |
9:89aeb1297779 | 51 | void call() { |
Christopher Haster |
9:89aeb1297779 | 52 | return _func(); |
Christopher Haster |
9:89aeb1297779 | 53 | } |
Christopher Haster |
9:89aeb1297779 | 54 | |
Christopher Haster |
9:89aeb1297779 | 55 | /** Call the attached function |
Christopher Haster |
9:89aeb1297779 | 56 | */ |
Christopher Haster |
9:89aeb1297779 | 57 | void operator()() { |
Christopher Haster |
9:89aeb1297779 | 58 | return call(); |
Christopher Haster |
9:89aeb1297779 | 59 | } |
Christopher Haster |
9:89aeb1297779 | 60 | |
Christopher Haster |
9:89aeb1297779 | 61 | /** Test if function has be attached |
Christopher Haster |
9:89aeb1297779 | 62 | */ |
Christopher Haster |
9:89aeb1297779 | 63 | operator bool() const { |
Christopher Haster |
9:89aeb1297779 | 64 | return _func; |
Christopher Haster |
9:89aeb1297779 | 65 | } |
Christopher Haster |
9:89aeb1297779 | 66 | |
Christopher Haster |
9:89aeb1297779 | 67 | /** Static thunk for passing as C-style function |
Christopher Haster |
9:89aeb1297779 | 68 | * @param func Thunker to call passed as void pointer |
Christopher Haster |
9:89aeb1297779 | 69 | */ |
Christopher Haster |
9:89aeb1297779 | 70 | static void thunk(void *func) { |
Christopher Haster |
9:89aeb1297779 | 71 | return static_cast<Thunker*>(func)->call(); |
Christopher Haster |
9:89aeb1297779 | 72 | } |
Christopher Haster |
9:89aeb1297779 | 73 | |
Christopher Haster |
9:89aeb1297779 | 74 | /** Entry point into thunk into function |
Christopher Haster |
9:89aeb1297779 | 75 | */ |
Christopher Haster |
12:a005f8ca5d36 | 76 | entry_t *entry() { |
Christopher Haster |
9:89aeb1297779 | 77 | return _entry; |
Christopher Haster |
9:89aeb1297779 | 78 | } |
Christopher Haster |
9:89aeb1297779 | 79 | |
Christopher Haster |
9:89aeb1297779 | 80 | /** Entry point into thunk into function |
Christopher Haster |
9:89aeb1297779 | 81 | */ |
Christopher Haster |
12:a005f8ca5d36 | 82 | operator entry_t*() { |
Christopher Haster |
9:89aeb1297779 | 83 | return entry(); |
Christopher Haster |
9:89aeb1297779 | 84 | } |
Christopher Haster |
9:89aeb1297779 | 85 | |
Christopher Haster |
9:89aeb1297779 | 86 | private: |
Christopher Haster |
12:a005f8ca5d36 | 87 | entry_t *_entry; |
Christopher Haster |
9:89aeb1297779 | 88 | trampoline_t _trampoline; |
Christopher Haster |
9:89aeb1297779 | 89 | FuncPtr<void()> _func; |
Christopher Haster |
9:89aeb1297779 | 90 | }; |
Christopher Haster |
9:89aeb1297779 | 91 | |
Christopher Haster |
9:89aeb1297779 | 92 | |
Christopher Haster |
9:89aeb1297779 | 93 | #endif |