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.
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 Tue Jul 12 2022 14:23:29 by
