a

Dependencies:   4DGL-uLCD-SE LSM9DS1_Library_cal SDFileSystem mbed-rtos mbed wave_player

Committer:
rmaran6
Date:
Wed Nov 02 02:02:03 2016 +0000
Revision:
0:2b0c527942db
a

Who changed what in which revision?

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