Ram Gandikota / Mbed OS ABCD
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 #include <stddef.h>
00022 #include <stdarg.h>
00023 #include <new>
00024 #include "FunctionPointerBase.h"
00025 #include "FunctionPointerBind.h"
00026 
00027 namespace mbed {
00028 /** A class for storing and calling a pointer to a static or member void function without arguments
00029  */
00030 template <typename R>
00031 class FunctionPointer0 : public FunctionPointerBase<R>{
00032 public:
00033     typedef R(*static_fp)(void);
00034     typedef struct arg_struct{
00035     } ArgStruct;
00036     /** Create a FunctionPointer, attaching a static function
00037      *
00038      *  @param function The void static function to attach (default is none)
00039      */
00040     FunctionPointer0(static_fp function = 0):
00041         FunctionPointerBase<R>()
00042     {
00043         attach(function);
00044     }
00045 
00046     /** Create a FunctionPointer, attaching a member function
00047      *
00048      *  @param object The object pointer to invoke the member function on (i.e. the this pointer)
00049      *  @param function The address of the void member function to attach
00050      */
00051     template<typename T>
00052     FunctionPointer0(T *object, R (T::*member)(void)):
00053         FunctionPointerBase<R>()
00054     {
00055         attach(object, member);
00056     }
00057 
00058     /** Attach a static function
00059      *
00060      *  @param function The void static function to attach (default is none)
00061      */
00062     void attach(static_fp function) {
00063         FunctionPointerBase<R>::_object = reinterpret_cast<void*>(function);
00064         FunctionPointerBase<R>::_membercaller = &FunctionPointer0::staticcaller;
00065     }
00066 
00067     /** Attach a member function
00068      *
00069      *  @param object The object pointer to invoke the member function on (i.e. the this pointer)
00070      *  @param function The address of the void member function to attach
00071      */
00072     template<typename T>
00073     void attach(T *object, R (T::*member)(void)) {
00074         FunctionPointerBase<R>::_object = static_cast<void*>(object);
00075         *reinterpret_cast<R (T::**)(void)>(FunctionPointerBase<R>::_member) = member;
00076         FunctionPointerBase<R>::_membercaller = &FunctionPointer0::membercaller<T>;
00077     }
00078 
00079     /** Call the attached static or member function
00080      */
00081     R call(){
00082         return FunctionPointerBase<R>::call(NULL);
00083     }
00084 
00085     FunctionPointerBind<R> bind() {
00086         FunctionPointerBind<R> fp;
00087         fp.bind(&FunctionPointerBase<R>::_nullops, (ArgStruct *) NULL, this);
00088         return fp;
00089     }
00090 
00091     static_fp get_function()const {
00092         return reinterpret_cast<static_fp>(FunctionPointerBase<R>::_object);
00093     }
00094 
00095     R operator ()(void) {
00096         return call();
00097     }
00098 
00099 private:
00100     template<typename T>
00101     static R membercaller(void *object, uintptr_t *member, void *arg) {
00102         (void) arg;
00103         T* o = static_cast<T*>(object);
00104         R (T::**m)(void) = reinterpret_cast<R (T::**)(void)>(member);
00105         return (o->**m)();
00106     }
00107     static R staticcaller(void *object, uintptr_t *member, void *arg) {
00108         (void) arg;
00109         (void) member;
00110         static_fp f = reinterpret_cast<static_fp>(object);
00111         return f();
00112     }
00113 };
00114 
00115 /* If we had variaditic templates, this wouldn't be a problem, but until C++11 is enabled, we are stuck with multiple classes... */
00116 
00117 /** A class for storing and calling a pointer to a static or member void function with one argument
00118  */
00119 template <typename R, typename A1>
00120 class FunctionPointer1 : public FunctionPointerBase<R> {
00121 protected:
00122     typedef struct arg_struct{
00123         A1 a1;
00124         arg_struct(const A1 *b1) {
00125             a1 = *b1;
00126         }
00127     } ArgStruct;
00128 
00129 public:
00130     typedef R(*static_fp)(A1);
00131     /** Create a FunctionPointer, attaching a static function
00132      *
00133      *  @param function The void static function to attach (default is none)
00134      */
00135     FunctionPointer1(static_fp function = 0) {
00136         attach(function);
00137     }
00138 
00139     /** Create a FunctionPointer, attaching a member function
00140      *
00141      *  @param object The object pointer to invoke the member function on (i.e. the this pointer)
00142      *  @param function The address of the void member function to attach
00143      */
00144     template<typename T>
00145     FunctionPointer1(T *object, R (T::*member)(A1)) {
00146         attach(object, member);
00147     }
00148 
00149     /** Attach a static function
00150      *
00151      *  @param function The void static function to attach (default is none)
00152      */
00153     void attach(static_fp function) {
00154         FunctionPointerBase<R>::_object = reinterpret_cast<void*>(function);
00155         FunctionPointerBase<R>::_membercaller = &FunctionPointer1::staticcaller;
00156     }
00157 
00158     /** Attach a member function
00159      *
00160      *  @param object The object pointer to invoke the member function on (i.e. the this pointer)
00161      *  @param function The address of the void member function to attach
00162      */
00163     template<typename T>
00164     void attach(T *object, R (T::*member)(A1))
00165     {
00166         FunctionPointerBase<R>::_object = static_cast<void*>(object);
00167         *reinterpret_cast<R (T::**)(A1)>(FunctionPointerBase<R>::_member) = member;
00168         FunctionPointerBase<R>::_membercaller = &FunctionPointer1::membercaller<T>;
00169     }
00170 
00171     FunctionPointerBind<R> bind(const A1 &a1) {
00172         FunctionPointerBind<R> fp;
00173         fp.bind(&_fp1_ops, (ArgStruct *) NULL, this, &a1);
00174         return fp;
00175     }
00176 
00177 
00178     /** Call the attached static or member function
00179      */
00180     R call(A1 a1)
00181     {
00182         ArgStruct Args(&a1);
00183         return FunctionPointerBase<R>::call(&Args);
00184     }
00185 
00186     static_fp get_function()const
00187     {
00188         return reinterpret_cast<static_fp>(FunctionPointerBase<R>::_object);
00189     }
00190 
00191     R operator ()(A1 a) {
00192         return call(a);
00193     }
00194 
00195 private:
00196     template<typename T>
00197     static R membercaller(void *object, uintptr_t *member, void *arg) {
00198         ArgStruct *Args = static_cast<ArgStruct *>(arg);
00199         T* o = static_cast<T*>(object);
00200         R (T::**m)(A1) = reinterpret_cast<R (T::**)(A1)>(member);
00201         return (o->**m)(Args->a1);
00202     }
00203     static R staticcaller(void *object, uintptr_t *member, void *arg) {
00204         ArgStruct *Args = static_cast<ArgStruct *>(arg);
00205         (void) member;
00206         static_fp f = reinterpret_cast<static_fp>(object);
00207         return f(Args->a1);
00208     }
00209 /*    static void constructor(void * dest, va_list args) {
00210         new(dest) ArgStruct(va_arg(args,A1*));
00211     }
00212     static void copy_constructor(void *dest , void* src) {
00213         ArgStruct *src_args = static_cast<ArgStruct *>(src);
00214         new(dest) ArgStruct(&(src_args->a1));
00215     }
00216     static void destructor(void *args) {
00217         ArgStruct *argstruct = static_cast<ArgStruct *>(args);
00218         argstruct->~arg_struct();
00219     }
00220 */
00221 protected:
00222     static const struct FunctionPointerBase<R>::ArgOps _fp1_ops;
00223 };
00224 
00225 template <typename R, typename A1>
00226 const struct FunctionPointerBase<R>::ArgOps FunctionPointer1<R,A1>::_fp1_ops = {
00227     FunctionPointer1<R,A1>::constructor,
00228     FunctionPointer1<R,A1>::copy_constructor,
00229     FunctionPointer1<R,A1>::destructor
00230 };
00231 
00232 
00233 /** A class for storing and calling a pointer to a static or member void function with two arguments
00234  */
00235 template <typename R, typename A1, typename A2>
00236 class FunctionPointer2 : public FunctionPointerBase<R> {
00237 protected:
00238     typedef struct arg_struct{
00239         A1 a1;
00240         A2 a2;
00241         arg_struct(const A1 *b1, const A2 *b2) {
00242             a1 = *b1;
00243             a2 = *b2;
00244         }
00245     } ArgStruct;
00246 
00247 public:
00248     typedef R(*static_fp)(A1, A2);
00249     /** Create a FunctionPointer, attaching a static function
00250      *
00251      *  @param function The void static function to attach (default is none)
00252      */
00253     FunctionPointer2(static_fp function = 0) {
00254         attach(function);
00255     }
00256 
00257     /** Create a FunctionPointer, attaching a member function
00258      *
00259      *  @param object The object pointer to invoke the member function on (i.e. the this pointer)
00260      *  @param function The address of the void member function to attach
00261      */
00262     template<typename T>
00263     FunctionPointer2(T *object, R (T::*member)(A1, A2)) {
00264         attach(object, member);
00265     }
00266 
00267     /** Attach a static function
00268      *
00269      *  @param function The void static function to attach (default is none)
00270      */
00271     void attach(static_fp function) {
00272         FunctionPointerBase<R>::_object = reinterpret_cast<void*>(function);
00273         FunctionPointerBase<R>::_membercaller = &FunctionPointer2::staticcaller;
00274     }
00275 
00276     /** Attach a member function
00277      *
00278      *  @param object The object pointer to invoke the member function on (i.e. the this pointer)
00279      *  @param function The address of the void member function to attach
00280      */
00281     template<typename T>
00282     void attach(T *object, R (T::*member)(A1, A2))
00283     {
00284         FunctionPointerBase<R>::_object = static_cast<void*>(object);
00285         *reinterpret_cast<R (T::**)(A1, A2)>(FunctionPointerBase<R>::_member) = member;
00286         FunctionPointerBase<R>::_membercaller = &FunctionPointer2::membercaller<T>;
00287     }
00288 
00289     FunctionPointerBind<R> bind(const A1 &a1, const A2 &a2) {
00290         FunctionPointerBind<R> fp;
00291         fp.bind(&_fp2_ops, (ArgStruct *) NULL, this, &a1, &a2);
00292         return fp;
00293     }
00294 
00295 
00296     /** Call the attached static or member function
00297      */
00298     R call(A1 a1, A2 a2)
00299     {
00300         ArgStruct Args(&a1, &a2);
00301         return FunctionPointerBase<R>::call(&Args);
00302     }
00303 
00304     static_fp get_function()const
00305     {
00306         return reinterpret_cast<static_fp>(FunctionPointerBase<R>::_object);
00307     }
00308 
00309     R operator ()(A1 a1, A2 a2) {
00310         return call(a1, a2);
00311     }
00312 
00313 private:
00314     template<typename T>
00315     static R membercaller(void *object, uintptr_t *member, void *arg) {
00316         ArgStruct *Args = static_cast<ArgStruct *>(arg);
00317         T* o = static_cast<T*>(object);
00318         R (T::**m)(A1, A2) = reinterpret_cast<R (T::**)(A1, A2)>(member);
00319         return (o->**m)(Args->a1, Args->a2);
00320     }
00321     static R staticcaller(void *object, uintptr_t *member, void *arg) {
00322         ArgStruct *Args = static_cast<ArgStruct *>(arg);
00323         (void) member;
00324         static_fp f = reinterpret_cast<static_fp>(object);
00325         return f(Args->a1, Args->a2);
00326     }
00327 /*    static void constructor(void * dest, va_list args) {
00328         A1 *a1 = va_arg(args, A1*);
00329         A2 *a2 = va_arg(args, A2*);
00330         new(dest) ArgStruct(a1, a2);
00331     }
00332     static void copy_constructor(void *dest , void* src) {
00333         ArgStruct *src_args = static_cast<ArgStruct *>(src);
00334         new(dest) ArgStruct(&(src_args->a1), &(src_args->a2));
00335     }
00336     static void destructor(void *args) {
00337         ArgStruct *argstruct = static_cast<ArgStruct *>(args);
00338         argstruct->~arg_struct();
00339     }
00340 */
00341 protected:
00342     static const struct FunctionPointerBase<R>::ArgOps _fp2_ops;
00343 };
00344 
00345 template <typename R, typename A1, typename A2>
00346 const struct FunctionPointerBase<R>::ArgOps FunctionPointer2<R,A1,A2>::_fp2_ops = {
00347     FunctionPointer2<R,A1,A2>::constructor,
00348     FunctionPointer2<R,A1,A2>::copy_constructor,
00349     FunctionPointer2<R,A1,A2>::destructor
00350 };
00351 
00352 /** A class for storing and calling a pointer to a static or member void function with three arguments
00353  */
00354 template <typename R, typename A1, typename A2, typename A3>
00355 class FunctionPointer3 : public FunctionPointerBase<R> {
00356 protected:
00357     typedef struct arg_struct{
00358         A1 a1;
00359         A2 a2;
00360         A3 a3;
00361         arg_struct(const A1 *b1, const A2 *b2, const A3* b3) {
00362             a1 = *b1;
00363             a2 = *b2;
00364             a3 = *b3;
00365         }
00366     } ArgStruct;
00367 
00368 public:
00369     typedef R(*static_fp)(A1, A2, A3);
00370     /** Create a FunctionPointer, attaching a static function
00371      *
00372      *  @param function The void static function to attach (default is none)
00373      */
00374     FunctionPointer3(static_fp function = 0) {
00375         attach(function);
00376     }
00377 
00378     /** Create a FunctionPointer, attaching a member function
00379      *
00380      *  @param object The object pointer to invoke the member function on (i.e. the this pointer)
00381      *  @param function The address of the void member function to attach
00382      */
00383     template<typename T>
00384     FunctionPointer3(T *object, R (T::*member)(A1, A2, A3)) {
00385         attach(object, member);
00386     }
00387 
00388     /** Attach a static function
00389      *
00390      *  @param function The void static function to attach (default is none)
00391      */
00392     void attach(static_fp function) {
00393         FunctionPointerBase<R>::_object = reinterpret_cast<void*>(function);
00394         FunctionPointerBase<R>::_membercaller = &FunctionPointer3::staticcaller;
00395     }
00396 
00397     /** Attach a member function
00398      *
00399      *  @param object The object pointer to invoke the member function on (i.e. the this pointer)
00400      *  @param function The address of the void member function to attach
00401      */
00402     template<typename T>
00403     void attach(T *object, R (T::*member)(A1, A2, A3))
00404     {
00405         FunctionPointerBase<R>::_object = static_cast<void*>(object);
00406         *reinterpret_cast<R (T::**)(A1, A2, A3)>(FunctionPointerBase<R>::_member) = member;
00407         FunctionPointerBase<R>::_membercaller = &FunctionPointer3::membercaller<T>;
00408     }
00409 
00410     FunctionPointerBind<R> bind(const A1 &a1, const A2 &a2, const A3 &a3) {
00411         FunctionPointerBind<R> fp;
00412         fp.bind(&_fp3_ops, (ArgStruct *) NULL, this, &a1, &a2, &a3);
00413         return fp;
00414     }
00415 
00416 
00417     /** Call the attached static or member function
00418      */
00419     R call(A1 a1, A2 a2, A3 a3)
00420     {
00421         ArgStruct Args(&a1, &a2, &a3);
00422         return FunctionPointerBase<R>::call(&Args);
00423     }
00424 
00425     static_fp get_function()const
00426     {
00427         return reinterpret_cast<static_fp>(FunctionPointerBase<R>::_object);
00428     }
00429 
00430     R operator ()(A1 a1, A2 a2, A3 a3) {
00431         return call(a1, a2, a3);
00432     }
00433 
00434 private:
00435     template<typename T>
00436     static R membercaller(void *object, uintptr_t *member, void *arg) {
00437         ArgStruct *Args = static_cast<ArgStruct *>(arg);
00438         T* o = static_cast<T*>(object);
00439         R (T::**m)(A1, A2, A3) = reinterpret_cast<R (T::**)(A1, A2, A3)>(member);
00440         return (o->**m)(Args->a1, Args->a2, Args->a3);
00441     }
00442     static R staticcaller(void *object, uintptr_t *member, void *arg) {
00443         ArgStruct *Args = static_cast<ArgStruct *>(arg);
00444         (void) member;
00445         static_fp f = reinterpret_cast<static_fp>(object);
00446         return f(Args->a1, Args->a2, Args->a3);
00447     }
00448 /*    static void constructor(void * dest, va_list args) {
00449         A1 *a1 = va_arg(args, A1*);
00450         A2 *a2 = va_arg(args, A2*);
00451         A3 *a3 = va_arg(args, A3*);
00452         new(dest) ArgStruct(a1, a2, a3);
00453     }
00454     static void copy_constructor(void *dest , void* src) {
00455         ArgStruct *src_args = static_cast<ArgStruct *>(src);
00456         new(dest) ArgStruct(&(src_args->a1), &(src_args->a2), &(src_args->a3));
00457     }
00458     static void destructor(void *args) {
00459         ArgStruct *argstruct = static_cast<ArgStruct *>(args);
00460         argstruct->~arg_struct();
00461     }
00462 */
00463 protected:
00464     static const struct FunctionPointerBase<R>::ArgOps _fp3_ops;
00465 };
00466 
00467 template <typename R, typename A1, typename A2, typename A3>
00468 const struct FunctionPointerBase<R>::ArgOps FunctionPointer3<R,A1,A2,A3>::_fp3_ops = {
00469     FunctionPointer3<R,A1,A2,A3>::constructor,
00470     FunctionPointer3<R,A1,A2,A3>::copy_constructor,
00471     FunctionPointer3<R,A1,A2,A3>::destructor
00472 };
00473 
00474 /** A class for storing and calling a pointer to a static or member void function with four arguments
00475  */
00476 template <typename R, typename A1, typename A2, typename A3, typename A4>
00477 class FunctionPointer4 : public FunctionPointerBase<R> {
00478 protected:
00479     typedef struct arg_struct{
00480         A1 a1;
00481         A2 a2;
00482         A3 a3;
00483         A4 a4;
00484         arg_struct(const A1 *b1, const A2 *b2, const A3* b3, const A4* b4) {
00485             a1 = *b1;
00486             a2 = *b2;
00487             a3 = *b3;
00488             a4 = *b4;
00489         }
00490     } ArgStruct;
00491 
00492 public:
00493     typedef R(*static_fp)(A1, A2, A3, A4);
00494     /** Create a FunctionPointer, attaching a static function
00495      *
00496      *  @param function The void static function to attach (default is none)
00497      */
00498     FunctionPointer4(static_fp function = 0) {
00499         attach(function);
00500     }
00501 
00502     /** Create a FunctionPointer, attaching a member function
00503      *
00504      *  @param object The object pointer to invoke the member function on (i.e. the this pointer)
00505      *  @param function The address of the void member function to attach
00506      */
00507     template<typename T>
00508     FunctionPointer4(T *object, R (T::*member)(A1, A2, A3, A4)) {
00509         attach(object, member);
00510     }
00511 
00512     /** Attach a static function
00513      *
00514      *  @param function The void static function to attach (default is none)
00515      */
00516     void attach(static_fp function) {
00517         FunctionPointerBase<R>::_object = reinterpret_cast<void*>(function);
00518         FunctionPointerBase<R>::_membercaller = &FunctionPointer4::staticcaller;
00519     }
00520 
00521     /** Attach a member function
00522      *
00523      *  @param object The object pointer to invoke the member function on (i.e. the this pointer)
00524      *  @param function The address of the void member function to attach
00525      */
00526     template<typename T>
00527     void attach(T *object, R (T::*member)(A1, A2, A3, A4))
00528     {
00529         FunctionPointerBase<R>::_object = static_cast<void*>(object);
00530         *reinterpret_cast<R (T::**)(A1, A2, A3, A4)>(FunctionPointerBase<R>::_member) = member;
00531         FunctionPointerBase<R>::_membercaller = &FunctionPointer4::membercaller<T>;
00532     }
00533 
00534     FunctionPointerBind<R> bind(const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4) {
00535         FunctionPointerBind<R> fp;
00536         fp.bind(&_fp4_ops, (ArgStruct *) NULL, this, &a1, &a2, &a3, &a4);
00537         return fp;
00538     }
00539 
00540 
00541     /** Call the attached static or member function
00542      */
00543     R call(A1 a1, A2 a2, A3 a3, A4 a4)
00544     {
00545         ArgStruct Args(&a1, &a2, &a3, &a4);
00546         return FunctionPointerBase<R>::call(&Args);
00547     }
00548 
00549     static_fp get_function()const
00550     {
00551         return reinterpret_cast<static_fp>(FunctionPointerBase<R>::_object);
00552     }
00553 
00554     R operator ()(A1 a1, A2 a2, A3 a3, A4 a4) {
00555         return call(a1, a2, a3, a4);
00556     }
00557 
00558 private:
00559     template<typename T>
00560     static R membercaller(void *object, uintptr_t *member, void *arg) {
00561         ArgStruct *Args = static_cast<ArgStruct *>(arg);
00562         T* o = static_cast<T*>(object);
00563         R (T::**m)(A1, A2, A3, A4) = reinterpret_cast<R (T::**)(A1, A2, A3, A4)>(member);
00564         return (o->**m)(Args->a1, Args->a2, Args->a3, Args->a4);
00565     }
00566     static R staticcaller(void *object, uintptr_t *member, void *arg) {
00567         ArgStruct *Args = static_cast<ArgStruct *>(arg);
00568         (void) member;
00569         static_fp f = reinterpret_cast<static_fp>(object);
00570         return f(Args->a1, Args->a2, Args->a3, Args->a4);
00571     }
00572 /*    static void constructor(void * dest, va_list args) {
00573         A1 *a1 = va_arg(args, A1*);
00574         A2 *a2 = va_arg(args, A2*);
00575         A3 *a3 = va_arg(args, A3*);
00576         A4 *a4 = va_arg(args, A4*);
00577         new(dest) ArgStruct(a1, a2, a3, a4);
00578     }
00579     static void copy_constructor(void *dest , void* src) {
00580         ArgStruct *src_args = static_cast<ArgStruct *>(src);
00581         new(dest) ArgStruct(&(src_args->a1), &(src_args->a2), &(src_args->a3), &(src_args->a4));
00582     }
00583     static void destructor(void *args) {
00584         ArgStruct *argstruct = static_cast<ArgStruct *>(args);
00585         argstruct->~arg_struct();
00586     }
00587 */
00588 protected:
00589     static const struct FunctionPointerBase<R>::ArgOps _fp4_ops;
00590 };
00591 
00592 template <typename R, typename A1, typename A2, typename A3, typename A4>
00593 const struct FunctionPointerBase<R>::ArgOps FunctionPointer4<R,A1,A2,A3,A4>::_fp4_ops = {
00594     FunctionPointer4<R,A1,A2,A3,A4>::constructor,
00595     FunctionPointer4<R,A1,A2,A3,A4>::copy_constructor,
00596     FunctionPointer4<R,A1,A2,A3,A4>::destructor
00597 };
00598 
00599 typedef FunctionPointer0<void> FunctionPointer;
00600 //typedef FunctionPointer1<void, int> event_callback_t;
00601 
00602 } // namespace mbed
00603 
00604 #endif