Marco Zecchini
/
Example_RTOS
Rtos API example
Embed:
(wiki syntax)
Show/hide line numbers
CallChainOfFunctionPointersWithContext.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 #ifndef MBED_CALLCHAIN_OF_FUNCTION_POINTERS_WITH_CONTEXT_H 00017 #define MBED_CALLCHAIN_OF_FUNCTION_POINTERS_WITH_CONTEXT_H 00018 00019 #include <string.h> 00020 #include "FunctionPointerWithContext.h " 00021 #include "SafeBool.h " 00022 00023 /** 00024 * @addtogroup ble 00025 * @{ 00026 * @addtogroup common 00027 * @{ 00028 */ 00029 00030 /** 00031 * Function like object hosting a list of FunctionPointerWithContext. 00032 * 00033 * Upon call, each FunctionPointerWithContext instance present in the object will 00034 * be called in sequence with the initial parameters. 00035 * 00036 * It can be seen as a variation of the observer pattern this object being the 00037 * observable, instances of the FunctionPointerWithContext being the observable 00038 * and the notify/update operation being the function call. 00039 * 00040 * Example: 00041 * @code 00042 * 00043 * CallChainOfFunctionPointersWithContext<void *> chain; 00044 * 00045 * void first(void *context) { 00046 * printf("'first' function.\n"); 00047 * } 00048 * 00049 * void second(void *context) { 00050 * printf("'second' function.\n"); 00051 * } 00052 * 00053 * class Test { 00054 * public: 00055 * void f(void *context) { 00056 * printf("A::f (class member).\n"); 00057 * } 00058 * }; 00059 * 00060 * int main() { 00061 * Test test; 00062 * 00063 * chain.add(second); 00064 * chain.add_front(first); 00065 * chain.add(&test, &Test::f); 00066 * 00067 * // will print: 00068 * // 'second' function. 00069 * // 'first' function. 00070 * // A::f (class member). 00071 * chain.call(); 00072 * } 00073 * @endcode 00074 * 00075 * @note memory allocation is used to add new function like objects into the 00076 * call chain. 00077 * 00078 * @tparam ContextType Type of the parameter accepted by the callbacks hosted 00079 * in the object. 00080 */ 00081 template <typename ContextType> 00082 class CallChainOfFunctionPointersWithContext : 00083 public SafeBool<CallChainOfFunctionPointersWithContext<ContextType> > { 00084 public: 00085 /** 00086 * Alias of the FunctionPointerWithContext type this object can store. 00087 */ 00088 typedef FunctionPointerWithContext<ContextType> *pFunctionPointerWithContext_t; 00089 00090 public: 00091 /** 00092 * Create an empty callchain. 00093 */ 00094 CallChainOfFunctionPointersWithContext() : chainHead(NULL) { } 00095 00096 /** 00097 * Destruction of the callchain. 00098 */ 00099 virtual ~CallChainOfFunctionPointersWithContext() 00100 { 00101 clear(); 00102 } 00103 00104 /** 00105 * Add a function pointer at the front of the chain. 00106 * 00107 * @param[in] function A pointer to a void function. 00108 * 00109 * @return The FunctionPointerWithContext object created from @p function. 00110 */ 00111 pFunctionPointerWithContext_t add(void (*function)(ContextType context)) 00112 { 00113 return common_add(new FunctionPointerWithContext<ContextType>(function)); 00114 } 00115 00116 /** 00117 * Add a member function bound to its instance at the front of the chain. 00118 * 00119 * @param[in] tptr Pointer to the object to call the member function on. 00120 * @param[in] mptr Pointer to the member function to be called. 00121 * 00122 * @return The FunctionPointerWithContext object created from @p tptr and 00123 * @p mptr. 00124 */ 00125 template<typename T> 00126 pFunctionPointerWithContext_t add(T *tptr, void (T::*mptr)(ContextType context)) 00127 { 00128 return common_add(new FunctionPointerWithContext<ContextType>(tptr, mptr)); 00129 } 00130 00131 /** 00132 * Add a FunctionPointerWithContext at the front of the chain. 00133 * 00134 * @param[in] func The FunctionPointerWithContext to add. 00135 * 00136 * @return The function object created for @p func. 00137 */ 00138 pFunctionPointerWithContext_t add(const FunctionPointerWithContext<ContextType> &func) 00139 { 00140 return common_add(new FunctionPointerWithContext<ContextType>(func)); 00141 } 00142 00143 /** 00144 * Detach a function pointer from a callchain. 00145 * 00146 * @param[in] toDetach FunctionPointerWithContext instance to detach from 00147 * this callchain. 00148 * 00149 * @return true if a function pointer has been detached and false otherwise. 00150 * 00151 * @note It is safe to remove a function pointer while 00152 * call(ContextType) is traversing the chain. 00153 */ 00154 bool detach(const FunctionPointerWithContext<ContextType> &toDetach) 00155 { 00156 pFunctionPointerWithContext_t current = chainHead; 00157 pFunctionPointerWithContext_t previous = NULL; 00158 00159 while (current) { 00160 if(*current == toDetach) { 00161 if(previous == NULL) { 00162 if(currentCalled == current) { 00163 currentCalled = NULL; 00164 } 00165 chainHead = current->getNext(); 00166 } else { 00167 if(currentCalled == current) { 00168 currentCalled = previous; 00169 } 00170 previous->chainAsNext(current->getNext()); 00171 } 00172 delete current; 00173 return true; 00174 } 00175 00176 previous = current; 00177 current = current->getNext(); 00178 } 00179 00180 return false; 00181 } 00182 00183 /** 00184 * Remove all functions registered in the chain. 00185 */ 00186 void clear(void) 00187 { 00188 pFunctionPointerWithContext_t fptr = chainHead; 00189 while (fptr) { 00190 pFunctionPointerWithContext_t deadPtr = fptr; 00191 fptr = deadPtr->getNext(); 00192 delete deadPtr; 00193 } 00194 00195 chainHead = NULL; 00196 } 00197 00198 /** 00199 * Check whether the callchain contains any callbacks. 00200 * 00201 * @return true if the callchain is not empty and false otherwise. 00202 */ 00203 bool hasCallbacksAttached(void) const 00204 { 00205 return (chainHead != NULL); 00206 } 00207 00208 /** 00209 * Call sequentially each member of the chain. 00210 * 00211 * @param[in] context Parameter to pass to the functions called. 00212 */ 00213 void call(ContextType context) 00214 { 00215 ((const CallChainOfFunctionPointersWithContext*) this)->call(context); 00216 } 00217 00218 /** 00219 * Call sequentially each member of the chain. 00220 * 00221 * @param[in] context Parameter to pass to the functions called. 00222 */ 00223 void call(ContextType context) const 00224 { 00225 currentCalled = chainHead; 00226 00227 while(currentCalled) { 00228 currentCalled->call(context); 00229 // if this was the head and the call removed the head 00230 if(currentCalled == NULL) { 00231 currentCalled = chainHead; 00232 } else { 00233 currentCalled = currentCalled->getNext(); 00234 } 00235 } 00236 } 00237 00238 /** 00239 * Call sequentially each member of the chain. 00240 * 00241 * @param[in] context Parameter to pass to the functions called. 00242 * 00243 * @code 00244 * 00245 * void first(bool); 00246 * void second(bool); 00247 * 00248 * CallChainOfFunctionPointerWithContext<bool> foo; 00249 * 00250 * foo.attach(first); 00251 * foo.attach(second); 00252 * 00253 * // call the callchain like a function 00254 * foo(true); 00255 * 00256 * @endcode 00257 */ 00258 void operator()(ContextType context) const 00259 { 00260 call(context); 00261 } 00262 00263 /** 00264 * Test if the callchain is empty or not. 00265 * 00266 * @return true if the callchain is not empty and false otherwise. 00267 * 00268 * @note used by SafeBool to offer a safe boolean conversion. 00269 * 00270 * @code 00271 * CallChainOfFunctionPointersWithContext<void *> chain; 00272 * 00273 * if (!chain) { 00274 * // Do something if the chain is empty. 00275 * } 00276 * 00277 * if (chain) { 00278 * // Do something if the chain is not empty. 00279 * } 00280 * @endcode 00281 * 00282 */ 00283 bool toBool() const 00284 { 00285 return chainHead != NULL; 00286 } 00287 00288 private: 00289 /** 00290 * Add a callback to the head of the callchain. 00291 * 00292 * @return A pointer to the head of the callchain. 00293 */ 00294 pFunctionPointerWithContext_t common_add(pFunctionPointerWithContext_t pf) 00295 { 00296 if (chainHead == NULL) { 00297 chainHead = pf; 00298 } else { 00299 pf->chainAsNext(chainHead); 00300 chainHead = pf; 00301 } 00302 00303 return chainHead; 00304 } 00305 00306 private: 00307 /** 00308 * Pointer to the first callback of the callchain or NULL if the callchain 00309 * is empty. 00310 */ 00311 pFunctionPointerWithContext_t chainHead; 00312 00313 /** 00314 * Pointer to the function being called. 00315 * 00316 * It is used to maintain the data structure integrity if a function is 00317 * removed during the call() operation. 00318 * 00319 * @note It has to be mutable to accomodate the const version of call(). The 00320 * iterator doesn't leak outside the object; therefore, it remains seen as 00321 * const from an external standpoint. 00322 */ 00323 mutable pFunctionPointerWithContext_t currentCalled; 00324 00325 00326 /* Disallow copy constructor and assignment operators. */ 00327 private: 00328 CallChainOfFunctionPointersWithContext( 00329 const CallChainOfFunctionPointersWithContext& 00330 ); 00331 CallChainOfFunctionPointersWithContext &operator=( 00332 const CallChainOfFunctionPointersWithContext& 00333 ); 00334 }; 00335 00336 /** 00337 * @} 00338 * @} 00339 */ 00340 00341 #endif
Generated on Sun Jul 17 2022 08:25:20 by 1.7.2