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 23:38:04 2016 -0500
Revision:
18:a0fde14b6c39
Parent:
14:79be4e700cc9
Increase to 5 args

Who changed what in which revision?

UserRevisionLine numberNew 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