Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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 22:19:20 by
