mbed library for slider v2

Dependents:   kl46z_slider_v2

Committer:
mturner5
Date:
Wed Sep 14 07:04:27 2016 +0000
Revision:
0:b7116bd48af6
Tried to use the timer.

Who changed what in which revision?

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