mbed library sources. Supersedes mbed-src.
Dependents: LPCXpresso1769_blinky
Fork of mbed-dev by
Callback.h
00001 /* mbed Microcontroller Library 00002 * Copyright (c) 2006-2015 ARM Limited 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 #ifndef MBED_CALLBACK_H 00017 #define MBED_CALLBACK_H 00018 00019 #include <string.h> 00020 #include <stdint.h> 00021 00022 namespace mbed { 00023 00024 00025 /** Callback class based on template specialization 00026 * 00027 * @Note Synchronization level: Not protected 00028 */ 00029 template <typename F> 00030 class Callback; 00031 00032 /** Templated function class 00033 */ 00034 template <typename R, typename A0, typename A1, typename A2, typename A3, typename A4> 00035 class Callback<R(A0, A1, A2, A3, A4)> { 00036 public: 00037 /** Create a Callback with a static function 00038 * @param func Static function to attach 00039 */ 00040 Callback(R (*func)(A0, A1, A2, A3, A4) = 0) { 00041 attach(func); 00042 } 00043 00044 /** Create a Callback with a static function and bound pointer 00045 * @param obj Pointer to object to bind to function 00046 * @param func Static function to attach 00047 */ 00048 template<typename T> 00049 Callback(T *obj, R (*func)(T*, A0, A1, A2, A3, A4)) { 00050 attach(obj, func); 00051 } 00052 00053 /** Create a Callback with a member function 00054 * @param obj Pointer to object to invoke member function on 00055 * @param func Member function to attach 00056 */ 00057 template<typename T> 00058 Callback(T *obj, R (T::*func)(A0, A1, A2, A3, A4)) { 00059 attach(obj, func); 00060 } 00061 00062 /** Create a Callback with another Callback 00063 * @param func Callback to attach 00064 */ 00065 Callback(const Callback<R(A0, A1, A2, A3, A4)> &func) { 00066 attach(func); 00067 } 00068 00069 /** Attach a static function 00070 * @param func Static function to attach 00071 */ 00072 void attach(R (*func)(A0, A1, A2, A3, A4)) { 00073 memcpy(&_func, &func, sizeof func); 00074 _thunk = func ? &Callback::_staticthunk : 0; 00075 } 00076 00077 /** Attach a static function with a bound pointer 00078 * @param obj Pointer to object to bind to function 00079 * @param func Static function to attach 00080 */ 00081 template <typename T> 00082 void attach(T *obj, R (*func)(T*, A0, A1, A2, A3, A4)) { 00083 _obj = (void*)obj; 00084 memcpy(&_func, &func, sizeof func); 00085 _thunk = &Callback::_boundthunk<T>; 00086 } 00087 00088 /** Attach a member function 00089 * @param obj Pointer to object to invoke member function on 00090 * @param func Member function to attach 00091 */ 00092 template<typename T> 00093 void attach(T *obj, R (T::*func)(A0, A1, A2, A3, A4)) { 00094 _obj = static_cast<void*>(obj); 00095 memcpy(&_func, &func, sizeof func); 00096 _thunk = &Callback::_methodthunk<T>; 00097 } 00098 00099 /** Attach a Callback 00100 * @param func The Callback to attach 00101 */ 00102 void attach(const Callback<R(A0, A1, A2, A3, A4)> &func) { 00103 _obj = func._obj; 00104 memcpy(&_func, &func._func, sizeof _func); 00105 _thunk = func._thunk; 00106 } 00107 00108 /** Call the attached function 00109 */ 00110 R call(A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) { 00111 if (!_thunk) { 00112 return (R)0; 00113 } 00114 return _thunk(_obj, &_func, a0, a1, a2, a3, a4); 00115 } 00116 00117 /** Call the attached function 00118 */ 00119 R operator()(A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) { 00120 return call(a0, a1, a2, a3, a4); 00121 } 00122 00123 /** Test if function has been attached 00124 */ 00125 operator bool() const { 00126 return _thunk; 00127 } 00128 00129 /** Static thunk for passing as C-style function 00130 * @param func Callback to call passed as void pointer 00131 */ 00132 static R thunk(void *func, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) { 00133 return static_cast<Callback<R(A0, A1, A2, A3, A4)>*>(func) 00134 ->call(a0, a1, a2, a3, a4); 00135 } 00136 00137 private: 00138 // Internal thunks for various function types 00139 static R _staticthunk(void*, void *func, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) { 00140 return (*reinterpret_cast<R (**)(A0, A1, A2, A3, A4)>(func)) 00141 (a0, a1, a2, a3, a4); 00142 } 00143 00144 template<typename T> 00145 static R _boundthunk(void *obj, void *func, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) { 00146 return (*reinterpret_cast<R (**)(T*, A0, A1, A2, A3, A4)>(func)) 00147 (static_cast<T*>(obj), a0, a1, a2, a3, a4); 00148 } 00149 00150 template<typename T> 00151 static R _methodthunk(void *obj, void *func, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) { 00152 return (static_cast<T*>(obj)->* 00153 (*reinterpret_cast<R (T::**)(A0, A1, A2, A3, A4)>(func))) 00154 (a0, a1, a2, a3, a4); 00155 } 00156 00157 // Stored as pointer to function and pointer to optional object 00158 // Function pointer is stored as union of possible function types 00159 // to garuntee proper size and alignment 00160 struct _class; 00161 union { 00162 void (*_staticfunc)(); 00163 void (*_boundfunc)(_class *); 00164 void (_class::*_methodfunc)(); 00165 } _func; 00166 00167 void *_obj; 00168 00169 // Thunk registered on attach to dispatch calls 00170 R (*_thunk)(void*, void*, A0, A1, A2, A3, A4); 00171 }; 00172 00173 /** Templated function class 00174 */ 00175 template <typename R, typename A0, typename A1, typename A2, typename A3> 00176 class Callback<R(A0, A1, A2, A3)> { 00177 public: 00178 /** Create a Callback with a static function 00179 * @param func Static function to attach 00180 */ 00181 Callback(R (*func)(A0, A1, A2, A3) = 0) { 00182 attach(func); 00183 } 00184 00185 /** Create a Callback with a static function and bound pointer 00186 * @param obj Pointer to object to bind to function 00187 * @param func Static function to attach 00188 */ 00189 template<typename T> 00190 Callback(T *obj, R (*func)(T*, A0, A1, A2, A3)) { 00191 attach(obj, func); 00192 } 00193 00194 /** Create a Callback with a member function 00195 * @param obj Pointer to object to invoke member function on 00196 * @param func Member function to attach 00197 */ 00198 template<typename T> 00199 Callback(T *obj, R (T::*func)(A0, A1, A2, A3)) { 00200 attach(obj, func); 00201 } 00202 00203 /** Create a Callback with another Callback 00204 * @param func Callback to attach 00205 */ 00206 Callback(const Callback<R(A0, A1, A2, A3)> &func) { 00207 attach(func); 00208 } 00209 00210 /** Attach a static function 00211 * @param func Static function to attach 00212 */ 00213 void attach(R (*func)(A0, A1, A2, A3)) { 00214 memcpy(&_func, &func, sizeof func); 00215 _thunk = func ? &Callback::_staticthunk : 0; 00216 } 00217 00218 /** Attach a static function with a bound pointer 00219 * @param obj Pointer to object to bind to function 00220 * @param func Static function to attach 00221 */ 00222 template <typename T> 00223 void attach(T *obj, R (*func)(T*, A0, A1, A2, A3)) { 00224 _obj = (void*)obj; 00225 memcpy(&_func, &func, sizeof func); 00226 _thunk = &Callback::_boundthunk<T>; 00227 } 00228 00229 /** Attach a member function 00230 * @param obj Pointer to object to invoke member function on 00231 * @param func Member function to attach 00232 */ 00233 template<typename T> 00234 void attach(T *obj, R (T::*func)(A0, A1, A2, A3)) { 00235 _obj = static_cast<void*>(obj); 00236 memcpy(&_func, &func, sizeof func); 00237 _thunk = &Callback::_methodthunk<T>; 00238 } 00239 00240 /** Attach a Callback 00241 * @param func The Callback to attach 00242 */ 00243 void attach(const Callback<R(A0, A1, A2, A3)> &func) { 00244 _obj = func._obj; 00245 memcpy(&_func, &func._func, sizeof _func); 00246 _thunk = func._thunk; 00247 } 00248 00249 /** Call the attached function 00250 */ 00251 R call(A0 a0, A1 a1, A2 a2, A3 a3) { 00252 if (!_thunk) { 00253 return (R)0; 00254 } 00255 return _thunk(_obj, &_func, a0, a1, a2, a3); 00256 } 00257 00258 /** Call the attached function 00259 */ 00260 R operator()(A0 a0, A1 a1, A2 a2, A3 a3) { 00261 return call(a0, a1, a2, a3); 00262 } 00263 00264 /** Test if function has been attached 00265 */ 00266 operator bool() const { 00267 return _thunk; 00268 } 00269 00270 /** Static thunk for passing as C-style function 00271 * @param func Callback to call passed as void pointer 00272 */ 00273 static R thunk(void *func, A0 a0, A1 a1, A2 a2, A3 a3) { 00274 return static_cast<Callback<R(A0, A1, A2, A3)>*>(func) 00275 ->call(a0, a1, a2, a3); 00276 } 00277 00278 private: 00279 // Internal thunks for various function types 00280 static R _staticthunk(void*, void *func, A0 a0, A1 a1, A2 a2, A3 a3) { 00281 return (*reinterpret_cast<R (**)(A0, A1, A2, A3)>(func)) 00282 (a0, a1, a2, a3); 00283 } 00284 00285 template<typename T> 00286 static R _boundthunk(void *obj, void *func, A0 a0, A1 a1, A2 a2, A3 a3) { 00287 return (*reinterpret_cast<R (**)(T*, A0, A1, A2, A3)>(func)) 00288 (static_cast<T*>(obj), a0, a1, a2, a3); 00289 } 00290 00291 template<typename T> 00292 static R _methodthunk(void *obj, void *func, A0 a0, A1 a1, A2 a2, A3 a3) { 00293 return (static_cast<T*>(obj)->* 00294 (*reinterpret_cast<R (T::**)(A0, A1, A2, A3)>(func))) 00295 (a0, a1, a2, a3); 00296 } 00297 00298 // Stored as pointer to function and pointer to optional object 00299 // Function pointer is stored as union of possible function types 00300 // to garuntee proper size and alignment 00301 struct _class; 00302 union { 00303 void (*_staticfunc)(); 00304 void (*_boundfunc)(_class *); 00305 void (_class::*_methodfunc)(); 00306 } _func; 00307 00308 void *_obj; 00309 00310 // Thunk registered on attach to dispatch calls 00311 R (*_thunk)(void*, void*, A0, A1, A2, A3); 00312 }; 00313 00314 /** Templated function class 00315 */ 00316 template <typename R, typename A0, typename A1, typename A2> 00317 class Callback<R(A0, A1, A2)> { 00318 public: 00319 /** Create a Callback with a static function 00320 * @param func Static function to attach 00321 */ 00322 Callback(R (*func)(A0, A1, A2) = 0) { 00323 attach(func); 00324 } 00325 00326 /** Create a Callback with a static function and bound pointer 00327 * @param obj Pointer to object to bind to function 00328 * @param func Static function to attach 00329 */ 00330 template<typename T> 00331 Callback(T *obj, R (*func)(T*, A0, A1, A2)) { 00332 attach(obj, func); 00333 } 00334 00335 /** Create a Callback with a member function 00336 * @param obj Pointer to object to invoke member function on 00337 * @param func Member function to attach 00338 */ 00339 template<typename T> 00340 Callback(T *obj, R (T::*func)(A0, A1, A2)) { 00341 attach(obj, func); 00342 } 00343 00344 /** Create a Callback with another Callback 00345 * @param func Callback to attach 00346 */ 00347 Callback(const Callback<R(A0, A1, A2)> &func) { 00348 attach(func); 00349 } 00350 00351 /** Attach a static function 00352 * @param func Static function to attach 00353 */ 00354 void attach(R (*func)(A0, A1, A2)) { 00355 memcpy(&_func, &func, sizeof func); 00356 _thunk = func ? &Callback::_staticthunk : 0; 00357 } 00358 00359 /** Attach a static function with a bound pointer 00360 * @param obj Pointer to object to bind to function 00361 * @param func Static function to attach 00362 */ 00363 template <typename T> 00364 void attach(T *obj, R (*func)(T*, A0, A1, A2)) { 00365 _obj = (void*)obj; 00366 memcpy(&_func, &func, sizeof func); 00367 _thunk = &Callback::_boundthunk<T>; 00368 } 00369 00370 /** Attach a member function 00371 * @param obj Pointer to object to invoke member function on 00372 * @param func Member function to attach 00373 */ 00374 template<typename T> 00375 void attach(T *obj, R (T::*func)(A0, A1, A2)) { 00376 _obj = static_cast<void*>(obj); 00377 memcpy(&_func, &func, sizeof func); 00378 _thunk = &Callback::_methodthunk<T>; 00379 } 00380 00381 /** Attach a Callback 00382 * @param func The Callback to attach 00383 */ 00384 void attach(const Callback<R(A0, A1, A2)> &func) { 00385 _obj = func._obj; 00386 memcpy(&_func, &func._func, sizeof _func); 00387 _thunk = func._thunk; 00388 } 00389 00390 /** Call the attached function 00391 */ 00392 R call(A0 a0, A1 a1, A2 a2) { 00393 if (!_thunk) { 00394 return (R)0; 00395 } 00396 return _thunk(_obj, &_func, a0, a1, a2); 00397 } 00398 00399 /** Call the attached function 00400 */ 00401 R operator()(A0 a0, A1 a1, A2 a2) { 00402 return call(a0, a1, a2); 00403 } 00404 00405 /** Test if function has been attached 00406 */ 00407 operator bool() const { 00408 return _thunk; 00409 } 00410 00411 /** Static thunk for passing as C-style function 00412 * @param func Callback to call passed as void pointer 00413 */ 00414 static R thunk(void *func, A0 a0, A1 a1, A2 a2) { 00415 return static_cast<Callback<R(A0, A1, A2)>*>(func) 00416 ->call(a0, a1, a2); 00417 } 00418 00419 private: 00420 // Internal thunks for various function types 00421 static R _staticthunk(void*, void *func, A0 a0, A1 a1, A2 a2) { 00422 return (*reinterpret_cast<R (**)(A0, A1, A2)>(func)) 00423 (a0, a1, a2); 00424 } 00425 00426 template<typename T> 00427 static R _boundthunk(void *obj, void *func, A0 a0, A1 a1, A2 a2) { 00428 return (*reinterpret_cast<R (**)(T*, A0, A1, A2)>(func)) 00429 (static_cast<T*>(obj), a0, a1, a2); 00430 } 00431 00432 template<typename T> 00433 static R _methodthunk(void *obj, void *func, A0 a0, A1 a1, A2 a2) { 00434 return (static_cast<T*>(obj)->* 00435 (*reinterpret_cast<R (T::**)(A0, A1, A2)>(func))) 00436 (a0, a1, a2); 00437 } 00438 00439 // Stored as pointer to function and pointer to optional object 00440 // Function pointer is stored as union of possible function types 00441 // to garuntee proper size and alignment 00442 struct _class; 00443 union { 00444 void (*_staticfunc)(); 00445 void (*_boundfunc)(_class *); 00446 void (_class::*_methodfunc)(); 00447 } _func; 00448 00449 void *_obj; 00450 00451 // Thunk registered on attach to dispatch calls 00452 R (*_thunk)(void*, void*, A0, A1, A2); 00453 }; 00454 00455 /** Templated function class 00456 */ 00457 template <typename R, typename A0, typename A1> 00458 class Callback<R(A0, A1)> { 00459 public: 00460 /** Create a Callback with a static function 00461 * @param func Static function to attach 00462 */ 00463 Callback(R (*func)(A0, A1) = 0) { 00464 attach(func); 00465 } 00466 00467 /** Create a Callback with a static function and bound pointer 00468 * @param obj Pointer to object to bind to function 00469 * @param func Static function to attach 00470 */ 00471 template<typename T> 00472 Callback(T *obj, R (*func)(T*, A0, A1)) { 00473 attach(obj, func); 00474 } 00475 00476 /** Create a Callback with a member function 00477 * @param obj Pointer to object to invoke member function on 00478 * @param func Member function to attach 00479 */ 00480 template<typename T> 00481 Callback(T *obj, R (T::*func)(A0, A1)) { 00482 attach(obj, func); 00483 } 00484 00485 /** Create a Callback with another Callback 00486 * @param func Callback to attach 00487 */ 00488 Callback(const Callback<R(A0, A1)> &func) { 00489 attach(func); 00490 } 00491 00492 /** Attach a static function 00493 * @param func Static function to attach 00494 */ 00495 void attach(R (*func)(A0, A1)) { 00496 memcpy(&_func, &func, sizeof func); 00497 _thunk = func ? &Callback::_staticthunk : 0; 00498 } 00499 00500 /** Attach a static function with a bound pointer 00501 * @param obj Pointer to object to bind to function 00502 * @param func Static function to attach 00503 */ 00504 template <typename T> 00505 void attach(T *obj, R (*func)(T*, A0, A1)) { 00506 _obj = (void*)obj; 00507 memcpy(&_func, &func, sizeof func); 00508 _thunk = &Callback::_boundthunk<T>; 00509 } 00510 00511 /** Attach a member function 00512 * @param obj Pointer to object to invoke member function on 00513 * @param func Member function to attach 00514 */ 00515 template<typename T> 00516 void attach(T *obj, R (T::*func)(A0, A1)) { 00517 _obj = static_cast<void*>(obj); 00518 memcpy(&_func, &func, sizeof func); 00519 _thunk = &Callback::_methodthunk<T>; 00520 } 00521 00522 /** Attach a Callback 00523 * @param func The Callback to attach 00524 */ 00525 void attach(const Callback<R(A0, A1)> &func) { 00526 _obj = func._obj; 00527 memcpy(&_func, &func._func, sizeof _func); 00528 _thunk = func._thunk; 00529 } 00530 00531 /** Call the attached function 00532 */ 00533 R call(A0 a0, A1 a1) { 00534 if (!_thunk) { 00535 return (R)0; 00536 } 00537 return _thunk(_obj, &_func, a0, a1); 00538 } 00539 00540 /** Call the attached function 00541 */ 00542 R operator()(A0 a0, A1 a1) { 00543 return call(a0, a1); 00544 } 00545 00546 /** Test if function has been attached 00547 */ 00548 operator bool() const { 00549 return _thunk; 00550 } 00551 00552 /** Static thunk for passing as C-style function 00553 * @param func Callback to call passed as void pointer 00554 */ 00555 static R thunk(void *func, A0 a0, A1 a1) { 00556 return static_cast<Callback<R(A0, A1)>*>(func) 00557 ->call(a0, a1); 00558 } 00559 00560 private: 00561 // Internal thunks for various function types 00562 static R _staticthunk(void*, void *func, A0 a0, A1 a1) { 00563 return (*reinterpret_cast<R (**)(A0, A1)>(func)) 00564 (a0, a1); 00565 } 00566 00567 template<typename T> 00568 static R _boundthunk(void *obj, void *func, A0 a0, A1 a1) { 00569 return (*reinterpret_cast<R (**)(T*, A0, A1)>(func)) 00570 (static_cast<T*>(obj), a0, a1); 00571 } 00572 00573 template<typename T> 00574 static R _methodthunk(void *obj, void *func, A0 a0, A1 a1) { 00575 return (static_cast<T*>(obj)->* 00576 (*reinterpret_cast<R (T::**)(A0, A1)>(func))) 00577 (a0, a1); 00578 } 00579 00580 // Stored as pointer to function and pointer to optional object 00581 // Function pointer is stored as union of possible function types 00582 // to garuntee proper size and alignment 00583 struct _class; 00584 union { 00585 void (*_staticfunc)(); 00586 void (*_boundfunc)(_class *); 00587 void (_class::*_methodfunc)(); 00588 } _func; 00589 00590 void *_obj; 00591 00592 // Thunk registered on attach to dispatch calls 00593 R (*_thunk)(void*, void*, A0, A1); 00594 }; 00595 00596 /** Templated function class 00597 */ 00598 template <typename R, typename A0> 00599 class Callback<R(A0)> { 00600 public: 00601 /** Create a Callback with a static function 00602 * @param func Static function to attach 00603 */ 00604 Callback(R (*func)(A0) = 0) { 00605 attach(func); 00606 } 00607 00608 /** Create a Callback with a static function and bound pointer 00609 * @param obj Pointer to object to bind to function 00610 * @param func Static function to attach 00611 */ 00612 template<typename T> 00613 Callback(T *obj, R (*func)(T*, A0)) { 00614 attach(obj, func); 00615 } 00616 00617 /** Create a Callback with a member function 00618 * @param obj Pointer to object to invoke member function on 00619 * @param func Member function to attach 00620 */ 00621 template<typename T> 00622 Callback(T *obj, R (T::*func)(A0)) { 00623 attach(obj, func); 00624 } 00625 00626 /** Create a Callback with another Callback 00627 * @param func Callback to attach 00628 */ 00629 Callback(const Callback<R(A0)> &func) { 00630 attach(func); 00631 } 00632 00633 /** Attach a static function 00634 * @param func Static function to attach 00635 */ 00636 void attach(R (*func)(A0)) { 00637 memcpy(&_func, &func, sizeof func); 00638 _thunk = func ? &Callback::_staticthunk : 0; 00639 } 00640 00641 /** Attach a static function with a bound pointer 00642 * @param obj Pointer to object to bind to function 00643 * @param func Static function to attach 00644 */ 00645 template <typename T> 00646 void attach(T *obj, R (*func)(T*, A0)) { 00647 _obj = (void*)obj; 00648 memcpy(&_func, &func, sizeof func); 00649 _thunk = &Callback::_boundthunk<T>; 00650 } 00651 00652 /** Attach a member function 00653 * @param obj Pointer to object to invoke member function on 00654 * @param func Member function to attach 00655 */ 00656 template<typename T> 00657 void attach(T *obj, R (T::*func)(A0)) { 00658 _obj = static_cast<void*>(obj); 00659 memcpy(&_func, &func, sizeof func); 00660 _thunk = &Callback::_methodthunk<T>; 00661 } 00662 00663 /** Attach a Callback 00664 * @param func The Callback to attach 00665 */ 00666 void attach(const Callback<R(A0)> &func) { 00667 _obj = func._obj; 00668 memcpy(&_func, &func._func, sizeof _func); 00669 _thunk = func._thunk; 00670 } 00671 00672 /** Call the attached function 00673 */ 00674 R call(A0 a0) { 00675 if (!_thunk) { 00676 return (R)0; 00677 } 00678 return _thunk(_obj, &_func, a0); 00679 } 00680 00681 /** Call the attached function 00682 */ 00683 R operator()(A0 a0) { 00684 return call(a0); 00685 } 00686 00687 /** Test if function has been attached 00688 */ 00689 operator bool() const { 00690 return _thunk; 00691 } 00692 00693 /** Static thunk for passing as C-style function 00694 * @param func Callback to call passed as void pointer 00695 */ 00696 static R thunk(void *func, A0 a0) { 00697 return static_cast<Callback<R(A0)>*>(func) 00698 ->call(a0); 00699 } 00700 00701 private: 00702 // Internal thunks for various function types 00703 static R _staticthunk(void*, void *func, A0 a0) { 00704 return (*reinterpret_cast<R (**)(A0)>(func)) 00705 (a0); 00706 } 00707 00708 template<typename T> 00709 static R _boundthunk(void *obj, void *func, A0 a0) { 00710 return (*reinterpret_cast<R (**)(T*, A0)>(func)) 00711 (static_cast<T*>(obj), a0); 00712 } 00713 00714 template<typename T> 00715 static R _methodthunk(void *obj, void *func, A0 a0) { 00716 return (static_cast<T*>(obj)->* 00717 (*reinterpret_cast<R (T::**)(A0)>(func))) 00718 (a0); 00719 } 00720 00721 // Stored as pointer to function and pointer to optional object 00722 // Function pointer is stored as union of possible function types 00723 // to garuntee proper size and alignment 00724 struct _class; 00725 union { 00726 void (*_staticfunc)(); 00727 void (*_boundfunc)(_class *); 00728 void (_class::*_methodfunc)(); 00729 } _func; 00730 00731 void *_obj; 00732 00733 // Thunk registered on attach to dispatch calls 00734 R (*_thunk)(void*, void*, A0); 00735 }; 00736 00737 /** Templated function class 00738 */ 00739 template <typename R> 00740 class Callback<R()> { 00741 public: 00742 /** Create a Callback with a static function 00743 * @param func Static function to attach 00744 */ 00745 Callback(R (*func)() = 0) { 00746 attach(func); 00747 } 00748 00749 /** Create a Callback with a static function and bound pointer 00750 * @param obj Pointer to object to bind to function 00751 * @param func Static function to attach 00752 */ 00753 template<typename T> 00754 Callback(T *obj, R (*func)(T*)) { 00755 attach(obj, func); 00756 } 00757 00758 /** Create a Callback with a member function 00759 * @param obj Pointer to object to invoke member function on 00760 * @param func Member function to attach 00761 */ 00762 template<typename T> 00763 Callback(T *obj, R (T::*func)()) { 00764 attach(obj, func); 00765 } 00766 00767 /** Create a Callback with another Callback 00768 * @param func Callback to attach 00769 */ 00770 Callback(const Callback<R()> &func) { 00771 attach(func); 00772 } 00773 00774 /** Attach a static function 00775 * @param func Static function to attach 00776 */ 00777 void attach(R (*func)()) { 00778 memcpy(&_func, &func, sizeof func); 00779 _thunk = func ? &Callback::_staticthunk : 0; 00780 } 00781 00782 /** Attach a static function with a bound pointer 00783 * @param obj Pointer to object to bind to function 00784 * @param func Static function to attach 00785 */ 00786 template <typename T> 00787 void attach(T *obj, R (*func)(T*)) { 00788 _obj = (void*)obj; 00789 memcpy(&_func, &func, sizeof func); 00790 _thunk = &Callback::_boundthunk<T>; 00791 } 00792 00793 /** Attach a member function 00794 * @param obj Pointer to object to invoke member function on 00795 * @param func Member function to attach 00796 */ 00797 template<typename T> 00798 void attach(T *obj, R (T::*func)()) { 00799 _obj = static_cast<void*>(obj); 00800 memcpy(&_func, &func, sizeof func); 00801 _thunk = &Callback::_methodthunk<T>; 00802 } 00803 00804 /** Attach a Callback 00805 * @param func The Callback to attach 00806 */ 00807 void attach(const Callback<R()> &func) { 00808 _obj = func._obj; 00809 memcpy(&_func, &func._func, sizeof _func); 00810 _thunk = func._thunk; 00811 } 00812 00813 /** Call the attached function 00814 */ 00815 R call() { 00816 if (!_thunk) { 00817 return (R)0; 00818 } 00819 return _thunk(_obj, &_func); 00820 } 00821 00822 /** Call the attached function 00823 */ 00824 R operator()() { 00825 return call(); 00826 } 00827 00828 /** Test if function has been attached 00829 */ 00830 operator bool() const { 00831 return _thunk; 00832 } 00833 00834 /** Static thunk for passing as C-style function 00835 * @param func Callback to call passed as void pointer 00836 */ 00837 static R thunk(void *func) { 00838 return static_cast<Callback<R()>*>(func) 00839 ->call(); 00840 } 00841 00842 private: 00843 // Internal thunks for various function types 00844 static R _staticthunk(void*, void *func) { 00845 return (*reinterpret_cast<R (**)()>(func)) 00846 (); 00847 } 00848 00849 template<typename T> 00850 static R _boundthunk(void *obj, void *func) { 00851 return (*reinterpret_cast<R (**)(T*)>(func)) 00852 (static_cast<T*>(obj)); 00853 } 00854 00855 template<typename T> 00856 static R _methodthunk(void *obj, void *func) { 00857 return (static_cast<T*>(obj)->* 00858 (*reinterpret_cast<R (T::**)()>(func))) 00859 (); 00860 } 00861 00862 // Stored as pointer to function and pointer to optional object 00863 // Function pointer is stored as union of possible function types 00864 // to garuntee proper size and alignment 00865 struct _class; 00866 union { 00867 void (*_staticfunc)(); 00868 void (*_boundfunc)(_class *); 00869 void (_class::*_methodfunc)(); 00870 } _func; 00871 00872 void *_obj; 00873 00874 // Thunk registered on attach to dispatch calls 00875 R (*_thunk)(void*, void*); 00876 }; 00877 00878 typedef Callback<void(int)> event_callback_t; 00879 00880 00881 } // namespace mbed 00882 00883 #endif
Generated on Tue Jul 12 2022 16:04:25 by 1.7.2