adaptation for book and plug demo
Fork of BLE_API by
Embed:
(wiki syntax)
Show/hide line numbers
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 #include "SafeBool.h" 00022 00023 /** A class for storing and calling a pointer to a static or member void function 00024 * that takes a context. 00025 */ 00026 template <typename ContextType> 00027 class FunctionPointerWithContext : public SafeBool<FunctionPointerWithContext<ContextType> > { 00028 public: 00029 typedef FunctionPointerWithContext<ContextType> *pFunctionPointerWithContext_t; 00030 typedef const FunctionPointerWithContext<ContextType> *cpFunctionPointerWithContext_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 _memberFunctionAndPointer(), _caller(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 (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 _memberFunctionAndPointer(), _caller(NULL), _next(NULL) { 00050 attach(object, member); 00051 } 00052 00053 FunctionPointerWithContext(const FunctionPointerWithContext& that) : 00054 _memberFunctionAndPointer(that._memberFunctionAndPointer), _caller(that._caller), _next(NULL) { 00055 } 00056 00057 FunctionPointerWithContext& operator=(const FunctionPointerWithContext& that) { 00058 _memberFunctionAndPointer = that._memberFunctionAndPointer; 00059 _caller = that._caller; 00060 _next = NULL; 00061 return *this; 00062 } 00063 00064 /** Attach a static function. 00065 * 00066 * @param function The void static function to attach (default is none). 00067 */ 00068 void attach(void (*function)(ContextType context) = NULL) { 00069 _function = function; 00070 _caller = functioncaller; 00071 } 00072 00073 /** Attach a member function. 00074 * 00075 * @param object The object pointer to invoke the member function on (the "this" pointer). 00076 * @param function The address of the void member function to attach. 00077 */ 00078 template<typename T> 00079 void attach(T *object, void (T::*member)(ContextType context)) { 00080 _memberFunctionAndPointer._object = static_cast<void *>(object); 00081 memcpy(_memberFunctionAndPointer._memberFunction, (char*) &member, sizeof(member)); 00082 _caller = &FunctionPointerWithContext::membercaller<T>; 00083 } 00084 00085 /** Call the attached static or member function; if there are chained 00086 * FunctionPointers their callbacks are invoked as well. 00087 * @Note: All chained callbacks stack up, so hopefully there won't be too 00088 * many FunctionPointers in a chain. */ 00089 void call(ContextType context) const { 00090 _caller(this, context); 00091 } 00092 00093 /** 00094 * @brief Same as above 00095 */ 00096 void operator()(ContextType context) const { 00097 call(context); 00098 } 00099 00100 /** Same as above, workaround for mbed os FunctionPointer implementation. */ 00101 void call(ContextType context) { 00102 ((const FunctionPointerWithContext*) this)->call(context); 00103 } 00104 00105 typedef void (FunctionPointerWithContext::*bool_type)() const; 00106 00107 /** 00108 * implementation of safe bool operator 00109 */ 00110 bool toBool() const { 00111 return (_function || _memberFunctionAndPointer._object); 00112 } 00113 00114 /** 00115 * Set up an external FunctionPointer as a next in the chain of related 00116 * callbacks. Invoking call() on the head FunctionPointer will invoke all 00117 * chained callbacks. 00118 * 00119 * Refer to 'CallChain' as an alternative. 00120 */ 00121 void chainAsNext(pFunctionPointerWithContext_t next) { 00122 _next = next; 00123 } 00124 00125 pFunctionPointerWithContext_t getNext(void) const { 00126 return _next; 00127 } 00128 00129 pvoidfcontext_t get_function() const { 00130 return (pvoidfcontext_t)_function; 00131 } 00132 00133 friend bool operator==(const FunctionPointerWithContext& lhs, const FunctionPointerWithContext& rhs) { 00134 return rhs._caller == lhs._caller && 00135 memcmp( 00136 &rhs._memberFunctionAndPointer, 00137 &lhs._memberFunctionAndPointer, 00138 sizeof(rhs._memberFunctionAndPointer) 00139 ) == 0; 00140 } 00141 00142 private: 00143 template<typename T> 00144 static void membercaller(cpFunctionPointerWithContext_t self, ContextType context) { 00145 if (self->_memberFunctionAndPointer._object) { 00146 T *o = static_cast<T *>(self->_memberFunctionAndPointer._object); 00147 void (T::*m)(ContextType); 00148 memcpy((char*) &m, self->_memberFunctionAndPointer._memberFunction, sizeof(m)); 00149 (o->*m)(context); 00150 } 00151 } 00152 00153 static void functioncaller(cpFunctionPointerWithContext_t self, ContextType context) { 00154 if (self->_function) { 00155 self->_function(context); 00156 } 00157 } 00158 00159 struct MemberFunctionAndPtr { 00160 /* 00161 * Forward declaration of a class and a member function to this class. 00162 * Because the compiler doesn't know anything about the forwarded member 00163 * function, it will always use the biggest size and the biggest alignment 00164 * that a member function can take for objects of type UndefinedMemberFunction. 00165 */ 00166 class UndefinedClass; 00167 typedef void (UndefinedClass::*UndefinedMemberFunction)(ContextType); 00168 00169 void* _object; 00170 union { 00171 char _memberFunction[sizeof(UndefinedMemberFunction)]; 00172 UndefinedMemberFunction _alignment; 00173 }; 00174 }; 00175 00176 union { 00177 pvoidfcontext_t _function; /**< Static function pointer - NULL if none attached */ 00178 /** 00179 * object this pointer and pointer to member - 00180 * _memberFunctionAndPointer._object will be NULL if none attached 00181 */ 00182 mutable MemberFunctionAndPtr _memberFunctionAndPointer; 00183 }; 00184 00185 void (*_caller)(const FunctionPointerWithContext*, ContextType); 00186 00187 pFunctionPointerWithContext_t _next; /**< Optional link to make a chain out of functionPointers. This 00188 * allows chaining function pointers without requiring 00189 * external memory to manage the chain. Refer to 00190 * 'CallChain' as an alternative. */ 00191 }; 00192 00193 /** 00194 * @brief Create a new FunctionPointerWithContext which bind an instance and a 00195 * a member function together. 00196 * @details This little helper is a just here to eliminate the need to write the 00197 * FunctionPointerWithContext type each time you want to create one by kicking 00198 * automatic type deduction of function templates. With this function, it is easy 00199 * to write only one entry point for functions which expect a FunctionPointer 00200 * in parameters. 00201 * 00202 * @param object to bound with member function 00203 * @param member The member function called 00204 * @return a new FunctionPointerWithContext 00205 */ 00206 template<typename T, typename ContextType> 00207 FunctionPointerWithContext<ContextType> makeFunctionPointer(T *object, void (T::*member)(ContextType context)) 00208 { 00209 return FunctionPointerWithContext<ContextType>(object, member); 00210 } 00211 00212 #endif // ifndef MBED_FUNCTIONPOINTER_WITH_CONTEXT_H
Generated on Wed Jul 13 2022 09:31:10 by 1.7.2