Morpheus / mbed-hal

Dependencies:   target-freescale

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers FunctionPointer.h Source File

FunctionPointer.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_FUNCTIONPOINTER_H
00017 #define MBED_FUNCTIONPOINTER_H
00018 
00019 #include <string.h>
00020 #include <stdint.h>
00021 
00022 namespace mbed {
00023 
00024 // Reusable FuncPtr class based on template specialization
00025 template <typename F>
00026 class FuncPtr;
00027 
00028 /** A class for storing and calling a pointer to a static or member function
00029  */
00030 template <typename R, typename A1, typename A2, typename A3, typename A4>
00031 class FuncPtr<R(A1, A2, A3, A4)> {
00032 public:
00033     /** Create a FuncPtr, attaching a static function
00034      *
00035      *  @param function The static function to attach (default is none)
00036      */
00037     FuncPtr(R (*function)(A1, A2, A3, A4) = 0) {
00038         attach(function);
00039     }
00040 
00041     /** Create a FuncPtr, attaching a static function with bound pointer
00042      *
00043      *  @param object Pointer to object to bind to function
00044      *  @param function The static function to attach
00045      */
00046     template<typename T>
00047     FuncPtr(T *object, R (*function)(T*, A1, A2, A3, A4)) {
00048         attach(object, function);
00049     }
00050 
00051     /** Create a FuncPtr, attaching a member function
00052      *
00053      *  @param object The object pointer to invoke the member function on (i.e. the this pointer)
00054      *  @param function The address of the member function to attach
00055      */
00056     template<typename T>
00057     FuncPtr(T *object, R (T::*member)(A1, A2, A3, A4)) {
00058         attach(object, member);
00059     }
00060 
00061     /** Create a FuncPtr, attaching a function object
00062      *
00063      *  @param object Pointer to a function object to attach
00064      */
00065     template<typename T>
00066     FuncPtr(T *object) {
00067         attach(object, &T::operator());
00068     }
00069 
00070     /** Create a FuncPtr from another FuncPtr
00071      *
00072      *  @param func The func to attach
00073      */
00074     FuncPtr(const FuncPtr<R(A1, A2, A3, A4)> &func) {
00075         attach(func);
00076     }
00077 
00078     /** Attach a static function
00079      *
00080      *  @param function The static function to attach (default is none)
00081      */
00082     void attach(R (*function)(A1, A2, A3, A4)) {
00083         _object = 0;
00084         memcpy(&_function, &function, sizeof function);
00085         _thunk = &FuncPtr::staticthunk;
00086     }
00087 
00088     /** Attach a static function with bound pointer
00089      *
00090      *  @param object Pointer to object to bind to function
00091      *  @param function The static function to attach
00092      */
00093     template <typename T>
00094     void attach(T *object, R (*function)(T*, A1, A2, A3, A4)) {
00095         _object = static_cast<void*>(object);
00096         memcpy(&_function, &function, sizeof function);
00097         _thunk = &FuncPtr::boundthunk<T>;
00098     }
00099 
00100     /** Attach a member function
00101      *
00102      *  @param object The object pointer to invoke the member function on (i.e. the this pointer)
00103      *  @param function The address of the member function to attach
00104      */
00105     template<typename T>
00106     void attach(T *object, R (T::*method)(A1, A2, A3, A4)) {
00107         _object = static_cast<void*>(object);
00108         memcpy(&_function, &method, sizeof method);
00109         _thunk = &FuncPtr::methodthunk<T>;
00110     }
00111 
00112     /** Attach a function object
00113      *
00114      *  @param object Pointer to a function object to attach
00115      */
00116     template<typename T>
00117     void attach(T *object) {
00118         attach(object, &T::operator());
00119     }
00120 
00121     /** Attach a FuncPtr
00122      *
00123      *  @param func The func to attach
00124      */
00125     void attach(const FuncPtr<R(A1, A2, A3, A4)> &func) {
00126         _object = func._object;
00127         memcpy(&_function, &func._function, sizeof _function);
00128         _thunk = func._thunk;
00129     }
00130 
00131     /** Call the attached static or member function
00132      */
00133     R call(A1 a1, A2 a2, A3 a3, A4 a4) {
00134         return _thunk(_object, _function, a1, a2, a3, a4);
00135     }
00136 
00137     /** Get registered static function
00138      */
00139     R (*get_function(A1, A2, A3, A4))() {
00140         return reinterpret_cast<R (*)(A1, A2, A3, A4)>(_object ? 0 : _function);
00141     }
00142 
00143 #ifdef MBED_OPERATORS
00144     R operator ()(A1 a1, A2 a2, A3 a3, A4 a4) {
00145         return call(a1, a2, a3, a4);
00146     }
00147     operator bool(void) const {
00148         return static_cast<bool>(_function);
00149     }
00150 #endif
00151 private:
00152     // Static thunks for various function types
00153     static R staticthunk(void*, void *func, A1 a1, A2 a2, A3 a3, A4 a4) {
00154         R (*f)(A1, A2, A3, A4) = *reinterpret_cast<R (**)(A1, A2, A3, A4)>(func);
00155         return f(a1, a2, a3, a4);
00156     }
00157 
00158     template<typename T>
00159     static R boundthunk(void *object, void *func, A1 a1, A2 a2, A3 a3, A4 a4) {
00160         T *o = static_cast<T*>(object);
00161         R (*f)(T*, A1, A2, A3, A4) = *reinterpret_cast<R (**)(T*, A1, A2, A3, A4)>(func);
00162         return f(o, a1);
00163     }
00164 
00165     template<typename T>
00166     static R methodthunk(void *object, void *member, A1 a1, A2 a2, A3 a3, A4 a4) {
00167         T* o = static_cast<T*>(object);
00168         R (T::*m)(A1, A2, A3, A4) = *reinterpret_cast<R (T::**)(A1, A2, A3, A4)>(member);
00169         return (o->*m)(a1, a2, a3, a4);
00170     }
00171 
00172     // Forward declaration of an unknown class
00173     // this kind of declaration is authorized by the standard (see 8.3.3/2 of C++ 03 standard).  
00174     // As a result, the compiler will allocate for UnknownFunctionMember_t the biggest size 
00175     // and biggest alignment possible for member function. 
00176     // This type can be used inside unions, it will help to provide the storage 
00177     // with the proper size and alignment guarantees 
00178     class UnknownClass;
00179 
00180     // object this pointer
00181     void *_object;
00182 
00183     // aligned raw member function pointer storage - converted back by registered thunk
00184     char _function[sizeof(void (UnknownClass::*)())];
00185 
00186     // registered function to convert back and call _m.member on _object
00187     R (*_thunk)(void*, void*, A1, A2, A3, A4); 
00188 };
00189 
00190 /** A class for storing and calling a pointer to a static or member function
00191  */
00192 template <typename R, typename A1, typename A2, typename A3>
00193 class FuncPtr<R(A1, A2, A3)> {
00194 public:
00195     /** Create a FuncPtr, attaching a static function
00196      *
00197      *  @param function The static function to attach (default is none)
00198      */
00199     FuncPtr(R (*function)(A1, A2, A3) = 0) {
00200         attach(function);
00201     }
00202 
00203     /** Create a FuncPtr, attaching a static function with bound pointer
00204      *
00205      *  @param object Pointer to object to bind to function
00206      *  @param function The static function to attach
00207      */
00208     template<typename T>
00209     FuncPtr(T *object, R (*function)(T*, A1, A2, A3)) {
00210         attach(object, function);
00211     }
00212 
00213     /** Create a FuncPtr, attaching a member function
00214      *
00215      *  @param object The object pointer to invoke the member function on (i.e. the this pointer)
00216      *  @param function The address of the member function to attach
00217      */
00218     template<typename T>
00219     FuncPtr(T *object, R (T::*member)(A1, A2, A3)) {
00220         attach(object, member);
00221     }
00222 
00223     /** Create a FuncPtr, attaching a function object
00224      *
00225      *  @param object Pointer to a function object to attach
00226      */
00227     template<typename T>
00228     FuncPtr(T *object) {
00229         attach(object, &T::operator());
00230     }
00231 
00232     /** Create a FuncPtr from another FuncPtr
00233      *
00234      *  @param func The func to attach
00235      */
00236     FuncPtr(const FuncPtr<R(A1, A2, A3)> &func) {
00237         attach(func);
00238     }
00239 
00240     /** Attach a static function
00241      *
00242      *  @param function The static function to attach (default is none)
00243      */
00244     void attach(R (*function)(A1, A2, A3)) {
00245         _object = 0;
00246         memcpy(&_function, &function, sizeof function);
00247         _thunk = &FuncPtr::staticthunk;
00248     }
00249 
00250     /** Attach a static function with bound pointer
00251      *
00252      *  @param object Pointer to object to bind to function
00253      *  @param function The static function to attach
00254      */
00255     template <typename T>
00256     void attach(T *object, R (*function)(T*, A1, A2, A3)) {
00257         _object = static_cast<void*>(object);
00258         memcpy(&_function, &function, sizeof function);
00259         _thunk = &FuncPtr::boundthunk<T>;
00260     }
00261 
00262     /** Attach a member function
00263      *
00264      *  @param object The object pointer to invoke the member function on (i.e. the this pointer)
00265      *  @param function The address of the member function to attach
00266      */
00267     template<typename T>
00268     void attach(T *object, R (T::*method)(A1, A2, A3)) {
00269         _object = static_cast<void*>(object);
00270         memcpy(&_function, &method, sizeof method);
00271         _thunk = &FuncPtr::methodthunk<T>;
00272     }
00273 
00274     /** Attach a function object
00275      *
00276      *  @param object Pointer to a function object to attach
00277      */
00278     template<typename T>
00279     void attach(T *object) {
00280         attach(object, &T::operator());
00281     }
00282 
00283     /** Attach a FuncPtr
00284      *
00285      *  @param func The func to attach
00286      */
00287     void attach(const FuncPtr<R(A1, A2, A3)> &func) {
00288         _object = func._object;
00289         memcpy(&_function, &func._function, sizeof _function);
00290         _thunk = func._thunk;
00291     }
00292 
00293     /** Call the attached static or member function
00294      */
00295     R call(A1 a1, A2 a2, A3 a3) {
00296         return _thunk(_object, _function, a1, a2, a3);
00297     }
00298 
00299     /** Get registered static function
00300      */
00301     R (*get_function(A1, A2, A3))() {
00302         return reinterpret_cast<R (*)(A1, A2, A3)>(_object ? 0 : _function);
00303     }
00304 
00305 #ifdef MBED_OPERATORS
00306     R operator ()(A1 a1, A2 a2, A3 a3) {
00307         return call(a1, a2, a3);
00308     }
00309     operator bool(void) const {
00310         return static_cast<bool>(_function);
00311     }
00312 #endif
00313 private:
00314     // Static thunks for various function types
00315     static R staticthunk(void*, void *func, A1 a1, A2 a2, A3 a3) {
00316         R (*f)(A1, A2, A3) = *reinterpret_cast<R (**)(A1, A2, A3)>(func);
00317         return f(a1, a2, a3);
00318     }
00319 
00320     template<typename T>
00321     static R boundthunk(void *object, void *func, A1 a1, A2 a2, A3 a3) {
00322         T *o = static_cast<T*>(object);
00323         R (*f)(T*, A1, A2, A3) = *reinterpret_cast<R (**)(T*, A1, A2, A3)>(func);
00324         return f(o, a1);
00325     }
00326 
00327     template<typename T>
00328     static R methodthunk(void *object, void *member, A1 a1, A2 a2, A3 a3) {
00329         T* o = static_cast<T*>(object);
00330         R (T::*m)(A1, A2, A3) = *reinterpret_cast<R (T::**)(A1, A2, A3)>(member);
00331         return (o->*m)(a1, a2, a3);
00332     }
00333 
00334     // Forward declaration of an unknown class
00335     // this kind of declaration is authorized by the standard (see 8.3.3/2 of C++ 03 standard).  
00336     // As a result, the compiler will allocate for UnknownFunctionMember_t the biggest size 
00337     // and biggest alignment possible for member function. 
00338     // This type can be used inside unions, it will help to provide the storage 
00339     // with the proper size and alignment guarantees 
00340     class UnknownClass;
00341 
00342     // object this pointer
00343     void *_object;
00344 
00345     // aligned raw member function pointer storage - converted back by registered thunk
00346     char _function[sizeof(void (UnknownClass::*)())];
00347 
00348     // registered function to convert back and call _m.member on _object
00349     R (*_thunk)(void*, void*, A1, A2, A3); 
00350 };
00351 
00352 /** A class for storing and calling a pointer to a static or member function
00353  */
00354 template <typename R, typename A1, typename A2>
00355 class FuncPtr<R(A1, A2)> {
00356 public:
00357     /** Create a FuncPtr, attaching a static function
00358      *
00359      *  @param function The static function to attach (default is none)
00360      */
00361     FuncPtr(R (*function)(A1, A2) = 0) {
00362         attach(function);
00363     }
00364 
00365     /** Create a FuncPtr, attaching a static function with bound pointer
00366      *
00367      *  @param object Pointer to object to bind to function
00368      *  @param function The static function to attach
00369      */
00370     template<typename T>
00371     FuncPtr(T *object, R (*function)(T*, A1, A2)) {
00372         attach(object, function);
00373     }
00374 
00375     /** Create a FuncPtr, attaching a member function
00376      *
00377      *  @param object The object pointer to invoke the member function on (i.e. the this pointer)
00378      *  @param function The address of the member function to attach
00379      */
00380     template<typename T>
00381     FuncPtr(T *object, R (T::*member)(A1, A2)) {
00382         attach(object, member);
00383     }
00384 
00385     /** Create a FuncPtr, attaching a function object
00386      *
00387      *  @param object Pointer to a function object to attach
00388      */
00389     template<typename T>
00390     FuncPtr(T *object) {
00391         attach(object, &T::operator());
00392     }
00393 
00394     /** Create a FuncPtr from another FuncPtr
00395      *
00396      *  @param func The func to attach
00397      */
00398     FuncPtr(const FuncPtr<R(A1, A2)> &func) {
00399         attach(func);
00400     }
00401 
00402     /** Attach a static function
00403      *
00404      *  @param function The static function to attach (default is none)
00405      */
00406     void attach(R (*function)(A1, A2)) {
00407         _object = 0;
00408         memcpy(&_function, &function, sizeof function);
00409         _thunk = &FuncPtr::staticthunk;
00410     }
00411 
00412     /** Attach a static function with bound pointer
00413      *
00414      *  @param object Pointer to object to bind to function
00415      *  @param function The static function to attach
00416      */
00417     template <typename T>
00418     void attach(T *object, R (*function)(T*, A1, A2)) {
00419         _object = static_cast<void*>(object);
00420         memcpy(&_function, &function, sizeof function);
00421         _thunk = &FuncPtr::boundthunk<T>;
00422     }
00423 
00424     /** Attach a member function
00425      *
00426      *  @param object The object pointer to invoke the member function on (i.e. the this pointer)
00427      *  @param function The address of the member function to attach
00428      */
00429     template<typename T>
00430     void attach(T *object, R (T::*method)(A1, A2)) {
00431         _object = static_cast<void*>(object);
00432         memcpy(&_function, &method, sizeof method);
00433         _thunk = &FuncPtr::methodthunk<T>;
00434     }
00435 
00436     /** Attach a function object
00437      *
00438      *  @param object Pointer to a function object to attach
00439      */
00440     template<typename T>
00441     void attach(T *object) {
00442         attach(object, &T::operator());
00443     }
00444 
00445     /** Attach a FuncPtr
00446      *
00447      *  @param func The func to attach
00448      */
00449     void attach(const FuncPtr<R(A1, A2)> &func) {
00450         _object = func._object;
00451         memcpy(&_function, &func._function, sizeof _function);
00452         _thunk = func._thunk;
00453     }
00454 
00455     /** Call the attached static or member function
00456      */
00457     R call(A1 a1, A2 a2) {
00458         return _thunk(_object, _function, a1, a2);
00459     }
00460 
00461     /** Get registered static function
00462      */
00463     R (*get_function(A1, A2))() {
00464         return reinterpret_cast<R (*)(A1, A2)>(_object ? 0 : _function);
00465     }
00466 
00467 #ifdef MBED_OPERATORS
00468     R operator ()(A1 a1, A2 a2) {
00469         return call(a1, a2);
00470     }
00471     operator bool(void) const {
00472         return static_cast<bool>(_function);
00473     }
00474 #endif
00475 private:
00476     // Static thunks for various function types
00477     static R staticthunk(void*, void *func, A1 a1, A2 a2) {
00478         R (*f)(A1, A2) = *reinterpret_cast<R (**)(A1, A2)>(func);
00479         return f(a1, a2);
00480     }
00481 
00482     template<typename T>
00483     static R boundthunk(void *object, void *func, A1 a1, A2 a2) {
00484         T *o = static_cast<T*>(object);
00485         R (*f)(T*, A1, A2) = *reinterpret_cast<R (**)(T*, A1, A2)>(func);
00486         return f(o, a1);
00487     }
00488 
00489     template<typename T>
00490     static R methodthunk(void *object, void *member, A1 a1, A2 a2) {
00491         T* o = static_cast<T*>(object);
00492         R (T::*m)(A1, A2) = *reinterpret_cast<R (T::**)(A1, A2)>(member);
00493         return (o->*m)(a1, a2);
00494     }
00495 
00496     // Forward declaration of an unknown class
00497     // this kind of declaration is authorized by the standard (see 8.3.3/2 of C++ 03 standard).  
00498     // As a result, the compiler will allocate for UnknownFunctionMember_t the biggest size 
00499     // and biggest alignment possible for member function. 
00500     // This type can be used inside unions, it will help to provide the storage 
00501     // with the proper size and alignment guarantees 
00502     class UnknownClass;
00503 
00504     // object this pointer
00505     void *_object;
00506 
00507     // aligned raw member function pointer storage - converted back by registered thunk
00508     char _function[sizeof(void (UnknownClass::*)())];
00509 
00510     // registered function to convert back and call _m.member on _object
00511     R (*_thunk)(void*, void*, A1, A2); 
00512 };
00513 
00514 /** A class for storing and calling a pointer to a static or member function
00515  */
00516 template <typename R, typename A1>
00517 class FuncPtr<R(A1)> {
00518 public:
00519     /** Create a FuncPtr, attaching a static function
00520      *
00521      *  @param function The static function to attach (default is none)
00522      */
00523     FuncPtr(R (*function)(A1) = 0) {
00524         attach(function);
00525     }
00526 
00527     /** Create a FuncPtr, attaching a static function with bound pointer
00528      *
00529      *  @param object Pointer to object to bind to function
00530      *  @param function The static function to attach
00531      */
00532     template<typename T>
00533     FuncPtr(T *object, R (*function)(T*, A1)) {
00534         attach(object, function);
00535     }
00536 
00537     /** Create a FuncPtr, attaching a member function
00538      *
00539      *  @param object The object pointer to invoke the member function on (i.e. the this pointer)
00540      *  @param function The address of the member function to attach
00541      */
00542     template<typename T>
00543     FuncPtr(T *object, R (T::*member)(A1)) {
00544         attach(object, member);
00545     }
00546 
00547     /** Create a FuncPtr, attaching a function object
00548      *
00549      *  @param object Pointer to a function object to attach
00550      */
00551     template<typename T>
00552     FuncPtr(T *object) {
00553         attach(object, &T::operator());
00554     }
00555 
00556     /** Create a FuncPtr from another FuncPtr
00557      *
00558      *  @param func The func to attach
00559      */
00560     FuncPtr(const FuncPtr<R(A1)> &func) {
00561         attach(func);
00562     }
00563 
00564     /** Attach a static function
00565      *
00566      *  @param function The static function to attach (default is none)
00567      */
00568     void attach(R (*function)(A1)) {
00569         _object = 0;
00570         memcpy(&_function, &function, sizeof function);
00571         _thunk = &FuncPtr::staticthunk;
00572     }
00573 
00574     /** Attach a static function with bound pointer
00575      *
00576      *  @param object Pointer to object to bind to function
00577      *  @param function The static function to attach
00578      */
00579     template <typename T>
00580     void attach(T *object, R (*function)(T*, A1)) {
00581         _object = static_cast<void*>(object);
00582         memcpy(&_function, &function, sizeof function);
00583         _thunk = &FuncPtr::boundthunk<T>;
00584     }
00585 
00586     /** Attach a member function
00587      *
00588      *  @param object The object pointer to invoke the member function on (i.e. the this pointer)
00589      *  @param function The address of the member function to attach
00590      */
00591     template<typename T>
00592     void attach(T *object, R (T::*method)(A1)) {
00593         _object = static_cast<void*>(object);
00594         memcpy(&_function, &method, sizeof method);
00595         _thunk = &FuncPtr::methodthunk<T>;
00596     }
00597 
00598     /** Attach a function object
00599      *
00600      *  @param object Pointer to a function object to attach
00601      */
00602     template<typename T>
00603     void attach(T *object) {
00604         attach(object, &T::operator());
00605     }
00606 
00607     /** Attach a FuncPtr
00608      *
00609      *  @param func The func to attach
00610      */
00611     void attach(const FuncPtr<R(A1)> &func) {
00612         _object = func._object;
00613         memcpy(&_function, &func._function, sizeof _function);
00614         _thunk = func._thunk;
00615     }
00616 
00617     /** Call the attached static or member function
00618      */
00619     R call(A1 a1) {
00620         return _thunk(_object, _function, a1);
00621     }
00622 
00623     /** Get registered static function
00624      */
00625     R (*get_function(A1))() {
00626         return reinterpret_cast<R (*)(A1)>(_object ? 0 : _function);
00627     }
00628 
00629 #ifdef MBED_OPERATORS
00630     R operator ()(A1 a1) {
00631         return call(a1);
00632     }
00633     operator bool(void) const {
00634         return static_cast<bool>(_function);
00635     }
00636 #endif
00637 private:
00638     // Static thunks for various function types
00639     static R staticthunk(void*, void *func, A1 a1) {
00640         R (*f)(A1) = *reinterpret_cast<R (**)(A1)>(func);
00641         return f(a1);
00642     }
00643 
00644     template<typename T>
00645     static R boundthunk(void *object, void *func, A1 a1) {
00646         T *o = static_cast<T*>(object);
00647         R (*f)(T*, A1) = *reinterpret_cast<R (**)(T*, A1)>(func);
00648         return f(o, a1);
00649     }
00650 
00651     template<typename T>
00652     static R methodthunk(void *object, void *member, A1 a1) {
00653         T* o = static_cast<T*>(object);
00654         R (T::*m)(A1) = *reinterpret_cast<R (T::**)(A1)>(member);
00655         return (o->*m)(a1);
00656     }
00657 
00658     // Forward declaration of an unknown class
00659     // this kind of declaration is authorized by the standard (see 8.3.3/2 of C++ 03 standard).  
00660     // As a result, the compiler will allocate for UnknownFunctionMember_t the biggest size 
00661     // and biggest alignment possible for member function. 
00662     // This type can be used inside unions, it will help to provide the storage 
00663     // with the proper size and alignment guarantees 
00664     class UnknownClass;
00665 
00666     // object this pointer
00667     void *_object;
00668 
00669     // aligned raw member function pointer storage - converted back by registered thunk
00670     char _function[sizeof(void (UnknownClass::*)())];
00671 
00672     // registered function to convert back and call _m.member on _object
00673     R (*_thunk)(void*, void*, A1); 
00674 };
00675 
00676 /** A class for storing and calling a pointer to a static or member function
00677  */
00678 template <typename R>
00679 class FuncPtr<R()> {
00680 public:
00681     /** Create a FuncPtr, attaching a static function
00682      *
00683      *  @param function The static function to attach (default is none)
00684      */
00685     FuncPtr(R (*function)() = 0) {
00686         attach(function);
00687     }
00688 
00689     /** Create a FuncPtr, attaching a static function with bound pointer
00690      *
00691      *  @param object Pointer to object to bind to function
00692      *  @param function The static function to attach
00693      */
00694     template<typename T>
00695     FuncPtr(T *object, R (*function)(T*)) {
00696         attach(object, function);
00697     }
00698 
00699     /** Create a FuncPtr, attaching a member function
00700      *
00701      *  @param object The object pointer to invoke the member function on (i.e. the this pointer)
00702      *  @param function The address of the member function to attach
00703      */
00704     template<typename T>
00705     FuncPtr(T *object, R (T::*member)()) {
00706         attach(object, member);
00707     }
00708 
00709     /** Create a FuncPtr, attaching a function object
00710      *
00711      *  @param object Pointer to a function object to attach
00712      */
00713     template<typename T>
00714     FuncPtr(T *object) {
00715         attach(object, &T::operator());
00716     }
00717 
00718     /** Create a FuncPtr from another FuncPtr
00719      *
00720      *  @param func The func to attach
00721      */
00722     FuncPtr(const FuncPtr<R()> &func) {
00723         attach(func);
00724     }
00725 
00726     /** Attach a static function
00727      *
00728      *  @param function The static function to attach (default is none)
00729      */
00730     void attach(R (*function)()) {
00731         _object = 0;
00732         memcpy(&_function, &function, sizeof function);
00733         _thunk = &FuncPtr::staticthunk;
00734     }
00735 
00736     /** Attach a static function with bound pointer
00737      *
00738      *  @param object Pointer to object to bind to function
00739      *  @param function The static function to attach
00740      */
00741     template <typename T>
00742     void attach(T *object, R (*function)(T*)) {
00743         _object = static_cast<void*>(object);
00744         memcpy(&_function, &function, sizeof function);
00745         _thunk = &FuncPtr::boundthunk<T>;
00746     }
00747 
00748     /** Attach a member function
00749      *
00750      *  @param object The object pointer to invoke the member function on (i.e. the this pointer)
00751      *  @param function The address of the member function to attach
00752      */
00753     template<typename T>
00754     void attach(T *object, R (T::*method)()) {
00755         _object = static_cast<void*>(object);
00756         memcpy(&_function, &method, sizeof method);
00757         _thunk = &FuncPtr::methodthunk<T>;
00758     }
00759 
00760     /** Attach a function object
00761      *
00762      *  @param object Pointer to a function object to attach
00763      */
00764     template<typename T>
00765     void attach(T *object) {
00766         attach(object, &T::operator());
00767     }
00768 
00769     /** Attach a FuncPtr
00770      *
00771      *  @param func The func to attach
00772      */
00773     void attach(const FuncPtr<R()> &func) {
00774         _object = func._object;
00775         memcpy(&_function, &func._function, sizeof _function);
00776         _thunk = func._thunk;
00777     }
00778 
00779     /** Call the attached static or member function
00780      */
00781     R call() {
00782         return _thunk(_object, _function);
00783     }
00784 
00785     /** Get registered static function
00786      */
00787     R (*get_function())() {
00788         return reinterpret_cast<R (*)()>(_object ? 0 : _function);
00789     }
00790 
00791 #ifdef MBED_OPERATORS
00792     R operator ()() {
00793         return call();
00794     }
00795     operator bool(void) const {
00796         return static_cast<bool>(_function);
00797     }
00798 #endif
00799 private:
00800     // Static thunks for various function types
00801     static R staticthunk(void*, void *func) {
00802         R (*f)() = *reinterpret_cast<R (**)()>(func);
00803         return f();
00804     }
00805 
00806     template<typename T>
00807     static R boundthunk(void *object, void *func) {
00808         T *o = static_cast<T*>(object);
00809         R (*f)(T*) = *reinterpret_cast<R (**)(T*)>(func);
00810         return f(o);
00811     }
00812 
00813     template<typename T>
00814     static R methodthunk(void *object, void *member) {
00815         T* o = static_cast<T*>(object);
00816         R (T::*m)() = *reinterpret_cast<R (T::**)()>(member);
00817         return (o->*m)();
00818     }
00819 
00820     // Forward declaration of an unknown class
00821     // this kind of declaration is authorized by the standard (see 8.3.3/2 of C++ 03 standard).  
00822     // As a result, the compiler will allocate for UnknownFunctionMember_t the biggest size 
00823     // and biggest alignment possible for member function. 
00824     // This type can be used inside unions, it will help to provide the storage 
00825     // with the proper size and alignment guarantees 
00826     class UnknownClass;
00827 
00828     // object this pointer
00829     void *_object;
00830 
00831     // aligned raw member function pointer storage - converted back by registered thunk
00832     union {
00833         char _function[sizeof(void (UnknownClass::*)())];
00834         void (UnknownClass::*_unknownMethod)();
00835     };
00836 
00837     // registered function to convert back and call _m.member on _object
00838     R (*_thunk)(void*, void*); 
00839 };
00840 
00841 // Overloads for backwards compatibility
00842 template <typename R, typename A1>
00843 class FunctionPointerArg1 : public FuncPtr<R(A1)> {};
00844 
00845 template <typename R>
00846 class FunctionPointerArg1<R, void> : public FuncPtr<R()> {};
00847 
00848 typedef FuncPtr<void()> FunctionPointer;
00849 typedef FuncPtr<void(int)> event_callback_t;
00850 
00851 } // namespace mbed
00852 
00853 #endif