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 21:15:30 2016 -0500
Revision:
13:4d8a50d4967e
Parent:
8:71037a47492d
Child:
14:79be4e700cc9
Added funcptr namespace

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