Holla back

Fork of BLE_API by Bluetooth Low Energy

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers FunctionPointerWithContext.h Source File

FunctionPointerWithContext.h

00001 /* mbed Microcontroller Library
00002  * Copyright (c) 2006-2013 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 
00017 #ifndef MBED_FUNCTIONPOINTER_WITH_CONTEXT_H
00018 #define MBED_FUNCTIONPOINTER_WITH_CONTEXT_H
00019 
00020 #include <string.h>
00021 
00022 namespace mbed {
00023 
00024 /** A class for storing and calling a pointer to a static or member void function
00025  *  which takes a context.
00026  */
00027 template <typename ContextType>
00028 class FunctionPointerWithContext {
00029 public:
00030     typedef FunctionPointerWithContext<ContextType> *pFunctionPointerWithContext_t;
00031     typedef void (*pvoidfcontext_t)(ContextType context);
00032 
00033     /** Create a FunctionPointerWithContext, attaching a static function
00034      *
00035      *  @param function The void static function to attach (default is none)
00036      */
00037     FunctionPointerWithContext(void (*function)(ContextType context) = NULL) :
00038         _function(NULL), _object(NULL), _member(), _membercaller(NULL), _next(NULL) {
00039         attach(function);
00040     }
00041 
00042     /** Create a FunctionPointerWithContext, attaching a member function
00043      *
00044      *  @param object The object pointer to invoke the member function on (i.e. the this pointer)
00045      *  @param function The address of the void member function to attach
00046      */
00047     template<typename T>
00048     FunctionPointerWithContext(T *object, void (T::*member)(ContextType context)) :
00049         _function(NULL), _object(NULL), _member(), _membercaller(NULL), _next(NULL) {
00050         attach(object, member);
00051     }
00052 
00053     /** Attach a static function
00054      *
00055      *  @param function The void static function to attach (default is none)
00056      */
00057     void attach(void (*function)(ContextType context) = NULL) {
00058         _function = function;
00059     }
00060 
00061     /** Attach a member function
00062      *
00063      *  @param object The object pointer to invoke the member function on (i.e. the this pointer)
00064      *  @param function The address of the void member function to attach
00065      */
00066     template<typename T>
00067     void attach(T *object, void (T::*member)(ContextType context)) {
00068         _object = static_cast<void *>(object);
00069         memcpy(_member, (char *)&member, sizeof(member));
00070         _membercaller = &FunctionPointerWithContext::membercaller<T>;
00071     }
00072 
00073     /** Call the attached static or member function; and if there are chained
00074      *  FunctionPointers their callbacks are invoked as well.
00075      *  @Note: all chained callbacks stack up; so hopefully there won't be too
00076      *  many FunctionPointers in a chain. */
00077     void call(ContextType context) {
00078         if (_function) {
00079             _function(context);
00080         } else if (_object && _membercaller) {
00081             _membercaller(_object, _member, context);
00082         }
00083 
00084         /* Propagate the call to next in the chain. */
00085         if (_next) {
00086             _next->call(context);
00087         }
00088     }
00089 
00090     /**
00091      * Setup an external FunctionPointer as a next in the chain of related
00092      * callbacks. Invoking call() on the head FunctionPointer will invoke all
00093      * chained callbacks.
00094      *
00095      * Refer to 'CallChain' as an alternative.
00096      */
00097     void chainAsNext(pFunctionPointerWithContext_t next) {
00098         _next = next;
00099     }
00100 
00101     pFunctionPointerWithContext_t getNext(void) const {
00102         return _next;
00103     }
00104 
00105     pvoidfcontext_t get_function() const {
00106         return (pvoidfcontext_t)_function;
00107     }
00108 
00109 private:
00110     template<typename T>
00111     static void membercaller(void *object, char *member, ContextType context) {
00112         T *o = static_cast<T *>(object);
00113         void (T::*m)(ContextType);
00114         memcpy((char *)&m, member, sizeof(m));
00115         (o->*m)(context);
00116     }
00117 
00118     void (*_function)(ContextType context);             /**< static function pointer - NULL if none attached */
00119     void *_object;                                      /**< object this pointer - NULL if none attached */
00120     char _member[16];                                   /**< raw member function pointer storage - converted back by
00121                                                          *   registered _membercaller */
00122     void (*_membercaller)(void *, char *, ContextType); /**< registered membercaller function to convert back and call
00123                                                          *   _member on _object passing the context. */
00124     pFunctionPointerWithContext_t _next;                /**< Optional link to make a chain out of functionPointers; this
00125                                                          *   allows chaining function pointers without requiring
00126                                                          *   external memory to manage the chain. Also refer to
00127                                                          *   'CallChain' as an alternative. */
00128 };
00129 } // namespace mbed
00130 
00131 #endif // ifndef MBED_FUNCTIONPOINTER_WITH_CONTEXT_H