Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of LinkNode-Test by
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 Tue Jul 12 2022 16:00:20 by
