MCU driver/HAL for the Picocell Gateway concentrator board. The firmware implements either a USB CDC protocol or a UART protocol to bridge commands coming from host to the SX1308 SPI interface.

Committer:
dgabino
Date:
Wed Apr 11 14:42:47 2018 +0000
Revision:
0:c76361bd82e8
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
dgabino 0:c76361bd82e8 1 /* mbed Microcontroller Library
dgabino 0:c76361bd82e8 2 * Copyright (c) 2006-2015 ARM Limited
dgabino 0:c76361bd82e8 3 *
dgabino 0:c76361bd82e8 4 * Licensed under the Apache License, Version 2.0 (the "License");
dgabino 0:c76361bd82e8 5 * you may not use this file except in compliance with the License.
dgabino 0:c76361bd82e8 6 * You may obtain a copy of the License at
dgabino 0:c76361bd82e8 7 *
dgabino 0:c76361bd82e8 8 * http://www.apache.org/licenses/LICENSE-2.0
dgabino 0:c76361bd82e8 9 *
dgabino 0:c76361bd82e8 10 * Unless required by applicable law or agreed to in writing, software
dgabino 0:c76361bd82e8 11 * distributed under the License is distributed on an "AS IS" BASIS,
dgabino 0:c76361bd82e8 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
dgabino 0:c76361bd82e8 13 * See the License for the specific language governing permissions and
dgabino 0:c76361bd82e8 14 * limitations under the License.
dgabino 0:c76361bd82e8 15 */
dgabino 0:c76361bd82e8 16 #ifndef MBED_CALLBACK_H
dgabino 0:c76361bd82e8 17 #define MBED_CALLBACK_H
dgabino 0:c76361bd82e8 18
dgabino 0:c76361bd82e8 19 #include <string.h>
dgabino 0:c76361bd82e8 20 #include <stdint.h>
dgabino 0:c76361bd82e8 21
dgabino 0:c76361bd82e8 22 namespace mbed {
dgabino 0:c76361bd82e8 23
dgabino 0:c76361bd82e8 24
dgabino 0:c76361bd82e8 25 /** Callback class based on template specialization
dgabino 0:c76361bd82e8 26 *
dgabino 0:c76361bd82e8 27 * @Note Synchronization level: Not protected
dgabino 0:c76361bd82e8 28 */
dgabino 0:c76361bd82e8 29 template <typename F>
dgabino 0:c76361bd82e8 30 class Callback;
dgabino 0:c76361bd82e8 31
dgabino 0:c76361bd82e8 32 /** Templated function class
dgabino 0:c76361bd82e8 33 */
dgabino 0:c76361bd82e8 34 template <typename R, typename A0, typename A1, typename A2, typename A3, typename A4>
dgabino 0:c76361bd82e8 35 class Callback<R(A0, A1, A2, A3, A4)> {
dgabino 0:c76361bd82e8 36 public:
dgabino 0:c76361bd82e8 37 /** Create a Callback with a static function
dgabino 0:c76361bd82e8 38 * @param func Static function to attach
dgabino 0:c76361bd82e8 39 */
dgabino 0:c76361bd82e8 40 Callback(R (*func)(A0, A1, A2, A3, A4) = 0) {
dgabino 0:c76361bd82e8 41 attach(func);
dgabino 0:c76361bd82e8 42 }
dgabino 0:c76361bd82e8 43
dgabino 0:c76361bd82e8 44 /** Create a Callback with a static function and bound pointer
dgabino 0:c76361bd82e8 45 * @param obj Pointer to object to bind to function
dgabino 0:c76361bd82e8 46 * @param func Static function to attach
dgabino 0:c76361bd82e8 47 */
dgabino 0:c76361bd82e8 48 template<typename T>
dgabino 0:c76361bd82e8 49 Callback(T *obj, R (*func)(T*, A0, A1, A2, A3, A4)) {
dgabino 0:c76361bd82e8 50 attach(obj, func);
dgabino 0:c76361bd82e8 51 }
dgabino 0:c76361bd82e8 52
dgabino 0:c76361bd82e8 53 /** Create a Callback with a member function
dgabino 0:c76361bd82e8 54 * @param obj Pointer to object to invoke member function on
dgabino 0:c76361bd82e8 55 * @param func Member function to attach
dgabino 0:c76361bd82e8 56 */
dgabino 0:c76361bd82e8 57 template<typename T>
dgabino 0:c76361bd82e8 58 Callback(T *obj, R (T::*func)(A0, A1, A2, A3, A4)) {
dgabino 0:c76361bd82e8 59 attach(obj, func);
dgabino 0:c76361bd82e8 60 }
dgabino 0:c76361bd82e8 61
dgabino 0:c76361bd82e8 62 /** Create a Callback with another Callback
dgabino 0:c76361bd82e8 63 * @param func Callback to attach
dgabino 0:c76361bd82e8 64 */
dgabino 0:c76361bd82e8 65 Callback(const Callback<R(A0, A1, A2, A3, A4)> &func) {
dgabino 0:c76361bd82e8 66 attach(func);
dgabino 0:c76361bd82e8 67 }
dgabino 0:c76361bd82e8 68
dgabino 0:c76361bd82e8 69 /** Attach a static function
dgabino 0:c76361bd82e8 70 * @param func Static function to attach
dgabino 0:c76361bd82e8 71 */
dgabino 0:c76361bd82e8 72 void attach(R (*func)(A0, A1, A2, A3, A4)) {
dgabino 0:c76361bd82e8 73 memcpy(&_func, &func, sizeof func);
dgabino 0:c76361bd82e8 74 _thunk = func ? &Callback::_staticthunk : 0;
dgabino 0:c76361bd82e8 75 }
dgabino 0:c76361bd82e8 76
dgabino 0:c76361bd82e8 77 /** Attach a static function with a bound pointer
dgabino 0:c76361bd82e8 78 * @param obj Pointer to object to bind to function
dgabino 0:c76361bd82e8 79 * @param func Static function to attach
dgabino 0:c76361bd82e8 80 */
dgabino 0:c76361bd82e8 81 template <typename T>
dgabino 0:c76361bd82e8 82 void attach(T *obj, R (*func)(T*, A0, A1, A2, A3, A4)) {
dgabino 0:c76361bd82e8 83 _obj = (void*)obj;
dgabino 0:c76361bd82e8 84 memcpy(&_func, &func, sizeof func);
dgabino 0:c76361bd82e8 85 _thunk = &Callback::_boundthunk<T>;
dgabino 0:c76361bd82e8 86 }
dgabino 0:c76361bd82e8 87
dgabino 0:c76361bd82e8 88 /** Attach a member function
dgabino 0:c76361bd82e8 89 * @param obj Pointer to object to invoke member function on
dgabino 0:c76361bd82e8 90 * @param func Member function to attach
dgabino 0:c76361bd82e8 91 */
dgabino 0:c76361bd82e8 92 template<typename T>
dgabino 0:c76361bd82e8 93 void attach(T *obj, R (T::*func)(A0, A1, A2, A3, A4)) {
dgabino 0:c76361bd82e8 94 _obj = static_cast<void*>(obj);
dgabino 0:c76361bd82e8 95 memcpy(&_func, &func, sizeof func);
dgabino 0:c76361bd82e8 96 _thunk = &Callback::_methodthunk<T>;
dgabino 0:c76361bd82e8 97 }
dgabino 0:c76361bd82e8 98
dgabino 0:c76361bd82e8 99 /** Attach a Callback
dgabino 0:c76361bd82e8 100 * @param func The Callback to attach
dgabino 0:c76361bd82e8 101 */
dgabino 0:c76361bd82e8 102 void attach(const Callback<R(A0, A1, A2, A3, A4)> &func) {
dgabino 0:c76361bd82e8 103 _obj = func._obj;
dgabino 0:c76361bd82e8 104 memcpy(&_func, &func._func, sizeof _func);
dgabino 0:c76361bd82e8 105 _thunk = func._thunk;
dgabino 0:c76361bd82e8 106 }
dgabino 0:c76361bd82e8 107
dgabino 0:c76361bd82e8 108 /** Call the attached function
dgabino 0:c76361bd82e8 109 */
dgabino 0:c76361bd82e8 110 R call(A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) {
dgabino 0:c76361bd82e8 111 if (!_thunk) {
dgabino 0:c76361bd82e8 112 return (R)0;
dgabino 0:c76361bd82e8 113 }
dgabino 0:c76361bd82e8 114 return _thunk(_obj, &_func, a0, a1, a2, a3, a4);
dgabino 0:c76361bd82e8 115 }
dgabino 0:c76361bd82e8 116
dgabino 0:c76361bd82e8 117 /** Call the attached function
dgabino 0:c76361bd82e8 118 */
dgabino 0:c76361bd82e8 119 R operator()(A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) {
dgabino 0:c76361bd82e8 120 return call(a0, a1, a2, a3, a4);
dgabino 0:c76361bd82e8 121 }
dgabino 0:c76361bd82e8 122
dgabino 0:c76361bd82e8 123 /** Test if function has been attached
dgabino 0:c76361bd82e8 124 */
dgabino 0:c76361bd82e8 125 operator bool() const {
dgabino 0:c76361bd82e8 126 return _thunk;
dgabino 0:c76361bd82e8 127 }
dgabino 0:c76361bd82e8 128
dgabino 0:c76361bd82e8 129 /** Static thunk for passing as C-style function
dgabino 0:c76361bd82e8 130 * @param func Callback to call passed as void pointer
dgabino 0:c76361bd82e8 131 */
dgabino 0:c76361bd82e8 132 static R thunk(void *func, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) {
dgabino 0:c76361bd82e8 133 return static_cast<Callback<R(A0, A1, A2, A3, A4)>*>(func)
dgabino 0:c76361bd82e8 134 ->call(a0, a1, a2, a3, a4);
dgabino 0:c76361bd82e8 135 }
dgabino 0:c76361bd82e8 136
dgabino 0:c76361bd82e8 137 private:
dgabino 0:c76361bd82e8 138 // Internal thunks for various function types
dgabino 0:c76361bd82e8 139 static R _staticthunk(void*, void *func, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) {
dgabino 0:c76361bd82e8 140 return (*reinterpret_cast<R (**)(A0, A1, A2, A3, A4)>(func))
dgabino 0:c76361bd82e8 141 (a0, a1, a2, a3, a4);
dgabino 0:c76361bd82e8 142 }
dgabino 0:c76361bd82e8 143
dgabino 0:c76361bd82e8 144 template<typename T>
dgabino 0:c76361bd82e8 145 static R _boundthunk(void *obj, void *func, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) {
dgabino 0:c76361bd82e8 146 return (*reinterpret_cast<R (**)(T*, A0, A1, A2, A3, A4)>(func))
dgabino 0:c76361bd82e8 147 (static_cast<T*>(obj), a0, a1, a2, a3, a4);
dgabino 0:c76361bd82e8 148 }
dgabino 0:c76361bd82e8 149
dgabino 0:c76361bd82e8 150 template<typename T>
dgabino 0:c76361bd82e8 151 static R _methodthunk(void *obj, void *func, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) {
dgabino 0:c76361bd82e8 152 return (static_cast<T*>(obj)->*
dgabino 0:c76361bd82e8 153 (*reinterpret_cast<R (T::**)(A0, A1, A2, A3, A4)>(func)))
dgabino 0:c76361bd82e8 154 (a0, a1, a2, a3, a4);
dgabino 0:c76361bd82e8 155 }
dgabino 0:c76361bd82e8 156
dgabino 0:c76361bd82e8 157 // Stored as pointer to function and pointer to optional object
dgabino 0:c76361bd82e8 158 // Function pointer is stored as union of possible function types
dgabino 0:c76361bd82e8 159 // to garuntee proper size and alignment
dgabino 0:c76361bd82e8 160 struct _class;
dgabino 0:c76361bd82e8 161 union {
dgabino 0:c76361bd82e8 162 void (*_staticfunc)();
dgabino 0:c76361bd82e8 163 void (*_boundfunc)(_class *);
dgabino 0:c76361bd82e8 164 void (_class::*_methodfunc)();
dgabino 0:c76361bd82e8 165 } _func;
dgabino 0:c76361bd82e8 166
dgabino 0:c76361bd82e8 167 void *_obj;
dgabino 0:c76361bd82e8 168
dgabino 0:c76361bd82e8 169 // Thunk registered on attach to dispatch calls
dgabino 0:c76361bd82e8 170 R (*_thunk)(void*, void*, A0, A1, A2, A3, A4);
dgabino 0:c76361bd82e8 171 };
dgabino 0:c76361bd82e8 172
dgabino 0:c76361bd82e8 173 /** Templated function class
dgabino 0:c76361bd82e8 174 */
dgabino 0:c76361bd82e8 175 template <typename R, typename A0, typename A1, typename A2, typename A3>
dgabino 0:c76361bd82e8 176 class Callback<R(A0, A1, A2, A3)> {
dgabino 0:c76361bd82e8 177 public:
dgabino 0:c76361bd82e8 178 /** Create a Callback with a static function
dgabino 0:c76361bd82e8 179 * @param func Static function to attach
dgabino 0:c76361bd82e8 180 */
dgabino 0:c76361bd82e8 181 Callback(R (*func)(A0, A1, A2, A3) = 0) {
dgabino 0:c76361bd82e8 182 attach(func);
dgabino 0:c76361bd82e8 183 }
dgabino 0:c76361bd82e8 184
dgabino 0:c76361bd82e8 185 /** Create a Callback with a static function and bound pointer
dgabino 0:c76361bd82e8 186 * @param obj Pointer to object to bind to function
dgabino 0:c76361bd82e8 187 * @param func Static function to attach
dgabino 0:c76361bd82e8 188 */
dgabino 0:c76361bd82e8 189 template<typename T>
dgabino 0:c76361bd82e8 190 Callback(T *obj, R (*func)(T*, A0, A1, A2, A3)) {
dgabino 0:c76361bd82e8 191 attach(obj, func);
dgabino 0:c76361bd82e8 192 }
dgabino 0:c76361bd82e8 193
dgabino 0:c76361bd82e8 194 /** Create a Callback with a member function
dgabino 0:c76361bd82e8 195 * @param obj Pointer to object to invoke member function on
dgabino 0:c76361bd82e8 196 * @param func Member function to attach
dgabino 0:c76361bd82e8 197 */
dgabino 0:c76361bd82e8 198 template<typename T>
dgabino 0:c76361bd82e8 199 Callback(T *obj, R (T::*func)(A0, A1, A2, A3)) {
dgabino 0:c76361bd82e8 200 attach(obj, func);
dgabino 0:c76361bd82e8 201 }
dgabino 0:c76361bd82e8 202
dgabino 0:c76361bd82e8 203 /** Create a Callback with another Callback
dgabino 0:c76361bd82e8 204 * @param func Callback to attach
dgabino 0:c76361bd82e8 205 */
dgabino 0:c76361bd82e8 206 Callback(const Callback<R(A0, A1, A2, A3)> &func) {
dgabino 0:c76361bd82e8 207 attach(func);
dgabino 0:c76361bd82e8 208 }
dgabino 0:c76361bd82e8 209
dgabino 0:c76361bd82e8 210 /** Attach a static function
dgabino 0:c76361bd82e8 211 * @param func Static function to attach
dgabino 0:c76361bd82e8 212 */
dgabino 0:c76361bd82e8 213 void attach(R (*func)(A0, A1, A2, A3)) {
dgabino 0:c76361bd82e8 214 memcpy(&_func, &func, sizeof func);
dgabino 0:c76361bd82e8 215 _thunk = func ? &Callback::_staticthunk : 0;
dgabino 0:c76361bd82e8 216 }
dgabino 0:c76361bd82e8 217
dgabino 0:c76361bd82e8 218 /** Attach a static function with a bound pointer
dgabino 0:c76361bd82e8 219 * @param obj Pointer to object to bind to function
dgabino 0:c76361bd82e8 220 * @param func Static function to attach
dgabino 0:c76361bd82e8 221 */
dgabino 0:c76361bd82e8 222 template <typename T>
dgabino 0:c76361bd82e8 223 void attach(T *obj, R (*func)(T*, A0, A1, A2, A3)) {
dgabino 0:c76361bd82e8 224 _obj = (void*)obj;
dgabino 0:c76361bd82e8 225 memcpy(&_func, &func, sizeof func);
dgabino 0:c76361bd82e8 226 _thunk = &Callback::_boundthunk<T>;
dgabino 0:c76361bd82e8 227 }
dgabino 0:c76361bd82e8 228
dgabino 0:c76361bd82e8 229 /** Attach a member function
dgabino 0:c76361bd82e8 230 * @param obj Pointer to object to invoke member function on
dgabino 0:c76361bd82e8 231 * @param func Member function to attach
dgabino 0:c76361bd82e8 232 */
dgabino 0:c76361bd82e8 233 template<typename T>
dgabino 0:c76361bd82e8 234 void attach(T *obj, R (T::*func)(A0, A1, A2, A3)) {
dgabino 0:c76361bd82e8 235 _obj = static_cast<void*>(obj);
dgabino 0:c76361bd82e8 236 memcpy(&_func, &func, sizeof func);
dgabino 0:c76361bd82e8 237 _thunk = &Callback::_methodthunk<T>;
dgabino 0:c76361bd82e8 238 }
dgabino 0:c76361bd82e8 239
dgabino 0:c76361bd82e8 240 /** Attach a Callback
dgabino 0:c76361bd82e8 241 * @param func The Callback to attach
dgabino 0:c76361bd82e8 242 */
dgabino 0:c76361bd82e8 243 void attach(const Callback<R(A0, A1, A2, A3)> &func) {
dgabino 0:c76361bd82e8 244 _obj = func._obj;
dgabino 0:c76361bd82e8 245 memcpy(&_func, &func._func, sizeof _func);
dgabino 0:c76361bd82e8 246 _thunk = func._thunk;
dgabino 0:c76361bd82e8 247 }
dgabino 0:c76361bd82e8 248
dgabino 0:c76361bd82e8 249 /** Call the attached function
dgabino 0:c76361bd82e8 250 */
dgabino 0:c76361bd82e8 251 R call(A0 a0, A1 a1, A2 a2, A3 a3) {
dgabino 0:c76361bd82e8 252 if (!_thunk) {
dgabino 0:c76361bd82e8 253 return (R)0;
dgabino 0:c76361bd82e8 254 }
dgabino 0:c76361bd82e8 255 return _thunk(_obj, &_func, a0, a1, a2, a3);
dgabino 0:c76361bd82e8 256 }
dgabino 0:c76361bd82e8 257
dgabino 0:c76361bd82e8 258 /** Call the attached function
dgabino 0:c76361bd82e8 259 */
dgabino 0:c76361bd82e8 260 R operator()(A0 a0, A1 a1, A2 a2, A3 a3) {
dgabino 0:c76361bd82e8 261 return call(a0, a1, a2, a3);
dgabino 0:c76361bd82e8 262 }
dgabino 0:c76361bd82e8 263
dgabino 0:c76361bd82e8 264 /** Test if function has been attached
dgabino 0:c76361bd82e8 265 */
dgabino 0:c76361bd82e8 266 operator bool() const {
dgabino 0:c76361bd82e8 267 return _thunk;
dgabino 0:c76361bd82e8 268 }
dgabino 0:c76361bd82e8 269
dgabino 0:c76361bd82e8 270 /** Static thunk for passing as C-style function
dgabino 0:c76361bd82e8 271 * @param func Callback to call passed as void pointer
dgabino 0:c76361bd82e8 272 */
dgabino 0:c76361bd82e8 273 static R thunk(void *func, A0 a0, A1 a1, A2 a2, A3 a3) {
dgabino 0:c76361bd82e8 274 return static_cast<Callback<R(A0, A1, A2, A3)>*>(func)
dgabino 0:c76361bd82e8 275 ->call(a0, a1, a2, a3);
dgabino 0:c76361bd82e8 276 }
dgabino 0:c76361bd82e8 277
dgabino 0:c76361bd82e8 278 private:
dgabino 0:c76361bd82e8 279 // Internal thunks for various function types
dgabino 0:c76361bd82e8 280 static R _staticthunk(void*, void *func, A0 a0, A1 a1, A2 a2, A3 a3) {
dgabino 0:c76361bd82e8 281 return (*reinterpret_cast<R (**)(A0, A1, A2, A3)>(func))
dgabino 0:c76361bd82e8 282 (a0, a1, a2, a3);
dgabino 0:c76361bd82e8 283 }
dgabino 0:c76361bd82e8 284
dgabino 0:c76361bd82e8 285 template<typename T>
dgabino 0:c76361bd82e8 286 static R _boundthunk(void *obj, void *func, A0 a0, A1 a1, A2 a2, A3 a3) {
dgabino 0:c76361bd82e8 287 return (*reinterpret_cast<R (**)(T*, A0, A1, A2, A3)>(func))
dgabino 0:c76361bd82e8 288 (static_cast<T*>(obj), a0, a1, a2, a3);
dgabino 0:c76361bd82e8 289 }
dgabino 0:c76361bd82e8 290
dgabino 0:c76361bd82e8 291 template<typename T>
dgabino 0:c76361bd82e8 292 static R _methodthunk(void *obj, void *func, A0 a0, A1 a1, A2 a2, A3 a3) {
dgabino 0:c76361bd82e8 293 return (static_cast<T*>(obj)->*
dgabino 0:c76361bd82e8 294 (*reinterpret_cast<R (T::**)(A0, A1, A2, A3)>(func)))
dgabino 0:c76361bd82e8 295 (a0, a1, a2, a3);
dgabino 0:c76361bd82e8 296 }
dgabino 0:c76361bd82e8 297
dgabino 0:c76361bd82e8 298 // Stored as pointer to function and pointer to optional object
dgabino 0:c76361bd82e8 299 // Function pointer is stored as union of possible function types
dgabino 0:c76361bd82e8 300 // to garuntee proper size and alignment
dgabino 0:c76361bd82e8 301 struct _class;
dgabino 0:c76361bd82e8 302 union {
dgabino 0:c76361bd82e8 303 void (*_staticfunc)();
dgabino 0:c76361bd82e8 304 void (*_boundfunc)(_class *);
dgabino 0:c76361bd82e8 305 void (_class::*_methodfunc)();
dgabino 0:c76361bd82e8 306 } _func;
dgabino 0:c76361bd82e8 307
dgabino 0:c76361bd82e8 308 void *_obj;
dgabino 0:c76361bd82e8 309
dgabino 0:c76361bd82e8 310 // Thunk registered on attach to dispatch calls
dgabino 0:c76361bd82e8 311 R (*_thunk)(void*, void*, A0, A1, A2, A3);
dgabino 0:c76361bd82e8 312 };
dgabino 0:c76361bd82e8 313
dgabino 0:c76361bd82e8 314 /** Templated function class
dgabino 0:c76361bd82e8 315 */
dgabino 0:c76361bd82e8 316 template <typename R, typename A0, typename A1, typename A2>
dgabino 0:c76361bd82e8 317 class Callback<R(A0, A1, A2)> {
dgabino 0:c76361bd82e8 318 public:
dgabino 0:c76361bd82e8 319 /** Create a Callback with a static function
dgabino 0:c76361bd82e8 320 * @param func Static function to attach
dgabino 0:c76361bd82e8 321 */
dgabino 0:c76361bd82e8 322 Callback(R (*func)(A0, A1, A2) = 0) {
dgabino 0:c76361bd82e8 323 attach(func);
dgabino 0:c76361bd82e8 324 }
dgabino 0:c76361bd82e8 325
dgabino 0:c76361bd82e8 326 /** Create a Callback with a static function and bound pointer
dgabino 0:c76361bd82e8 327 * @param obj Pointer to object to bind to function
dgabino 0:c76361bd82e8 328 * @param func Static function to attach
dgabino 0:c76361bd82e8 329 */
dgabino 0:c76361bd82e8 330 template<typename T>
dgabino 0:c76361bd82e8 331 Callback(T *obj, R (*func)(T*, A0, A1, A2)) {
dgabino 0:c76361bd82e8 332 attach(obj, func);
dgabino 0:c76361bd82e8 333 }
dgabino 0:c76361bd82e8 334
dgabino 0:c76361bd82e8 335 /** Create a Callback with a member function
dgabino 0:c76361bd82e8 336 * @param obj Pointer to object to invoke member function on
dgabino 0:c76361bd82e8 337 * @param func Member function to attach
dgabino 0:c76361bd82e8 338 */
dgabino 0:c76361bd82e8 339 template<typename T>
dgabino 0:c76361bd82e8 340 Callback(T *obj, R (T::*func)(A0, A1, A2)) {
dgabino 0:c76361bd82e8 341 attach(obj, func);
dgabino 0:c76361bd82e8 342 }
dgabino 0:c76361bd82e8 343
dgabino 0:c76361bd82e8 344 /** Create a Callback with another Callback
dgabino 0:c76361bd82e8 345 * @param func Callback to attach
dgabino 0:c76361bd82e8 346 */
dgabino 0:c76361bd82e8 347 Callback(const Callback<R(A0, A1, A2)> &func) {
dgabino 0:c76361bd82e8 348 attach(func);
dgabino 0:c76361bd82e8 349 }
dgabino 0:c76361bd82e8 350
dgabino 0:c76361bd82e8 351 /** Attach a static function
dgabino 0:c76361bd82e8 352 * @param func Static function to attach
dgabino 0:c76361bd82e8 353 */
dgabino 0:c76361bd82e8 354 void attach(R (*func)(A0, A1, A2)) {
dgabino 0:c76361bd82e8 355 memcpy(&_func, &func, sizeof func);
dgabino 0:c76361bd82e8 356 _thunk = func ? &Callback::_staticthunk : 0;
dgabino 0:c76361bd82e8 357 }
dgabino 0:c76361bd82e8 358
dgabino 0:c76361bd82e8 359 /** Attach a static function with a bound pointer
dgabino 0:c76361bd82e8 360 * @param obj Pointer to object to bind to function
dgabino 0:c76361bd82e8 361 * @param func Static function to attach
dgabino 0:c76361bd82e8 362 */
dgabino 0:c76361bd82e8 363 template <typename T>
dgabino 0:c76361bd82e8 364 void attach(T *obj, R (*func)(T*, A0, A1, A2)) {
dgabino 0:c76361bd82e8 365 _obj = (void*)obj;
dgabino 0:c76361bd82e8 366 memcpy(&_func, &func, sizeof func);
dgabino 0:c76361bd82e8 367 _thunk = &Callback::_boundthunk<T>;
dgabino 0:c76361bd82e8 368 }
dgabino 0:c76361bd82e8 369
dgabino 0:c76361bd82e8 370 /** Attach a member function
dgabino 0:c76361bd82e8 371 * @param obj Pointer to object to invoke member function on
dgabino 0:c76361bd82e8 372 * @param func Member function to attach
dgabino 0:c76361bd82e8 373 */
dgabino 0:c76361bd82e8 374 template<typename T>
dgabino 0:c76361bd82e8 375 void attach(T *obj, R (T::*func)(A0, A1, A2)) {
dgabino 0:c76361bd82e8 376 _obj = static_cast<void*>(obj);
dgabino 0:c76361bd82e8 377 memcpy(&_func, &func, sizeof func);
dgabino 0:c76361bd82e8 378 _thunk = &Callback::_methodthunk<T>;
dgabino 0:c76361bd82e8 379 }
dgabino 0:c76361bd82e8 380
dgabino 0:c76361bd82e8 381 /** Attach a Callback
dgabino 0:c76361bd82e8 382 * @param func The Callback to attach
dgabino 0:c76361bd82e8 383 */
dgabino 0:c76361bd82e8 384 void attach(const Callback<R(A0, A1, A2)> &func) {
dgabino 0:c76361bd82e8 385 _obj = func._obj;
dgabino 0:c76361bd82e8 386 memcpy(&_func, &func._func, sizeof _func);
dgabino 0:c76361bd82e8 387 _thunk = func._thunk;
dgabino 0:c76361bd82e8 388 }
dgabino 0:c76361bd82e8 389
dgabino 0:c76361bd82e8 390 /** Call the attached function
dgabino 0:c76361bd82e8 391 */
dgabino 0:c76361bd82e8 392 R call(A0 a0, A1 a1, A2 a2) {
dgabino 0:c76361bd82e8 393 if (!_thunk) {
dgabino 0:c76361bd82e8 394 return (R)0;
dgabino 0:c76361bd82e8 395 }
dgabino 0:c76361bd82e8 396 return _thunk(_obj, &_func, a0, a1, a2);
dgabino 0:c76361bd82e8 397 }
dgabino 0:c76361bd82e8 398
dgabino 0:c76361bd82e8 399 /** Call the attached function
dgabino 0:c76361bd82e8 400 */
dgabino 0:c76361bd82e8 401 R operator()(A0 a0, A1 a1, A2 a2) {
dgabino 0:c76361bd82e8 402 return call(a0, a1, a2);
dgabino 0:c76361bd82e8 403 }
dgabino 0:c76361bd82e8 404
dgabino 0:c76361bd82e8 405 /** Test if function has been attached
dgabino 0:c76361bd82e8 406 */
dgabino 0:c76361bd82e8 407 operator bool() const {
dgabino 0:c76361bd82e8 408 return _thunk;
dgabino 0:c76361bd82e8 409 }
dgabino 0:c76361bd82e8 410
dgabino 0:c76361bd82e8 411 /** Static thunk for passing as C-style function
dgabino 0:c76361bd82e8 412 * @param func Callback to call passed as void pointer
dgabino 0:c76361bd82e8 413 */
dgabino 0:c76361bd82e8 414 static R thunk(void *func, A0 a0, A1 a1, A2 a2) {
dgabino 0:c76361bd82e8 415 return static_cast<Callback<R(A0, A1, A2)>*>(func)
dgabino 0:c76361bd82e8 416 ->call(a0, a1, a2);
dgabino 0:c76361bd82e8 417 }
dgabino 0:c76361bd82e8 418
dgabino 0:c76361bd82e8 419 private:
dgabino 0:c76361bd82e8 420 // Internal thunks for various function types
dgabino 0:c76361bd82e8 421 static R _staticthunk(void*, void *func, A0 a0, A1 a1, A2 a2) {
dgabino 0:c76361bd82e8 422 return (*reinterpret_cast<R (**)(A0, A1, A2)>(func))
dgabino 0:c76361bd82e8 423 (a0, a1, a2);
dgabino 0:c76361bd82e8 424 }
dgabino 0:c76361bd82e8 425
dgabino 0:c76361bd82e8 426 template<typename T>
dgabino 0:c76361bd82e8 427 static R _boundthunk(void *obj, void *func, A0 a0, A1 a1, A2 a2) {
dgabino 0:c76361bd82e8 428 return (*reinterpret_cast<R (**)(T*, A0, A1, A2)>(func))
dgabino 0:c76361bd82e8 429 (static_cast<T*>(obj), a0, a1, a2);
dgabino 0:c76361bd82e8 430 }
dgabino 0:c76361bd82e8 431
dgabino 0:c76361bd82e8 432 template<typename T>
dgabino 0:c76361bd82e8 433 static R _methodthunk(void *obj, void *func, A0 a0, A1 a1, A2 a2) {
dgabino 0:c76361bd82e8 434 return (static_cast<T*>(obj)->*
dgabino 0:c76361bd82e8 435 (*reinterpret_cast<R (T::**)(A0, A1, A2)>(func)))
dgabino 0:c76361bd82e8 436 (a0, a1, a2);
dgabino 0:c76361bd82e8 437 }
dgabino 0:c76361bd82e8 438
dgabino 0:c76361bd82e8 439 // Stored as pointer to function and pointer to optional object
dgabino 0:c76361bd82e8 440 // Function pointer is stored as union of possible function types
dgabino 0:c76361bd82e8 441 // to garuntee proper size and alignment
dgabino 0:c76361bd82e8 442 struct _class;
dgabino 0:c76361bd82e8 443 union {
dgabino 0:c76361bd82e8 444 void (*_staticfunc)();
dgabino 0:c76361bd82e8 445 void (*_boundfunc)(_class *);
dgabino 0:c76361bd82e8 446 void (_class::*_methodfunc)();
dgabino 0:c76361bd82e8 447 } _func;
dgabino 0:c76361bd82e8 448
dgabino 0:c76361bd82e8 449 void *_obj;
dgabino 0:c76361bd82e8 450
dgabino 0:c76361bd82e8 451 // Thunk registered on attach to dispatch calls
dgabino 0:c76361bd82e8 452 R (*_thunk)(void*, void*, A0, A1, A2);
dgabino 0:c76361bd82e8 453 };
dgabino 0:c76361bd82e8 454
dgabino 0:c76361bd82e8 455 /** Templated function class
dgabino 0:c76361bd82e8 456 */
dgabino 0:c76361bd82e8 457 template <typename R, typename A0, typename A1>
dgabino 0:c76361bd82e8 458 class Callback<R(A0, A1)> {
dgabino 0:c76361bd82e8 459 public:
dgabino 0:c76361bd82e8 460 /** Create a Callback with a static function
dgabino 0:c76361bd82e8 461 * @param func Static function to attach
dgabino 0:c76361bd82e8 462 */
dgabino 0:c76361bd82e8 463 Callback(R (*func)(A0, A1) = 0) {
dgabino 0:c76361bd82e8 464 attach(func);
dgabino 0:c76361bd82e8 465 }
dgabino 0:c76361bd82e8 466
dgabino 0:c76361bd82e8 467 /** Create a Callback with a static function and bound pointer
dgabino 0:c76361bd82e8 468 * @param obj Pointer to object to bind to function
dgabino 0:c76361bd82e8 469 * @param func Static function to attach
dgabino 0:c76361bd82e8 470 */
dgabino 0:c76361bd82e8 471 template<typename T>
dgabino 0:c76361bd82e8 472 Callback(T *obj, R (*func)(T*, A0, A1)) {
dgabino 0:c76361bd82e8 473 attach(obj, func);
dgabino 0:c76361bd82e8 474 }
dgabino 0:c76361bd82e8 475
dgabino 0:c76361bd82e8 476 /** Create a Callback with a member function
dgabino 0:c76361bd82e8 477 * @param obj Pointer to object to invoke member function on
dgabino 0:c76361bd82e8 478 * @param func Member function to attach
dgabino 0:c76361bd82e8 479 */
dgabino 0:c76361bd82e8 480 template<typename T>
dgabino 0:c76361bd82e8 481 Callback(T *obj, R (T::*func)(A0, A1)) {
dgabino 0:c76361bd82e8 482 attach(obj, func);
dgabino 0:c76361bd82e8 483 }
dgabino 0:c76361bd82e8 484
dgabino 0:c76361bd82e8 485 /** Create a Callback with another Callback
dgabino 0:c76361bd82e8 486 * @param func Callback to attach
dgabino 0:c76361bd82e8 487 */
dgabino 0:c76361bd82e8 488 Callback(const Callback<R(A0, A1)> &func) {
dgabino 0:c76361bd82e8 489 attach(func);
dgabino 0:c76361bd82e8 490 }
dgabino 0:c76361bd82e8 491
dgabino 0:c76361bd82e8 492 /** Attach a static function
dgabino 0:c76361bd82e8 493 * @param func Static function to attach
dgabino 0:c76361bd82e8 494 */
dgabino 0:c76361bd82e8 495 void attach(R (*func)(A0, A1)) {
dgabino 0:c76361bd82e8 496 memcpy(&_func, &func, sizeof func);
dgabino 0:c76361bd82e8 497 _thunk = func ? &Callback::_staticthunk : 0;
dgabino 0:c76361bd82e8 498 }
dgabino 0:c76361bd82e8 499
dgabino 0:c76361bd82e8 500 /** Attach a static function with a bound pointer
dgabino 0:c76361bd82e8 501 * @param obj Pointer to object to bind to function
dgabino 0:c76361bd82e8 502 * @param func Static function to attach
dgabino 0:c76361bd82e8 503 */
dgabino 0:c76361bd82e8 504 template <typename T>
dgabino 0:c76361bd82e8 505 void attach(T *obj, R (*func)(T*, A0, A1)) {
dgabino 0:c76361bd82e8 506 _obj = (void*)obj;
dgabino 0:c76361bd82e8 507 memcpy(&_func, &func, sizeof func);
dgabino 0:c76361bd82e8 508 _thunk = &Callback::_boundthunk<T>;
dgabino 0:c76361bd82e8 509 }
dgabino 0:c76361bd82e8 510
dgabino 0:c76361bd82e8 511 /** Attach a member function
dgabino 0:c76361bd82e8 512 * @param obj Pointer to object to invoke member function on
dgabino 0:c76361bd82e8 513 * @param func Member function to attach
dgabino 0:c76361bd82e8 514 */
dgabino 0:c76361bd82e8 515 template<typename T>
dgabino 0:c76361bd82e8 516 void attach(T *obj, R (T::*func)(A0, A1)) {
dgabino 0:c76361bd82e8 517 _obj = static_cast<void*>(obj);
dgabino 0:c76361bd82e8 518 memcpy(&_func, &func, sizeof func);
dgabino 0:c76361bd82e8 519 _thunk = &Callback::_methodthunk<T>;
dgabino 0:c76361bd82e8 520 }
dgabino 0:c76361bd82e8 521
dgabino 0:c76361bd82e8 522 /** Attach a Callback
dgabino 0:c76361bd82e8 523 * @param func The Callback to attach
dgabino 0:c76361bd82e8 524 */
dgabino 0:c76361bd82e8 525 void attach(const Callback<R(A0, A1)> &func) {
dgabino 0:c76361bd82e8 526 _obj = func._obj;
dgabino 0:c76361bd82e8 527 memcpy(&_func, &func._func, sizeof _func);
dgabino 0:c76361bd82e8 528 _thunk = func._thunk;
dgabino 0:c76361bd82e8 529 }
dgabino 0:c76361bd82e8 530
dgabino 0:c76361bd82e8 531 /** Call the attached function
dgabino 0:c76361bd82e8 532 */
dgabino 0:c76361bd82e8 533 R call(A0 a0, A1 a1) {
dgabino 0:c76361bd82e8 534 if (!_thunk) {
dgabino 0:c76361bd82e8 535 return (R)0;
dgabino 0:c76361bd82e8 536 }
dgabino 0:c76361bd82e8 537 return _thunk(_obj, &_func, a0, a1);
dgabino 0:c76361bd82e8 538 }
dgabino 0:c76361bd82e8 539
dgabino 0:c76361bd82e8 540 /** Call the attached function
dgabino 0:c76361bd82e8 541 */
dgabino 0:c76361bd82e8 542 R operator()(A0 a0, A1 a1) {
dgabino 0:c76361bd82e8 543 return call(a0, a1);
dgabino 0:c76361bd82e8 544 }
dgabino 0:c76361bd82e8 545
dgabino 0:c76361bd82e8 546 /** Test if function has been attached
dgabino 0:c76361bd82e8 547 */
dgabino 0:c76361bd82e8 548 operator bool() const {
dgabino 0:c76361bd82e8 549 return _thunk;
dgabino 0:c76361bd82e8 550 }
dgabino 0:c76361bd82e8 551
dgabino 0:c76361bd82e8 552 /** Static thunk for passing as C-style function
dgabino 0:c76361bd82e8 553 * @param func Callback to call passed as void pointer
dgabino 0:c76361bd82e8 554 */
dgabino 0:c76361bd82e8 555 static R thunk(void *func, A0 a0, A1 a1) {
dgabino 0:c76361bd82e8 556 return static_cast<Callback<R(A0, A1)>*>(func)
dgabino 0:c76361bd82e8 557 ->call(a0, a1);
dgabino 0:c76361bd82e8 558 }
dgabino 0:c76361bd82e8 559
dgabino 0:c76361bd82e8 560 private:
dgabino 0:c76361bd82e8 561 // Internal thunks for various function types
dgabino 0:c76361bd82e8 562 static R _staticthunk(void*, void *func, A0 a0, A1 a1) {
dgabino 0:c76361bd82e8 563 return (*reinterpret_cast<R (**)(A0, A1)>(func))
dgabino 0:c76361bd82e8 564 (a0, a1);
dgabino 0:c76361bd82e8 565 }
dgabino 0:c76361bd82e8 566
dgabino 0:c76361bd82e8 567 template<typename T>
dgabino 0:c76361bd82e8 568 static R _boundthunk(void *obj, void *func, A0 a0, A1 a1) {
dgabino 0:c76361bd82e8 569 return (*reinterpret_cast<R (**)(T*, A0, A1)>(func))
dgabino 0:c76361bd82e8 570 (static_cast<T*>(obj), a0, a1);
dgabino 0:c76361bd82e8 571 }
dgabino 0:c76361bd82e8 572
dgabino 0:c76361bd82e8 573 template<typename T>
dgabino 0:c76361bd82e8 574 static R _methodthunk(void *obj, void *func, A0 a0, A1 a1) {
dgabino 0:c76361bd82e8 575 return (static_cast<T*>(obj)->*
dgabino 0:c76361bd82e8 576 (*reinterpret_cast<R (T::**)(A0, A1)>(func)))
dgabino 0:c76361bd82e8 577 (a0, a1);
dgabino 0:c76361bd82e8 578 }
dgabino 0:c76361bd82e8 579
dgabino 0:c76361bd82e8 580 // Stored as pointer to function and pointer to optional object
dgabino 0:c76361bd82e8 581 // Function pointer is stored as union of possible function types
dgabino 0:c76361bd82e8 582 // to garuntee proper size and alignment
dgabino 0:c76361bd82e8 583 struct _class;
dgabino 0:c76361bd82e8 584 union {
dgabino 0:c76361bd82e8 585 void (*_staticfunc)();
dgabino 0:c76361bd82e8 586 void (*_boundfunc)(_class *);
dgabino 0:c76361bd82e8 587 void (_class::*_methodfunc)();
dgabino 0:c76361bd82e8 588 } _func;
dgabino 0:c76361bd82e8 589
dgabino 0:c76361bd82e8 590 void *_obj;
dgabino 0:c76361bd82e8 591
dgabino 0:c76361bd82e8 592 // Thunk registered on attach to dispatch calls
dgabino 0:c76361bd82e8 593 R (*_thunk)(void*, void*, A0, A1);
dgabino 0:c76361bd82e8 594 };
dgabino 0:c76361bd82e8 595
dgabino 0:c76361bd82e8 596 /** Templated function class
dgabino 0:c76361bd82e8 597 */
dgabino 0:c76361bd82e8 598 template <typename R, typename A0>
dgabino 0:c76361bd82e8 599 class Callback<R(A0)> {
dgabino 0:c76361bd82e8 600 public:
dgabino 0:c76361bd82e8 601 /** Create a Callback with a static function
dgabino 0:c76361bd82e8 602 * @param func Static function to attach
dgabino 0:c76361bd82e8 603 */
dgabino 0:c76361bd82e8 604 Callback(R (*func)(A0) = 0) {
dgabino 0:c76361bd82e8 605 attach(func);
dgabino 0:c76361bd82e8 606 }
dgabino 0:c76361bd82e8 607
dgabino 0:c76361bd82e8 608 /** Create a Callback with a static function and bound pointer
dgabino 0:c76361bd82e8 609 * @param obj Pointer to object to bind to function
dgabino 0:c76361bd82e8 610 * @param func Static function to attach
dgabino 0:c76361bd82e8 611 */
dgabino 0:c76361bd82e8 612 template<typename T>
dgabino 0:c76361bd82e8 613 Callback(T *obj, R (*func)(T*, A0)) {
dgabino 0:c76361bd82e8 614 attach(obj, func);
dgabino 0:c76361bd82e8 615 }
dgabino 0:c76361bd82e8 616
dgabino 0:c76361bd82e8 617 /** Create a Callback with a member function
dgabino 0:c76361bd82e8 618 * @param obj Pointer to object to invoke member function on
dgabino 0:c76361bd82e8 619 * @param func Member function to attach
dgabino 0:c76361bd82e8 620 */
dgabino 0:c76361bd82e8 621 template<typename T>
dgabino 0:c76361bd82e8 622 Callback(T *obj, R (T::*func)(A0)) {
dgabino 0:c76361bd82e8 623 attach(obj, func);
dgabino 0:c76361bd82e8 624 }
dgabino 0:c76361bd82e8 625
dgabino 0:c76361bd82e8 626 /** Create a Callback with another Callback
dgabino 0:c76361bd82e8 627 * @param func Callback to attach
dgabino 0:c76361bd82e8 628 */
dgabino 0:c76361bd82e8 629 Callback(const Callback<R(A0)> &func) {
dgabino 0:c76361bd82e8 630 attach(func);
dgabino 0:c76361bd82e8 631 }
dgabino 0:c76361bd82e8 632
dgabino 0:c76361bd82e8 633 /** Attach a static function
dgabino 0:c76361bd82e8 634 * @param func Static function to attach
dgabino 0:c76361bd82e8 635 */
dgabino 0:c76361bd82e8 636 void attach(R (*func)(A0)) {
dgabino 0:c76361bd82e8 637 memcpy(&_func, &func, sizeof func);
dgabino 0:c76361bd82e8 638 _thunk = func ? &Callback::_staticthunk : 0;
dgabino 0:c76361bd82e8 639 }
dgabino 0:c76361bd82e8 640
dgabino 0:c76361bd82e8 641 /** Attach a static function with a bound pointer
dgabino 0:c76361bd82e8 642 * @param obj Pointer to object to bind to function
dgabino 0:c76361bd82e8 643 * @param func Static function to attach
dgabino 0:c76361bd82e8 644 */
dgabino 0:c76361bd82e8 645 template <typename T>
dgabino 0:c76361bd82e8 646 void attach(T *obj, R (*func)(T*, A0)) {
dgabino 0:c76361bd82e8 647 _obj = (void*)obj;
dgabino 0:c76361bd82e8 648 memcpy(&_func, &func, sizeof func);
dgabino 0:c76361bd82e8 649 _thunk = &Callback::_boundthunk<T>;
dgabino 0:c76361bd82e8 650 }
dgabino 0:c76361bd82e8 651
dgabino 0:c76361bd82e8 652 /** Attach a member function
dgabino 0:c76361bd82e8 653 * @param obj Pointer to object to invoke member function on
dgabino 0:c76361bd82e8 654 * @param func Member function to attach
dgabino 0:c76361bd82e8 655 */
dgabino 0:c76361bd82e8 656 template<typename T>
dgabino 0:c76361bd82e8 657 void attach(T *obj, R (T::*func)(A0)) {
dgabino 0:c76361bd82e8 658 _obj = static_cast<void*>(obj);
dgabino 0:c76361bd82e8 659 memcpy(&_func, &func, sizeof func);
dgabino 0:c76361bd82e8 660 _thunk = &Callback::_methodthunk<T>;
dgabino 0:c76361bd82e8 661 }
dgabino 0:c76361bd82e8 662
dgabino 0:c76361bd82e8 663 /** Attach a Callback
dgabino 0:c76361bd82e8 664 * @param func The Callback to attach
dgabino 0:c76361bd82e8 665 */
dgabino 0:c76361bd82e8 666 void attach(const Callback<R(A0)> &func) {
dgabino 0:c76361bd82e8 667 _obj = func._obj;
dgabino 0:c76361bd82e8 668 memcpy(&_func, &func._func, sizeof _func);
dgabino 0:c76361bd82e8 669 _thunk = func._thunk;
dgabino 0:c76361bd82e8 670 }
dgabino 0:c76361bd82e8 671
dgabino 0:c76361bd82e8 672 /** Call the attached function
dgabino 0:c76361bd82e8 673 */
dgabino 0:c76361bd82e8 674 R call(A0 a0) {
dgabino 0:c76361bd82e8 675 if (!_thunk) {
dgabino 0:c76361bd82e8 676 return (R)0;
dgabino 0:c76361bd82e8 677 }
dgabino 0:c76361bd82e8 678 return _thunk(_obj, &_func, a0);
dgabino 0:c76361bd82e8 679 }
dgabino 0:c76361bd82e8 680
dgabino 0:c76361bd82e8 681 /** Call the attached function
dgabino 0:c76361bd82e8 682 */
dgabino 0:c76361bd82e8 683 R operator()(A0 a0) {
dgabino 0:c76361bd82e8 684 return call(a0);
dgabino 0:c76361bd82e8 685 }
dgabino 0:c76361bd82e8 686
dgabino 0:c76361bd82e8 687 /** Test if function has been attached
dgabino 0:c76361bd82e8 688 */
dgabino 0:c76361bd82e8 689 operator bool() const {
dgabino 0:c76361bd82e8 690 return _thunk;
dgabino 0:c76361bd82e8 691 }
dgabino 0:c76361bd82e8 692
dgabino 0:c76361bd82e8 693 /** Static thunk for passing as C-style function
dgabino 0:c76361bd82e8 694 * @param func Callback to call passed as void pointer
dgabino 0:c76361bd82e8 695 */
dgabino 0:c76361bd82e8 696 static R thunk(void *func, A0 a0) {
dgabino 0:c76361bd82e8 697 return static_cast<Callback<R(A0)>*>(func)
dgabino 0:c76361bd82e8 698 ->call(a0);
dgabino 0:c76361bd82e8 699 }
dgabino 0:c76361bd82e8 700
dgabino 0:c76361bd82e8 701 private:
dgabino 0:c76361bd82e8 702 // Internal thunks for various function types
dgabino 0:c76361bd82e8 703 static R _staticthunk(void*, void *func, A0 a0) {
dgabino 0:c76361bd82e8 704 return (*reinterpret_cast<R (**)(A0)>(func))
dgabino 0:c76361bd82e8 705 (a0);
dgabino 0:c76361bd82e8 706 }
dgabino 0:c76361bd82e8 707
dgabino 0:c76361bd82e8 708 template<typename T>
dgabino 0:c76361bd82e8 709 static R _boundthunk(void *obj, void *func, A0 a0) {
dgabino 0:c76361bd82e8 710 return (*reinterpret_cast<R (**)(T*, A0)>(func))
dgabino 0:c76361bd82e8 711 (static_cast<T*>(obj), a0);
dgabino 0:c76361bd82e8 712 }
dgabino 0:c76361bd82e8 713
dgabino 0:c76361bd82e8 714 template<typename T>
dgabino 0:c76361bd82e8 715 static R _methodthunk(void *obj, void *func, A0 a0) {
dgabino 0:c76361bd82e8 716 return (static_cast<T*>(obj)->*
dgabino 0:c76361bd82e8 717 (*reinterpret_cast<R (T::**)(A0)>(func)))
dgabino 0:c76361bd82e8 718 (a0);
dgabino 0:c76361bd82e8 719 }
dgabino 0:c76361bd82e8 720
dgabino 0:c76361bd82e8 721 // Stored as pointer to function and pointer to optional object
dgabino 0:c76361bd82e8 722 // Function pointer is stored as union of possible function types
dgabino 0:c76361bd82e8 723 // to garuntee proper size and alignment
dgabino 0:c76361bd82e8 724 struct _class;
dgabino 0:c76361bd82e8 725 union {
dgabino 0:c76361bd82e8 726 void (*_staticfunc)();
dgabino 0:c76361bd82e8 727 void (*_boundfunc)(_class *);
dgabino 0:c76361bd82e8 728 void (_class::*_methodfunc)();
dgabino 0:c76361bd82e8 729 } _func;
dgabino 0:c76361bd82e8 730
dgabino 0:c76361bd82e8 731 void *_obj;
dgabino 0:c76361bd82e8 732
dgabino 0:c76361bd82e8 733 // Thunk registered on attach to dispatch calls
dgabino 0:c76361bd82e8 734 R (*_thunk)(void*, void*, A0);
dgabino 0:c76361bd82e8 735 };
dgabino 0:c76361bd82e8 736
dgabino 0:c76361bd82e8 737 /** Templated function class
dgabino 0:c76361bd82e8 738 */
dgabino 0:c76361bd82e8 739 template <typename R>
dgabino 0:c76361bd82e8 740 class Callback<R()> {
dgabino 0:c76361bd82e8 741 public:
dgabino 0:c76361bd82e8 742 /** Create a Callback with a static function
dgabino 0:c76361bd82e8 743 * @param func Static function to attach
dgabino 0:c76361bd82e8 744 */
dgabino 0:c76361bd82e8 745 Callback(R (*func)() = 0) {
dgabino 0:c76361bd82e8 746 attach(func);
dgabino 0:c76361bd82e8 747 }
dgabino 0:c76361bd82e8 748
dgabino 0:c76361bd82e8 749 /** Create a Callback with a static function and bound pointer
dgabino 0:c76361bd82e8 750 * @param obj Pointer to object to bind to function
dgabino 0:c76361bd82e8 751 * @param func Static function to attach
dgabino 0:c76361bd82e8 752 */
dgabino 0:c76361bd82e8 753 template<typename T>
dgabino 0:c76361bd82e8 754 Callback(T *obj, R (*func)(T*)) {
dgabino 0:c76361bd82e8 755 attach(obj, func);
dgabino 0:c76361bd82e8 756 }
dgabino 0:c76361bd82e8 757
dgabino 0:c76361bd82e8 758 /** Create a Callback with a member function
dgabino 0:c76361bd82e8 759 * @param obj Pointer to object to invoke member function on
dgabino 0:c76361bd82e8 760 * @param func Member function to attach
dgabino 0:c76361bd82e8 761 */
dgabino 0:c76361bd82e8 762 template<typename T>
dgabino 0:c76361bd82e8 763 Callback(T *obj, R (T::*func)()) {
dgabino 0:c76361bd82e8 764 attach(obj, func);
dgabino 0:c76361bd82e8 765 }
dgabino 0:c76361bd82e8 766
dgabino 0:c76361bd82e8 767 /** Create a Callback with another Callback
dgabino 0:c76361bd82e8 768 * @param func Callback to attach
dgabino 0:c76361bd82e8 769 */
dgabino 0:c76361bd82e8 770 Callback(const Callback<R()> &func) {
dgabino 0:c76361bd82e8 771 attach(func);
dgabino 0:c76361bd82e8 772 }
dgabino 0:c76361bd82e8 773
dgabino 0:c76361bd82e8 774 /** Attach a static function
dgabino 0:c76361bd82e8 775 * @param func Static function to attach
dgabino 0:c76361bd82e8 776 */
dgabino 0:c76361bd82e8 777 void attach(R (*func)()) {
dgabino 0:c76361bd82e8 778 memcpy(&_func, &func, sizeof func);
dgabino 0:c76361bd82e8 779 _thunk = func ? &Callback::_staticthunk : 0;
dgabino 0:c76361bd82e8 780 }
dgabino 0:c76361bd82e8 781
dgabino 0:c76361bd82e8 782 /** Attach a static function with a bound pointer
dgabino 0:c76361bd82e8 783 * @param obj Pointer to object to bind to function
dgabino 0:c76361bd82e8 784 * @param func Static function to attach
dgabino 0:c76361bd82e8 785 */
dgabino 0:c76361bd82e8 786 template <typename T>
dgabino 0:c76361bd82e8 787 void attach(T *obj, R (*func)(T*)) {
dgabino 0:c76361bd82e8 788 _obj = (void*)obj;
dgabino 0:c76361bd82e8 789 memcpy(&_func, &func, sizeof func);
dgabino 0:c76361bd82e8 790 _thunk = &Callback::_boundthunk<T>;
dgabino 0:c76361bd82e8 791 }
dgabino 0:c76361bd82e8 792
dgabino 0:c76361bd82e8 793 /** Attach a member function
dgabino 0:c76361bd82e8 794 * @param obj Pointer to object to invoke member function on
dgabino 0:c76361bd82e8 795 * @param func Member function to attach
dgabino 0:c76361bd82e8 796 */
dgabino 0:c76361bd82e8 797 template<typename T>
dgabino 0:c76361bd82e8 798 void attach(T *obj, R (T::*func)()) {
dgabino 0:c76361bd82e8 799 _obj = static_cast<void*>(obj);
dgabino 0:c76361bd82e8 800 memcpy(&_func, &func, sizeof func);
dgabino 0:c76361bd82e8 801 _thunk = &Callback::_methodthunk<T>;
dgabino 0:c76361bd82e8 802 }
dgabino 0:c76361bd82e8 803
dgabino 0:c76361bd82e8 804 /** Attach a Callback
dgabino 0:c76361bd82e8 805 * @param func The Callback to attach
dgabino 0:c76361bd82e8 806 */
dgabino 0:c76361bd82e8 807 void attach(const Callback<R()> &func) {
dgabino 0:c76361bd82e8 808 _obj = func._obj;
dgabino 0:c76361bd82e8 809 memcpy(&_func, &func._func, sizeof _func);
dgabino 0:c76361bd82e8 810 _thunk = func._thunk;
dgabino 0:c76361bd82e8 811 }
dgabino 0:c76361bd82e8 812
dgabino 0:c76361bd82e8 813 /** Call the attached function
dgabino 0:c76361bd82e8 814 */
dgabino 0:c76361bd82e8 815 R call() {
dgabino 0:c76361bd82e8 816 if (!_thunk) {
dgabino 0:c76361bd82e8 817 return (R)0;
dgabino 0:c76361bd82e8 818 }
dgabino 0:c76361bd82e8 819 return _thunk(_obj, &_func);
dgabino 0:c76361bd82e8 820 }
dgabino 0:c76361bd82e8 821
dgabino 0:c76361bd82e8 822 /** Call the attached function
dgabino 0:c76361bd82e8 823 */
dgabino 0:c76361bd82e8 824 R operator()() {
dgabino 0:c76361bd82e8 825 return call();
dgabino 0:c76361bd82e8 826 }
dgabino 0:c76361bd82e8 827
dgabino 0:c76361bd82e8 828 /** Test if function has been attached
dgabino 0:c76361bd82e8 829 */
dgabino 0:c76361bd82e8 830 operator bool() const {
dgabino 0:c76361bd82e8 831 return _thunk;
dgabino 0:c76361bd82e8 832 }
dgabino 0:c76361bd82e8 833
dgabino 0:c76361bd82e8 834 /** Static thunk for passing as C-style function
dgabino 0:c76361bd82e8 835 * @param func Callback to call passed as void pointer
dgabino 0:c76361bd82e8 836 */
dgabino 0:c76361bd82e8 837 static R thunk(void *func) {
dgabino 0:c76361bd82e8 838 return static_cast<Callback<R()>*>(func)
dgabino 0:c76361bd82e8 839 ->call();
dgabino 0:c76361bd82e8 840 }
dgabino 0:c76361bd82e8 841
dgabino 0:c76361bd82e8 842 private:
dgabino 0:c76361bd82e8 843 // Internal thunks for various function types
dgabino 0:c76361bd82e8 844 static R _staticthunk(void*, void *func) {
dgabino 0:c76361bd82e8 845 return (*reinterpret_cast<R (**)()>(func))
dgabino 0:c76361bd82e8 846 ();
dgabino 0:c76361bd82e8 847 }
dgabino 0:c76361bd82e8 848
dgabino 0:c76361bd82e8 849 template<typename T>
dgabino 0:c76361bd82e8 850 static R _boundthunk(void *obj, void *func) {
dgabino 0:c76361bd82e8 851 return (*reinterpret_cast<R (**)(T*)>(func))
dgabino 0:c76361bd82e8 852 (static_cast<T*>(obj));
dgabino 0:c76361bd82e8 853 }
dgabino 0:c76361bd82e8 854
dgabino 0:c76361bd82e8 855 template<typename T>
dgabino 0:c76361bd82e8 856 static R _methodthunk(void *obj, void *func) {
dgabino 0:c76361bd82e8 857 return (static_cast<T*>(obj)->*
dgabino 0:c76361bd82e8 858 (*reinterpret_cast<R (T::**)()>(func)))
dgabino 0:c76361bd82e8 859 ();
dgabino 0:c76361bd82e8 860 }
dgabino 0:c76361bd82e8 861
dgabino 0:c76361bd82e8 862 // Stored as pointer to function and pointer to optional object
dgabino 0:c76361bd82e8 863 // Function pointer is stored as union of possible function types
dgabino 0:c76361bd82e8 864 // to garuntee proper size and alignment
dgabino 0:c76361bd82e8 865 struct _class;
dgabino 0:c76361bd82e8 866 union {
dgabino 0:c76361bd82e8 867 void (*_staticfunc)();
dgabino 0:c76361bd82e8 868 void (*_boundfunc)(_class *);
dgabino 0:c76361bd82e8 869 void (_class::*_methodfunc)();
dgabino 0:c76361bd82e8 870 } _func;
dgabino 0:c76361bd82e8 871
dgabino 0:c76361bd82e8 872 void *_obj;
dgabino 0:c76361bd82e8 873
dgabino 0:c76361bd82e8 874 // Thunk registered on attach to dispatch calls
dgabino 0:c76361bd82e8 875 R (*_thunk)(void*, void*);
dgabino 0:c76361bd82e8 876 };
dgabino 0:c76361bd82e8 877
dgabino 0:c76361bd82e8 878 typedef Callback<void(int)> event_callback_t;
dgabino 0:c76361bd82e8 879
dgabino 0:c76361bd82e8 880
dgabino 0:c76361bd82e8 881 } // namespace mbed
dgabino 0:c76361bd82e8 882
dgabino 0:c76361bd82e8 883 #endif