This fork captures the mbed lib v125 for ease of integration into older projects.

Fork of mbed-dev by mbed official

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Callback.h Source File

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