Marco Zecchini
/
Example_RTOS
Rtos API example
Embed:
(wiki syntax)
Show/hide line numbers
FunctionPointerWithContext.h
Go to the documentation of this file.
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 /** 00024 * @file 00025 * @addtogroup ble 00026 * @{ 00027 * @addtogroup common 00028 * @{ 00029 */ 00030 00031 /** 00032 * Function like object adapter over freestanding and member functions. 00033 * 00034 * Freestanding and member functions are two distinct types in C++. One is 00035 * not convertible into the other, and the call syntax between the two is 00036 * different even if conceptually they are similar: Both primitives can be 00037 * copied, called and produce a result. 00038 * 00039 * To solve incompatibilities, this class adapts freestanding and member functions 00040 * to a common interface. The interface chosen is similar to the freestanding 00041 * function pointers interface: 00042 * - Copyable. 00043 * - Nullable. 00044 * - Callable. 00045 * 00046 * This class also offers a mechanism to chain other instances to it. When an 00047 * instance is called, all the instances being part of the chain are called. 00048 * 00049 * @important freestanding or member function adapted must accept a single 00050 * argument, and this argument is a pointer to ContextType. Adapted 00051 * primitives do not return anything. 00052 * 00053 * @tparam ContextType Type of the argument pointee. 00054 */ 00055 template <typename ContextType> 00056 class FunctionPointerWithContext : public SafeBool<FunctionPointerWithContext<ContextType> > { 00057 public: 00058 typedef FunctionPointerWithContext<ContextType> *pFunctionPointerWithContext_t; 00059 typedef const FunctionPointerWithContext<ContextType> *cpFunctionPointerWithContext_t; 00060 typedef void (*pvoidfcontext_t)(ContextType context); 00061 00062 /** 00063 * Create a FunctionPointerWithContext from a pointer to a freestanding 00064 * function. 00065 * 00066 * @param[in] function The freestanding function to attach. 00067 */ 00068 FunctionPointerWithContext(void (*function)(ContextType context) = NULL) : 00069 _memberFunctionAndPointer(), _caller(NULL), _next(NULL) 00070 { 00071 attach(function); 00072 } 00073 00074 /** 00075 * Create a FunctionPointerWithContext from a pointer to a member function 00076 * and the instance which is used to call it. 00077 * 00078 * @param[in] object Pointer to the instance which is used to invoke @p 00079 * member. 00080 * @param[in] Pointer to the member function to adapt. 00081 */ 00082 template<typename T> 00083 FunctionPointerWithContext(T *object, void (T::*member)(ContextType context)) : 00084 _memberFunctionAndPointer(), _caller(NULL), _next(NULL) 00085 { 00086 attach(object, member); 00087 } 00088 00089 /** 00090 * Copy construction. 00091 * 00092 * @param[in] that The FunctionPointerWithContext instance used to create 00093 * this. 00094 */ 00095 FunctionPointerWithContext(const FunctionPointerWithContext &that) : 00096 _memberFunctionAndPointer(that._memberFunctionAndPointer), 00097 _caller(that._caller), _next(NULL) { 00098 } 00099 00100 /** 00101 * Copy assignment. 00102 * 00103 * @param[in] that The FunctionPointerWithContext instance copied into this. 00104 */ 00105 FunctionPointerWithContext &operator=(const FunctionPointerWithContext &that) 00106 { 00107 _memberFunctionAndPointer = that._memberFunctionAndPointer; 00108 _caller = that._caller; 00109 _next = NULL; 00110 return *this; 00111 } 00112 00113 /** 00114 * Adapt a freestanding function. 00115 * 00116 * Previous content adapted is discarded while @p function replaces it. 00117 * 00118 * @note This function is equivalent to a call to the copy assignment 00119 * operator. 00120 * 00121 * @param[in] function The freestanding function to attach. 00122 */ 00123 void attach(void (*function)(ContextType context) = NULL) 00124 { 00125 _function = function; 00126 _caller = functioncaller; 00127 } 00128 00129 /** 00130 * Adapt a pointer to member function and the instance to use to call it. 00131 * 00132 * Previous content adapted is discarded while the adaptation 00133 * of the pair @p object and @p member replaces it. 00134 * 00135 * @note This function is equivalent to a call to the copy assignment 00136 * operator. 00137 * 00138 * @param[in] object Pointer to the instance is used to invoke @p member. 00139 * @param[in] function Pointer to the member function to adapt. 00140 */ 00141 template<typename T> 00142 void attach(T *object, void (T::*member)(ContextType context)) 00143 { 00144 _memberFunctionAndPointer._object = static_cast<void *>(object); 00145 memcpy( 00146 _memberFunctionAndPointer._memberFunction, 00147 (char*) &member, 00148 sizeof(member) 00149 ); 00150 _caller = &FunctionPointerWithContext::membercaller<T>; 00151 } 00152 00153 /** 00154 * Call the adapted function and functions chained to the instance. 00155 * 00156 * @param[in] context parameter to pass to chain of adapted functions. 00157 */ 00158 void call(ContextType context) const 00159 { 00160 _caller(this, context); 00161 } 00162 00163 /** 00164 * Call the adapted function and functions chained to the instance. 00165 * 00166 * @param[in] context parameter to pass to chain of adapted functions. 00167 */ 00168 void call(ContextType context) 00169 { 00170 ((const FunctionPointerWithContext*) this)->call(context); 00171 } 00172 00173 /** 00174 * Call the adapted function and functions chained to the instance. 00175 * 00176 * @param[in] context parameter to pass to chain of adapted functions. 00177 */ 00178 void operator()(ContextType context) const 00179 { 00180 call(context); 00181 } 00182 00183 typedef void (FunctionPointerWithContext::*bool_type)() const; 00184 00185 /** 00186 * Indicate if a callable object is being adapted. 00187 * 00188 * @note implementation of safe bool operator. 00189 * 00190 * @return true if the content of the instance can be invoked and false 00191 * otherwise. 00192 */ 00193 bool toBool() const 00194 { 00195 return (_function || _memberFunctionAndPointer._object); 00196 } 00197 00198 /** 00199 * Set a FunctionPointer instance as the next element in the chain of 00200 * callable objects. 00201 * 00202 * @note Invoking call() on the head FunctionPointer invokes all 00203 * chained callbacks. 00204 * 00205 * @note Refer to CallChainOfFunctionPointerWithContext as an alternative. 00206 * 00207 * @param next The instance to set as the next element in the chain of 00208 * callable objects. 00209 */ 00210 void chainAsNext(pFunctionPointerWithContext_t next) 00211 { 00212 _next = next; 00213 } 00214 00215 /** 00216 * Access the next element in the call chain. 00217 * 00218 * If there is no next element in the chain, this function returns NULL. 00219 * 00220 * @return A pointer to the next FunctionPointerWithContext instance in the 00221 * chain. 00222 */ 00223 pFunctionPointerWithContext_t getNext(void) const 00224 { 00225 return _next; 00226 } 00227 00228 /** 00229 * Access the next element in the call chain. 00230 * 00231 * If there is no next element in the chain, this function returns NULL. 00232 * 00233 * @return A pointer to the next FunctionPointerWithContext instance in the 00234 * chain. 00235 */ 00236 pvoidfcontext_t get_function() const 00237 { 00238 return (pvoidfcontext_t)_function; 00239 } 00240 00241 /** 00242 * Equal to operator between two FunctionPointerWithContext instances. 00243 * 00244 * @param[in] lhs Left hand side of the expression. 00245 * @param[in] rhs Right hand side of the expression. 00246 * 00247 * @return true if lhs and rhs adapt the same object and false otherwise. 00248 */ 00249 friend bool operator==( 00250 const FunctionPointerWithContext &lhs, 00251 const FunctionPointerWithContext &rhs 00252 ) { 00253 return rhs._caller == lhs._caller && 00254 memcmp( 00255 &rhs._memberFunctionAndPointer, 00256 &lhs._memberFunctionAndPointer, 00257 sizeof(rhs._memberFunctionAndPointer) 00258 ) == 0; 00259 } 00260 00261 private: 00262 template<typename T> 00263 static void membercaller(cpFunctionPointerWithContext_t self, ContextType context) { 00264 if (self->_memberFunctionAndPointer._object) { 00265 T *o = static_cast<T *>(self->_memberFunctionAndPointer._object); 00266 void (T::*m)(ContextType); 00267 memcpy((char*) &m, self->_memberFunctionAndPointer._memberFunction, sizeof(m)); 00268 (o->*m)(context); 00269 } 00270 } 00271 00272 static void functioncaller(cpFunctionPointerWithContext_t self, ContextType context) { 00273 if (self->_function) { 00274 self->_function(context); 00275 } 00276 } 00277 00278 struct MemberFunctionAndPtr { 00279 /* 00280 * Forward declaration of a class and a member function to this class. 00281 * Because the compiler doesn't know anything about the forwarded member 00282 * function, it always uses the biggest size and the biggest alignment 00283 * that a member function can take for objects of type UndefinedMemberFunction. 00284 */ 00285 class UndefinedClass; 00286 typedef void (UndefinedClass::*UndefinedMemberFunction)(ContextType); 00287 00288 void* _object; 00289 union { 00290 char _memberFunction[sizeof(UndefinedMemberFunction)]; 00291 UndefinedMemberFunction _alignment; 00292 }; 00293 }; 00294 00295 union { 00296 pvoidfcontext_t _function; /**< Static function pointer - NULL if none attached */ 00297 /** 00298 * object this pointer and pointer to member - 00299 * _memberFunctionAndPointer._object will be NULL if none attached 00300 */ 00301 mutable MemberFunctionAndPtr _memberFunctionAndPointer; 00302 }; 00303 00304 void (*_caller)(const FunctionPointerWithContext*, ContextType); 00305 00306 pFunctionPointerWithContext_t _next; /**< Optional link to make a chain out of functionPointers. This 00307 * allows chaining function pointers without requiring 00308 * external memory to manage the chain. Refer to 00309 * 'CallChain' as an alternative. */ 00310 }; 00311 00312 /** 00313 * Factory of adapted member function pointers. 00314 * 00315 * This factory eliminates the need to invoke the qualified constructor of 00316 * FunctionPointerWithContext by using automatic type deduction of function 00317 * templates. 00318 * 00319 * @code 00320 * 00321 * struct ReadHandler { 00322 * void on_data_read(const GattReadCallbackParams*); 00323 * }; 00324 * 00325 * ReadHandler read_handler; 00326 * 00327 * GattClient& client; 00328 * 00329 * client.onDataRead( 00330 * makeFunctionPointer(&read_handler, &ReadHandler::on_data_read) 00331 * ); 00332 * 00333 * // instead of 00334 * 00335 * client.onDataRead( 00336 * FunctionPointerWithContext<const GattReadCallbackParams*>( 00337 * &read_handler, 00338 * &ReadHandler::on_data_read 00339 * ) 00340 * ); 00341 * @endcode 00342 * 00343 * 00344 * @param[in] object Instance to bound with @p member. 00345 * @param member The member being adapted. 00346 * 00347 * @return Adaptation of the parameters in a FunctionPointerWithContext instance. 00348 */ 00349 template<typename T, typename ContextType> 00350 FunctionPointerWithContext<ContextType> makeFunctionPointer( 00351 T *object, 00352 void (T::*member)(ContextType context) 00353 ) { 00354 return FunctionPointerWithContext<ContextType>(object, member); 00355 } 00356 00357 /** 00358 * @} 00359 * @} 00360 */ 00361 00362 #endif // ifndef MBED_FUNCTIONPOINTER_WITH_CONTEXT_H
Generated on Sun Jul 17 2022 08:25:23 by 1.7.2