++

Fork of mbed-stm32l0/l1-src by lzbp li

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 /* If we had variaditic templates, this wouldn't be a problem, but until C++11 is enabled, we are stuck with multiple classes... */
00025 
00026 /** A class for storing and calling a pointer to a static or member function
00027  */
00028 template <typename R, typename A1>
00029 class FunctionPointerArg1{
00030 public:
00031     /** Create a FunctionPointer, attaching a static function
00032      *
00033      *  @param function The static function to attach (default is none)
00034      */
00035     FunctionPointerArg1(R (*function)(A1) = 0) {
00036         attach(function);
00037     }
00038 
00039     /** Create a FunctionPointer, attaching a member function
00040      *
00041      *  @param object The object pointer to invoke the member function on (i.e. the this pointer)
00042      *  @param function The address of the member function to attach
00043      */
00044     template<typename T>
00045     FunctionPointerArg1(T *object, R (T::*member)(A1)) {
00046         attach(object, member);
00047     }
00048 
00049     /** Attach a static function
00050      *
00051      *  @param function The static function to attach (default is none)
00052      */
00053     void attach(R (*function)(A1)) {
00054         _p.function = function;
00055         _membercaller = 0;
00056     }
00057 
00058     /** Attach a member function
00059      *
00060      *  @param object The object pointer to invoke the member function on (i.e. the this pointer)
00061      *  @param function The address of the member function to attach
00062      */
00063     template<typename T>
00064     void attach(T *object, R (T::*member)(A1)) {
00065         _p.object = static_cast<void*>(object);
00066         *reinterpret_cast<R (T::**)(A1)>(_member) = member;
00067         _membercaller = &FunctionPointerArg1::membercaller<T>;
00068     }
00069 
00070     /** Call the attached static or member function
00071      */
00072     R call(A1 a) {
00073         if (_membercaller == 0 && _p.function) {
00074            return _p.function(a);
00075         } else if (_membercaller && _p.object) {
00076            return _membercaller(_p.object, _member, a);
00077         }
00078         return (R)0;
00079     }
00080 
00081     /** Get registered static function
00082      */
00083     R(*get_function(A1))() {
00084         return _membercaller ? (R(*)(A1))0 : (R(*)(A1))_p.function;
00085     }
00086 
00087 #ifdef MBED_OPERATORS
00088     R operator ()(A1 a) {
00089         return call(a);
00090     }
00091     operator bool(void) const {
00092         return (_membercaller != NULL ? _p.object : (void*)_p.function) != NULL;
00093     }
00094 #endif
00095 private:
00096     template<typename T>
00097     static R membercaller(void *object, uintptr_t *member, A1 a) {
00098         T* o = static_cast<T*>(object);
00099         R (T::**m)(A1) = reinterpret_cast<R (T::**)(A1)>(member);
00100         return (o->**m)(a);
00101     }
00102 
00103     union {
00104         R (*function)(A1); // static function pointer
00105         void *object;      // object this pointer
00106     } _p;
00107     uintptr_t _member[4]; // aligned raw member function pointer storage - converted back by registered _membercaller
00108     R (*_membercaller)(void*, uintptr_t*, A1); // registered membercaller function to convert back and call _m.member on _object
00109 };
00110 
00111 /** A class for storing and calling a pointer to a static or member function (R ()(void))
00112  */
00113 template <typename R>
00114 class FunctionPointerArg1<R, void>{
00115 public:
00116     /** Create a FunctionPointer, attaching a static function
00117      *
00118      *  @param function The static function to attach (default is none)
00119      */
00120     FunctionPointerArg1(R (*function)(void) = 0) {
00121         attach(function);
00122     }
00123 
00124     /** Create a FunctionPointer, attaching a member function
00125      *
00126      *  @param object The object pointer to invoke the member function on (i.e. the this pointer)
00127      *  @param function The address of the void member function to attach
00128      */
00129     template<typename T>
00130     FunctionPointerArg1(T *object, R (T::*member)(void)) {
00131         attach(object, member);
00132     }
00133 
00134     /** Attach a static function
00135      *
00136      *  @param function The void static function to attach (default is none)
00137      */
00138     void attach(R (*function)(void)) {
00139         _p.function = function;
00140         _membercaller = 0;
00141     }
00142 
00143     /** Attach a member function
00144      *
00145      *  @param object The object pointer to invoke the member function on (i.e. the this pointer)
00146      *  @param function The address of the void member function to attach
00147      */
00148     template<typename T>
00149     void attach(T *object, R (T::*member)(void)) {
00150         _p.object = static_cast<void*>(object);
00151         *reinterpret_cast<R (T::**)(void)>(_member) = member;
00152         _membercaller = &FunctionPointerArg1::membercaller<T>;
00153     }
00154 
00155     /** Call the attached static or member function
00156      */
00157     R call(){
00158         if (_membercaller == 0 && _p.function) {
00159             return _p.function();
00160         } else if (_membercaller && _p.object) {
00161             return _membercaller(_p.object, _member);
00162         }
00163         return (R)0;
00164     }
00165 
00166     /** Get registered static function
00167      */
00168     R(*get_function())() {
00169         return _membercaller ? (R(*)())0 : (R(*)())_p.function;
00170     }
00171 
00172 #ifdef MBED_OPERATORS
00173     R operator ()(void) {
00174         return call();
00175     }
00176     operator bool(void) const {
00177         return (_membercaller != NULL ? _p.object : (void*)_p.function) != NULL;
00178     }
00179 #endif
00180 
00181 private:
00182     template<typename T>
00183     static R membercaller(void *object, uintptr_t *member) {
00184         T* o = static_cast<T*>(object);
00185         R (T::**m)(void) = reinterpret_cast<R (T::**)(void)>(member);
00186         return (o->**m)();
00187     }
00188 
00189     union {
00190         R (*function)(void); // static function pointer
00191         void *object;        // object this pointer
00192     } _p;
00193     uintptr_t _member[4]; // aligned raw member function pointer storage - converted back by registered _membercaller
00194     R (*_membercaller)(void*, uintptr_t*); // registered membercaller function to convert back and call _m.member on _object
00195 };
00196 
00197 typedef FunctionPointerArg1<void, void> FunctionPointer;
00198 typedef FunctionPointerArg1<void, int> event_callback_t;
00199 
00200 } // namespace mbed
00201 
00202 #endif