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:
15:0c3d1c4a050b
Increase to 5 args

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Christopher Haster 7:9a62ba2d3d68 1 /* Chainer
Christopher Haster 7:9a62ba2d3d68 2 * Static function chaining
Christopher Haster 7:9a62ba2d3d68 3 */
Christopher Haster 7:9a62ba2d3d68 4 #ifndef CHAINER_H
Christopher Haster 7:9a62ba2d3d68 5 #define CHAINER_H
Christopher Haster 7:9a62ba2d3d68 6
Christopher Haster 7:9a62ba2d3d68 7 #include "FuncPtr.h"
Christopher Haster 7:9a62ba2d3d68 8
Christopher Haster 7:9a62ba2d3d68 9
Christopher Haster 7:9a62ba2d3d68 10 /** Static function chaining
Christopher Haster 7:9a62ba2d3d68 11 */
Christopher Haster 15:0c3d1c4a050b 12 template <typename F, int N>
Christopher Haster 7:9a62ba2d3d68 13 class Chainer;
Christopher Haster 7:9a62ba2d3d68 14
Christopher Haster 7:9a62ba2d3d68 15 /** Static function composition
Christopher Haster 7:9a62ba2d3d68 16 */
Christopher Haster 18:a0fde14b6c39 17 template <typename A0, typename A1, typename A2, typename A3, typename A4, int N>
Christopher Haster 18:a0fde14b6c39 18 class Chainer<void(A0, A1, A2, A3, A4), N> {
Christopher Haster 18:a0fde14b6c39 19 public:
Christopher Haster 18:a0fde14b6c39 20 /** Access a function in the chain
Christopher Haster 18:a0fde14b6c39 21 */
Christopher Haster 18:a0fde14b6c39 22 FuncPtr<void(A0, A1, A2, A3, A4)> &operator[](int i) {
Christopher Haster 18:a0fde14b6c39 23 return _funcs[i];
Christopher Haster 18:a0fde14b6c39 24 }
Christopher Haster 18:a0fde14b6c39 25
Christopher Haster 18:a0fde14b6c39 26 /** Attach a function to the chain
Christopher Haster 18:a0fde14b6c39 27 */
Christopher Haster 18:a0fde14b6c39 28 bool attach(FuncPtr<void(A0, A1, A2, A3, A4)> func) {
Christopher Haster 18:a0fde14b6c39 29 for (int i = 0; i < N; i++) {
Christopher Haster 18:a0fde14b6c39 30 if (!_funcs[i]) {
Christopher Haster 18:a0fde14b6c39 31 _funcs[i].attach(func);
Christopher Haster 18:a0fde14b6c39 32 return true;
Christopher Haster 18:a0fde14b6c39 33 }
Christopher Haster 18:a0fde14b6c39 34 }
Christopher Haster 18:a0fde14b6c39 35
Christopher Haster 18:a0fde14b6c39 36 return false;
Christopher Haster 18:a0fde14b6c39 37 }
Christopher Haster 18:a0fde14b6c39 38
Christopher Haster 18:a0fde14b6c39 39 /** Attach a function to the chain
Christopher Haster 18:a0fde14b6c39 40 */
Christopher Haster 18:a0fde14b6c39 41 template <typename T, typename M>
Christopher Haster 18:a0fde14b6c39 42 bool attach(T *obj, M method) {
Christopher Haster 18:a0fde14b6c39 43 return attach(FuncPtr<void(A0, A1, A2, A3, A4)>(obj, method));
Christopher Haster 18:a0fde14b6c39 44 }
Christopher Haster 18:a0fde14b6c39 45
Christopher Haster 18:a0fde14b6c39 46 /** Call each function in the chain
Christopher Haster 18:a0fde14b6c39 47 */
Christopher Haster 18:a0fde14b6c39 48 void call(A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) {
Christopher Haster 18:a0fde14b6c39 49 for (int i = 0; i < N; i++) {
Christopher Haster 18:a0fde14b6c39 50 if (_funcs[i]) {
Christopher Haster 18:a0fde14b6c39 51 _funcs[i](a0, a1, a2, a3, a4);
Christopher Haster 18:a0fde14b6c39 52 }
Christopher Haster 18:a0fde14b6c39 53 }
Christopher Haster 18:a0fde14b6c39 54 }
Christopher Haster 18:a0fde14b6c39 55
Christopher Haster 18:a0fde14b6c39 56 /** Call each function in the chain
Christopher Haster 18:a0fde14b6c39 57 */
Christopher Haster 18:a0fde14b6c39 58 void operator()(A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) {
Christopher Haster 18:a0fde14b6c39 59 return call(a0, a1, a2, a3, a4);
Christopher Haster 18:a0fde14b6c39 60 }
Christopher Haster 18:a0fde14b6c39 61
Christopher Haster 18:a0fde14b6c39 62 /** Test if any functions have been attached
Christopher Haster 18:a0fde14b6c39 63 */
Christopher Haster 18:a0fde14b6c39 64 operator bool() const {
Christopher Haster 18:a0fde14b6c39 65 for (int i = 0; i < N; i++) {
Christopher Haster 18:a0fde14b6c39 66 if (_funcs[i]) {
Christopher Haster 18:a0fde14b6c39 67 return true;
Christopher Haster 18:a0fde14b6c39 68 }
Christopher Haster 18:a0fde14b6c39 69 }
Christopher Haster 18:a0fde14b6c39 70 return false;
Christopher Haster 18:a0fde14b6c39 71 }
Christopher Haster 18:a0fde14b6c39 72
Christopher Haster 18:a0fde14b6c39 73 /** Static thunk for passing as C-style function
Christopher Haster 18:a0fde14b6c39 74 * @param func Chainer to call passed as void pointer
Christopher Haster 18:a0fde14b6c39 75 */
Christopher Haster 18:a0fde14b6c39 76 static void thunk(void *func, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) {
Christopher Haster 18:a0fde14b6c39 77 return static_cast<Chainer<void(A0, A1, A2, A3, A4), N>*>(func)
Christopher Haster 18:a0fde14b6c39 78 ->call(a0, a1, a2, a3, a4);
Christopher Haster 18:a0fde14b6c39 79 }
Christopher Haster 18:a0fde14b6c39 80
Christopher Haster 18:a0fde14b6c39 81 private:
Christopher Haster 18:a0fde14b6c39 82 FuncPtr<void(A0, A1, A2, A3, A4)> _funcs[N];
Christopher Haster 18:a0fde14b6c39 83 };
Christopher Haster 18:a0fde14b6c39 84
Christopher Haster 18:a0fde14b6c39 85 /** Static function composition
Christopher Haster 18:a0fde14b6c39 86 */
Christopher Haster 15:0c3d1c4a050b 87 template <typename A0, typename A1, typename A2, typename A3, int N>
Christopher Haster 15:0c3d1c4a050b 88 class Chainer<void(A0, A1, A2, A3), N> {
Christopher Haster 7:9a62ba2d3d68 89 public:
Christopher Haster 7:9a62ba2d3d68 90 /** Access a function in the chain
Christopher Haster 7:9a62ba2d3d68 91 */
Christopher Haster 7:9a62ba2d3d68 92 FuncPtr<void(A0, A1, A2, A3)> &operator[](int i) {
Christopher Haster 7:9a62ba2d3d68 93 return _funcs[i];
Christopher Haster 7:9a62ba2d3d68 94 }
Christopher Haster 7:9a62ba2d3d68 95
Christopher Haster 7:9a62ba2d3d68 96 /** Attach a function to the chain
Christopher Haster 7:9a62ba2d3d68 97 */
Christopher Haster 7:9a62ba2d3d68 98 bool attach(FuncPtr<void(A0, A1, A2, A3)> func) {
Christopher Haster 7:9a62ba2d3d68 99 for (int i = 0; i < N; i++) {
Christopher Haster 7:9a62ba2d3d68 100 if (!_funcs[i]) {
Christopher Haster 7:9a62ba2d3d68 101 _funcs[i].attach(func);
Christopher Haster 7:9a62ba2d3d68 102 return true;
Christopher Haster 7:9a62ba2d3d68 103 }
Christopher Haster 7:9a62ba2d3d68 104 }
Christopher Haster 7:9a62ba2d3d68 105
Christopher Haster 7:9a62ba2d3d68 106 return false;
Christopher Haster 7:9a62ba2d3d68 107 }
Christopher Haster 7:9a62ba2d3d68 108
Christopher Haster 7:9a62ba2d3d68 109 /** Attach a function to the chain
Christopher Haster 7:9a62ba2d3d68 110 */
Christopher Haster 7:9a62ba2d3d68 111 template <typename T, typename M>
Christopher Haster 7:9a62ba2d3d68 112 bool attach(T *obj, M method) {
Christopher Haster 7:9a62ba2d3d68 113 return attach(FuncPtr<void(A0, A1, A2, A3)>(obj, method));
Christopher Haster 7:9a62ba2d3d68 114 }
Christopher Haster 7:9a62ba2d3d68 115
Christopher Haster 7:9a62ba2d3d68 116 /** Call each function in the chain
Christopher Haster 7:9a62ba2d3d68 117 */
Christopher Haster 7:9a62ba2d3d68 118 void call(A0 a0, A1 a1, A2 a2, A3 a3) {
Christopher Haster 7:9a62ba2d3d68 119 for (int i = 0; i < N; i++) {
Christopher Haster 7:9a62ba2d3d68 120 if (_funcs[i]) {
Christopher Haster 7:9a62ba2d3d68 121 _funcs[i](a0, a1, a2, a3);
Christopher Haster 7:9a62ba2d3d68 122 }
Christopher Haster 7:9a62ba2d3d68 123 }
Christopher Haster 7:9a62ba2d3d68 124 }
Christopher Haster 7:9a62ba2d3d68 125
Christopher Haster 7:9a62ba2d3d68 126 /** Call each function in the chain
Christopher Haster 7:9a62ba2d3d68 127 */
Christopher Haster 7:9a62ba2d3d68 128 void operator()(A0 a0, A1 a1, A2 a2, A3 a3) {
Christopher Haster 7:9a62ba2d3d68 129 return call(a0, a1, a2, a3);
Christopher Haster 7:9a62ba2d3d68 130 }
Christopher Haster 7:9a62ba2d3d68 131
Christopher Haster 7:9a62ba2d3d68 132 /** Test if any functions have been attached
Christopher Haster 7:9a62ba2d3d68 133 */
Christopher Haster 8:71037a47492d 134 operator bool() const {
Christopher Haster 7:9a62ba2d3d68 135 for (int i = 0; i < N; i++) {
Christopher Haster 7:9a62ba2d3d68 136 if (_funcs[i]) {
Christopher Haster 7:9a62ba2d3d68 137 return true;
Christopher Haster 7:9a62ba2d3d68 138 }
Christopher Haster 7:9a62ba2d3d68 139 }
Christopher Haster 7:9a62ba2d3d68 140 return false;
Christopher Haster 7:9a62ba2d3d68 141 }
Christopher Haster 7:9a62ba2d3d68 142
Christopher Haster 7:9a62ba2d3d68 143 /** Static thunk for passing as C-style function
Christopher Haster 7:9a62ba2d3d68 144 * @param func Chainer to call passed as void pointer
Christopher Haster 7:9a62ba2d3d68 145 */
Christopher Haster 7:9a62ba2d3d68 146 static void thunk(void *func, A0 a0, A1 a1, A2 a2, A3 a3) {
Christopher Haster 15:0c3d1c4a050b 147 return static_cast<Chainer<void(A0, A1, A2, A3), N>*>(func)
Christopher Haster 7:9a62ba2d3d68 148 ->call(a0, a1, a2, a3);
Christopher Haster 7:9a62ba2d3d68 149 }
Christopher Haster 7:9a62ba2d3d68 150
Christopher Haster 7:9a62ba2d3d68 151 private:
Christopher Haster 7:9a62ba2d3d68 152 FuncPtr<void(A0, A1, A2, A3)> _funcs[N];
Christopher Haster 7:9a62ba2d3d68 153 };
Christopher Haster 7:9a62ba2d3d68 154
Christopher Haster 7:9a62ba2d3d68 155 /** Static function composition
Christopher Haster 7:9a62ba2d3d68 156 */
Christopher Haster 15:0c3d1c4a050b 157 template <typename A0, typename A1, typename A2, int N>
Christopher Haster 15:0c3d1c4a050b 158 class Chainer<void(A0, A1, A2), N> {
Christopher Haster 7:9a62ba2d3d68 159 public:
Christopher Haster 7:9a62ba2d3d68 160 /** Access a function in the chain
Christopher Haster 7:9a62ba2d3d68 161 */
Christopher Haster 7:9a62ba2d3d68 162 FuncPtr<void(A0, A1, A2)> &operator[](int i) {
Christopher Haster 7:9a62ba2d3d68 163 return _funcs[i];
Christopher Haster 7:9a62ba2d3d68 164 }
Christopher Haster 7:9a62ba2d3d68 165
Christopher Haster 7:9a62ba2d3d68 166 /** Attach a function to the chain
Christopher Haster 7:9a62ba2d3d68 167 */
Christopher Haster 7:9a62ba2d3d68 168 bool attach(FuncPtr<void(A0, A1, A2)> func) {
Christopher Haster 7:9a62ba2d3d68 169 for (int i = 0; i < N; i++) {
Christopher Haster 7:9a62ba2d3d68 170 if (!_funcs[i]) {
Christopher Haster 7:9a62ba2d3d68 171 _funcs[i].attach(func);
Christopher Haster 7:9a62ba2d3d68 172 return true;
Christopher Haster 7:9a62ba2d3d68 173 }
Christopher Haster 7:9a62ba2d3d68 174 }
Christopher Haster 7:9a62ba2d3d68 175
Christopher Haster 7:9a62ba2d3d68 176 return false;
Christopher Haster 7:9a62ba2d3d68 177 }
Christopher Haster 7:9a62ba2d3d68 178
Christopher Haster 7:9a62ba2d3d68 179 /** Attach a function to the chain
Christopher Haster 7:9a62ba2d3d68 180 */
Christopher Haster 7:9a62ba2d3d68 181 template <typename T, typename M>
Christopher Haster 7:9a62ba2d3d68 182 bool attach(T *obj, M method) {
Christopher Haster 7:9a62ba2d3d68 183 return attach(FuncPtr<void(A0, A1, A2)>(obj, method));
Christopher Haster 7:9a62ba2d3d68 184 }
Christopher Haster 7:9a62ba2d3d68 185
Christopher Haster 7:9a62ba2d3d68 186 /** Call each function in the chain
Christopher Haster 7:9a62ba2d3d68 187 */
Christopher Haster 7:9a62ba2d3d68 188 void call(A0 a0, A1 a1, A2 a2) {
Christopher Haster 7:9a62ba2d3d68 189 for (int i = 0; i < N; i++) {
Christopher Haster 7:9a62ba2d3d68 190 if (_funcs[i]) {
Christopher Haster 7:9a62ba2d3d68 191 _funcs[i](a0, a1, a2);
Christopher Haster 7:9a62ba2d3d68 192 }
Christopher Haster 7:9a62ba2d3d68 193 }
Christopher Haster 7:9a62ba2d3d68 194 }
Christopher Haster 7:9a62ba2d3d68 195
Christopher Haster 7:9a62ba2d3d68 196 /** Call each function in the chain
Christopher Haster 7:9a62ba2d3d68 197 */
Christopher Haster 7:9a62ba2d3d68 198 void operator()(A0 a0, A1 a1, A2 a2) {
Christopher Haster 7:9a62ba2d3d68 199 return call(a0, a1, a2);
Christopher Haster 7:9a62ba2d3d68 200 }
Christopher Haster 7:9a62ba2d3d68 201
Christopher Haster 7:9a62ba2d3d68 202 /** Test if any functions have been attached
Christopher Haster 7:9a62ba2d3d68 203 */
Christopher Haster 8:71037a47492d 204 operator bool() const {
Christopher Haster 7:9a62ba2d3d68 205 for (int i = 0; i < N; i++) {
Christopher Haster 7:9a62ba2d3d68 206 if (_funcs[i]) {
Christopher Haster 7:9a62ba2d3d68 207 return true;
Christopher Haster 7:9a62ba2d3d68 208 }
Christopher Haster 7:9a62ba2d3d68 209 }
Christopher Haster 7:9a62ba2d3d68 210 return false;
Christopher Haster 7:9a62ba2d3d68 211 }
Christopher Haster 7:9a62ba2d3d68 212
Christopher Haster 7:9a62ba2d3d68 213 /** Static thunk for passing as C-style function
Christopher Haster 7:9a62ba2d3d68 214 * @param func Chainer to call passed as void pointer
Christopher Haster 7:9a62ba2d3d68 215 */
Christopher Haster 7:9a62ba2d3d68 216 static void thunk(void *func, A0 a0, A1 a1, A2 a2) {
Christopher Haster 15:0c3d1c4a050b 217 return static_cast<Chainer<void(A0, A1, A2), N>*>(func)
Christopher Haster 7:9a62ba2d3d68 218 ->call(a0, a1, a2);
Christopher Haster 7:9a62ba2d3d68 219 }
Christopher Haster 7:9a62ba2d3d68 220
Christopher Haster 7:9a62ba2d3d68 221 private:
Christopher Haster 7:9a62ba2d3d68 222 FuncPtr<void(A0, A1, A2)> _funcs[N];
Christopher Haster 7:9a62ba2d3d68 223 };
Christopher Haster 7:9a62ba2d3d68 224
Christopher Haster 7:9a62ba2d3d68 225 /** Static function composition
Christopher Haster 7:9a62ba2d3d68 226 */
Christopher Haster 15:0c3d1c4a050b 227 template <typename A0, typename A1, int N>
Christopher Haster 15:0c3d1c4a050b 228 class Chainer<void(A0, A1), N> {
Christopher Haster 7:9a62ba2d3d68 229 public:
Christopher Haster 7:9a62ba2d3d68 230 /** Access a function in the chain
Christopher Haster 7:9a62ba2d3d68 231 */
Christopher Haster 7:9a62ba2d3d68 232 FuncPtr<void(A0, A1)> &operator[](int i) {
Christopher Haster 7:9a62ba2d3d68 233 return _funcs[i];
Christopher Haster 7:9a62ba2d3d68 234 }
Christopher Haster 7:9a62ba2d3d68 235
Christopher Haster 7:9a62ba2d3d68 236 /** Attach a function to the chain
Christopher Haster 7:9a62ba2d3d68 237 */
Christopher Haster 7:9a62ba2d3d68 238 bool attach(FuncPtr<void(A0, A1)> func) {
Christopher Haster 7:9a62ba2d3d68 239 for (int i = 0; i < N; i++) {
Christopher Haster 7:9a62ba2d3d68 240 if (!_funcs[i]) {
Christopher Haster 7:9a62ba2d3d68 241 _funcs[i].attach(func);
Christopher Haster 7:9a62ba2d3d68 242 return true;
Christopher Haster 7:9a62ba2d3d68 243 }
Christopher Haster 7:9a62ba2d3d68 244 }
Christopher Haster 7:9a62ba2d3d68 245
Christopher Haster 7:9a62ba2d3d68 246 return false;
Christopher Haster 7:9a62ba2d3d68 247 }
Christopher Haster 7:9a62ba2d3d68 248
Christopher Haster 7:9a62ba2d3d68 249 /** Attach a function to the chain
Christopher Haster 7:9a62ba2d3d68 250 */
Christopher Haster 7:9a62ba2d3d68 251 template <typename T, typename M>
Christopher Haster 7:9a62ba2d3d68 252 bool attach(T *obj, M method) {
Christopher Haster 7:9a62ba2d3d68 253 return attach(FuncPtr<void(A0, A1)>(obj, method));
Christopher Haster 7:9a62ba2d3d68 254 }
Christopher Haster 7:9a62ba2d3d68 255
Christopher Haster 7:9a62ba2d3d68 256 /** Call each function in the chain
Christopher Haster 7:9a62ba2d3d68 257 */
Christopher Haster 7:9a62ba2d3d68 258 void call(A0 a0, A1 a1) {
Christopher Haster 7:9a62ba2d3d68 259 for (int i = 0; i < N; i++) {
Christopher Haster 7:9a62ba2d3d68 260 if (_funcs[i]) {
Christopher Haster 7:9a62ba2d3d68 261 _funcs[i](a0, a1);
Christopher Haster 7:9a62ba2d3d68 262 }
Christopher Haster 7:9a62ba2d3d68 263 }
Christopher Haster 7:9a62ba2d3d68 264 }
Christopher Haster 7:9a62ba2d3d68 265
Christopher Haster 7:9a62ba2d3d68 266 /** Call each function in the chain
Christopher Haster 7:9a62ba2d3d68 267 */
Christopher Haster 7:9a62ba2d3d68 268 void operator()(A0 a0, A1 a1) {
Christopher Haster 7:9a62ba2d3d68 269 return call(a0, a1);
Christopher Haster 7:9a62ba2d3d68 270 }
Christopher Haster 7:9a62ba2d3d68 271
Christopher Haster 7:9a62ba2d3d68 272 /** Test if any functions have been attached
Christopher Haster 7:9a62ba2d3d68 273 */
Christopher Haster 8:71037a47492d 274 operator bool() const {
Christopher Haster 7:9a62ba2d3d68 275 for (int i = 0; i < N; i++) {
Christopher Haster 7:9a62ba2d3d68 276 if (_funcs[i]) {
Christopher Haster 7:9a62ba2d3d68 277 return true;
Christopher Haster 7:9a62ba2d3d68 278 }
Christopher Haster 7:9a62ba2d3d68 279 }
Christopher Haster 7:9a62ba2d3d68 280 return false;
Christopher Haster 7:9a62ba2d3d68 281 }
Christopher Haster 7:9a62ba2d3d68 282
Christopher Haster 7:9a62ba2d3d68 283 /** Static thunk for passing as C-style function
Christopher Haster 7:9a62ba2d3d68 284 * @param func Chainer to call passed as void pointer
Christopher Haster 7:9a62ba2d3d68 285 */
Christopher Haster 7:9a62ba2d3d68 286 static void thunk(void *func, A0 a0, A1 a1) {
Christopher Haster 15:0c3d1c4a050b 287 return static_cast<Chainer<void(A0, A1), N>*>(func)
Christopher Haster 7:9a62ba2d3d68 288 ->call(a0, a1);
Christopher Haster 7:9a62ba2d3d68 289 }
Christopher Haster 7:9a62ba2d3d68 290
Christopher Haster 7:9a62ba2d3d68 291 private:
Christopher Haster 7:9a62ba2d3d68 292 FuncPtr<void(A0, A1)> _funcs[N];
Christopher Haster 7:9a62ba2d3d68 293 };
Christopher Haster 7:9a62ba2d3d68 294
Christopher Haster 7:9a62ba2d3d68 295 /** Static function composition
Christopher Haster 7:9a62ba2d3d68 296 */
Christopher Haster 15:0c3d1c4a050b 297 template <typename A0, int N>
Christopher Haster 15:0c3d1c4a050b 298 class Chainer<void(A0), N> {
Christopher Haster 7:9a62ba2d3d68 299 public:
Christopher Haster 7:9a62ba2d3d68 300 /** Access a function in the chain
Christopher Haster 7:9a62ba2d3d68 301 */
Christopher Haster 7:9a62ba2d3d68 302 FuncPtr<void(A0)> &operator[](int i) {
Christopher Haster 7:9a62ba2d3d68 303 return _funcs[i];
Christopher Haster 7:9a62ba2d3d68 304 }
Christopher Haster 7:9a62ba2d3d68 305
Christopher Haster 7:9a62ba2d3d68 306 /** Attach a function to the chain
Christopher Haster 7:9a62ba2d3d68 307 */
Christopher Haster 7:9a62ba2d3d68 308 bool attach(FuncPtr<void(A0)> func) {
Christopher Haster 7:9a62ba2d3d68 309 for (int i = 0; i < N; i++) {
Christopher Haster 7:9a62ba2d3d68 310 if (!_funcs[i]) {
Christopher Haster 7:9a62ba2d3d68 311 _funcs[i].attach(func);
Christopher Haster 7:9a62ba2d3d68 312 return true;
Christopher Haster 7:9a62ba2d3d68 313 }
Christopher Haster 7:9a62ba2d3d68 314 }
Christopher Haster 7:9a62ba2d3d68 315
Christopher Haster 7:9a62ba2d3d68 316 return false;
Christopher Haster 7:9a62ba2d3d68 317 }
Christopher Haster 7:9a62ba2d3d68 318
Christopher Haster 7:9a62ba2d3d68 319 /** Attach a function to the chain
Christopher Haster 7:9a62ba2d3d68 320 */
Christopher Haster 7:9a62ba2d3d68 321 template <typename T, typename M>
Christopher Haster 7:9a62ba2d3d68 322 bool attach(T *obj, M method) {
Christopher Haster 7:9a62ba2d3d68 323 return attach(FuncPtr<void(A0)>(obj, method));
Christopher Haster 7:9a62ba2d3d68 324 }
Christopher Haster 7:9a62ba2d3d68 325
Christopher Haster 7:9a62ba2d3d68 326 /** Call each function in the chain
Christopher Haster 7:9a62ba2d3d68 327 */
Christopher Haster 7:9a62ba2d3d68 328 void call(A0 a0) {
Christopher Haster 7:9a62ba2d3d68 329 for (int i = 0; i < N; i++) {
Christopher Haster 7:9a62ba2d3d68 330 if (_funcs[i]) {
Christopher Haster 7:9a62ba2d3d68 331 _funcs[i](a0);
Christopher Haster 7:9a62ba2d3d68 332 }
Christopher Haster 7:9a62ba2d3d68 333 }
Christopher Haster 7:9a62ba2d3d68 334 }
Christopher Haster 7:9a62ba2d3d68 335
Christopher Haster 7:9a62ba2d3d68 336 /** Call each function in the chain
Christopher Haster 7:9a62ba2d3d68 337 */
Christopher Haster 7:9a62ba2d3d68 338 void operator()(A0 a0) {
Christopher Haster 7:9a62ba2d3d68 339 return call(a0);
Christopher Haster 7:9a62ba2d3d68 340 }
Christopher Haster 7:9a62ba2d3d68 341
Christopher Haster 7:9a62ba2d3d68 342 /** Test if any functions have been attached
Christopher Haster 7:9a62ba2d3d68 343 */
Christopher Haster 8:71037a47492d 344 operator bool() const {
Christopher Haster 7:9a62ba2d3d68 345 for (int i = 0; i < N; i++) {
Christopher Haster 7:9a62ba2d3d68 346 if (_funcs[i]) {
Christopher Haster 7:9a62ba2d3d68 347 return true;
Christopher Haster 7:9a62ba2d3d68 348 }
Christopher Haster 7:9a62ba2d3d68 349 }
Christopher Haster 7:9a62ba2d3d68 350 return false;
Christopher Haster 7:9a62ba2d3d68 351 }
Christopher Haster 7:9a62ba2d3d68 352
Christopher Haster 7:9a62ba2d3d68 353 /** Static thunk for passing as C-style function
Christopher Haster 7:9a62ba2d3d68 354 * @param func Chainer to call passed as void pointer
Christopher Haster 7:9a62ba2d3d68 355 */
Christopher Haster 7:9a62ba2d3d68 356 static void thunk(void *func, A0 a0) {
Christopher Haster 15:0c3d1c4a050b 357 return static_cast<Chainer<void(A0), N>*>(func)
Christopher Haster 7:9a62ba2d3d68 358 ->call(a0);
Christopher Haster 7:9a62ba2d3d68 359 }
Christopher Haster 7:9a62ba2d3d68 360
Christopher Haster 7:9a62ba2d3d68 361 private:
Christopher Haster 7:9a62ba2d3d68 362 FuncPtr<void(A0)> _funcs[N];
Christopher Haster 7:9a62ba2d3d68 363 };
Christopher Haster 7:9a62ba2d3d68 364
Christopher Haster 7:9a62ba2d3d68 365 /** Static function composition
Christopher Haster 7:9a62ba2d3d68 366 */
Christopher Haster 7:9a62ba2d3d68 367 template <int N>
Christopher Haster 15:0c3d1c4a050b 368 class Chainer<void(), N> {
Christopher Haster 7:9a62ba2d3d68 369 public:
Christopher Haster 7:9a62ba2d3d68 370 /** Access a function in the chain
Christopher Haster 7:9a62ba2d3d68 371 */
Christopher Haster 7:9a62ba2d3d68 372 FuncPtr<void()> &operator[](int i) {
Christopher Haster 7:9a62ba2d3d68 373 return _funcs[i];
Christopher Haster 7:9a62ba2d3d68 374 }
Christopher Haster 7:9a62ba2d3d68 375
Christopher Haster 7:9a62ba2d3d68 376 /** Attach a function to the chain
Christopher Haster 7:9a62ba2d3d68 377 */
Christopher Haster 7:9a62ba2d3d68 378 bool attach(FuncPtr<void()> func) {
Christopher Haster 7:9a62ba2d3d68 379 for (int i = 0; i < N; i++) {
Christopher Haster 7:9a62ba2d3d68 380 if (!_funcs[i]) {
Christopher Haster 7:9a62ba2d3d68 381 _funcs[i].attach(func);
Christopher Haster 7:9a62ba2d3d68 382 return true;
Christopher Haster 7:9a62ba2d3d68 383 }
Christopher Haster 7:9a62ba2d3d68 384 }
Christopher Haster 7:9a62ba2d3d68 385
Christopher Haster 7:9a62ba2d3d68 386 return false;
Christopher Haster 7:9a62ba2d3d68 387 }
Christopher Haster 7:9a62ba2d3d68 388
Christopher Haster 7:9a62ba2d3d68 389 /** Attach a function to the chain
Christopher Haster 7:9a62ba2d3d68 390 */
Christopher Haster 7:9a62ba2d3d68 391 template <typename T, typename M>
Christopher Haster 7:9a62ba2d3d68 392 bool attach(T *obj, M method) {
Christopher Haster 7:9a62ba2d3d68 393 return attach(FuncPtr<void()>(obj, method));
Christopher Haster 7:9a62ba2d3d68 394 }
Christopher Haster 7:9a62ba2d3d68 395
Christopher Haster 7:9a62ba2d3d68 396 /** Call each function in the chain
Christopher Haster 7:9a62ba2d3d68 397 */
Christopher Haster 7:9a62ba2d3d68 398 void call() {
Christopher Haster 7:9a62ba2d3d68 399 for (int i = 0; i < N; i++) {
Christopher Haster 7:9a62ba2d3d68 400 if (_funcs[i]) {
Christopher Haster 7:9a62ba2d3d68 401 _funcs[i]();
Christopher Haster 7:9a62ba2d3d68 402 }
Christopher Haster 7:9a62ba2d3d68 403 }
Christopher Haster 7:9a62ba2d3d68 404 }
Christopher Haster 7:9a62ba2d3d68 405
Christopher Haster 7:9a62ba2d3d68 406 /** Call each function in the chain
Christopher Haster 7:9a62ba2d3d68 407 */
Christopher Haster 7:9a62ba2d3d68 408 void operator()() {
Christopher Haster 7:9a62ba2d3d68 409 return call();
Christopher Haster 7:9a62ba2d3d68 410 }
Christopher Haster 7:9a62ba2d3d68 411
Christopher Haster 7:9a62ba2d3d68 412 /** Test if any functions have been attached
Christopher Haster 7:9a62ba2d3d68 413 */
Christopher Haster 8:71037a47492d 414 operator bool() const {
Christopher Haster 7:9a62ba2d3d68 415 for (int i = 0; i < N; i++) {
Christopher Haster 7:9a62ba2d3d68 416 if (_funcs[i]) {
Christopher Haster 7:9a62ba2d3d68 417 return true;
Christopher Haster 7:9a62ba2d3d68 418 }
Christopher Haster 7:9a62ba2d3d68 419 }
Christopher Haster 7:9a62ba2d3d68 420 return false;
Christopher Haster 7:9a62ba2d3d68 421 }
Christopher Haster 7:9a62ba2d3d68 422
Christopher Haster 7:9a62ba2d3d68 423 /** Static thunk for passing as C-style function
Christopher Haster 7:9a62ba2d3d68 424 * @param func Chainer to call passed as void pointer
Christopher Haster 7:9a62ba2d3d68 425 */
Christopher Haster 7:9a62ba2d3d68 426 static void thunk(void *func) {
Christopher Haster 15:0c3d1c4a050b 427 return static_cast<Chainer<void(), N>*>(func)
Christopher Haster 7:9a62ba2d3d68 428 ->call();
Christopher Haster 7:9a62ba2d3d68 429 }
Christopher Haster 7:9a62ba2d3d68 430
Christopher Haster 7:9a62ba2d3d68 431 private:
Christopher Haster 7:9a62ba2d3d68 432 FuncPtr<void()> _funcs[N];
Christopher Haster 7:9a62ba2d3d68 433 };
Christopher Haster 7:9a62ba2d3d68 434
Christopher Haster 7:9a62ba2d3d68 435
Christopher Haster 7:9a62ba2d3d68 436 #endif