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 /** Group one or more functions in an instance of a CallChainOfFunctionPointersWithContext, then call them in 00025 * sequence using CallChainOfFunctionPointersWithContext::call(). Used mostly by the interrupt chaining code, 00026 * but can be used for other purposes. 00027 * 00028 * Example: 00029 * @code 00030 * 00031 * CallChainOfFunctionPointersWithContext<void *> chain; 00032 * 00033 * void first(void *context) { 00034 * printf("'first' function.\n"); 00035 * } 00036 * 00037 * void second(void *context) { 00038 * printf("'second' function.\n"); 00039 * } 00040 * 00041 * class Test { 00042 * public: 00043 * void f(void *context) { 00044 * printf("A::f (class member).\n"); 00045 * } 00046 * }; 00047 * 00048 * int main() { 00049 * Test test; 00050 * 00051 * chain.add(second); 00052 * chain.add_front(first); 00053 * chain.add(&test, &Test::f); 00054 * chain.call(); 00055 * } 00056 * @endcode 00057 */ 00058 template <typename ContextType> 00059 class CallChainOfFunctionPointersWithContext : public SafeBool<CallChainOfFunctionPointersWithContext<ContextType> > { 00060 public: 00061 /** 00062 * The type of each callback in the callchain. 00063 */ 00064 typedef FunctionPointerWithContext<ContextType> *pFunctionPointerWithContext_t; 00065 00066 public: 00067 /** 00068 * Create an empty chain. 00069 */ 00070 CallChainOfFunctionPointersWithContext() : chainHead(NULL) { 00071 /* empty */ 00072 } 00073 00074 virtual ~CallChainOfFunctionPointersWithContext() { 00075 clear(); 00076 } 00077 00078 /** 00079 * Add a function at the front of the chain. 00080 * 00081 * @param[in] function 00082 * A pointer to a void function. 00083 * 00084 * @return The function object created for @p function. 00085 */ 00086 pFunctionPointerWithContext_t add(void (*function)(ContextType context)) { 00087 return common_add(new FunctionPointerWithContext<ContextType>(function)); 00088 } 00089 00090 /** 00091 * Add a function at the front of the chain. 00092 * 00093 * @param[in] tptr 00094 * Pointer to the object to call the member function on. 00095 * @param[in] mptr 00096 * Pointer to the member function to be called. 00097 * 00098 * @return The function object created for @p tptr and @p mptr. 00099 */ 00100 template<typename T> 00101 pFunctionPointerWithContext_t add(T *tptr, void (T::*mptr)(ContextType context)) { 00102 return common_add(new FunctionPointerWithContext<ContextType>(tptr, mptr)); 00103 } 00104 00105 /** 00106 * Add a function at the front of the chain. 00107 * 00108 * @param[in] func 00109 * The FunctionPointerWithContext to add. 00110 * 00111 * @return The function object created for @p func. 00112 */ 00113 pFunctionPointerWithContext_t add(const FunctionPointerWithContext<ContextType>& func) { 00114 return common_add(new FunctionPointerWithContext<ContextType>(func)); 00115 } 00116 00117 /** 00118 * Detach a function pointer from a callchain. 00119 * 00120 * @param[in] toDetach 00121 * FunctionPointerWithContext to detach from this callchain. 00122 * 00123 * @return true if a function pointer has been detached and false otherwise. 00124 * 00125 * @note It is safe to remove a function pointer while the chain is 00126 * traversed by call(ContextType). 00127 */ 00128 bool detach(const FunctionPointerWithContext<ContextType>& toDetach) { 00129 pFunctionPointerWithContext_t current = chainHead; 00130 pFunctionPointerWithContext_t previous = NULL; 00131 00132 while (current) { 00133 if(*current == toDetach) { 00134 if(previous == NULL) { 00135 if(currentCalled == current) { 00136 currentCalled = NULL; 00137 } 00138 chainHead = current->getNext(); 00139 } else { 00140 if(currentCalled == current) { 00141 currentCalled = previous; 00142 } 00143 previous->chainAsNext(current->getNext()); 00144 } 00145 delete current; 00146 return true; 00147 } 00148 00149 previous = current; 00150 current = current->getNext(); 00151 } 00152 00153 return false; 00154 } 00155 00156 /** 00157 * Clear the call chain (remove all functions in the chain). 00158 */ 00159 void clear(void) { 00160 pFunctionPointerWithContext_t fptr = chainHead; 00161 while (fptr) { 00162 pFunctionPointerWithContext_t deadPtr = fptr; 00163 fptr = deadPtr->getNext(); 00164 delete deadPtr; 00165 } 00166 00167 chainHead = NULL; 00168 } 00169 00170 /** 00171 * Check whether the callchain contains any callbacks. 00172 * 00173 * @return true if the callchain is not empty and false otherwise. 00174 */ 00175 bool hasCallbacksAttached(void) const { 00176 return (chainHead != NULL); 00177 } 00178 00179 /** 00180 * Call all the functions in the chain in sequence. 00181 */ 00182 void call(ContextType context) { 00183 ((const CallChainOfFunctionPointersWithContext*) this)->call(context); 00184 } 00185 00186 /** 00187 * Same as call() above, but const. 00188 */ 00189 void call(ContextType context) const { 00190 currentCalled = chainHead; 00191 00192 while(currentCalled) { 00193 currentCalled->call(context); 00194 // if this was the head and the call removed the head 00195 if(currentCalled == NULL) { 00196 currentCalled = chainHead; 00197 } else { 00198 currentCalled = currentCalled->getNext(); 00199 } 00200 } 00201 } 00202 00203 /** 00204 * Same as call(), but with function call operator. 00205 * @code 00206 * 00207 * void first(bool); 00208 * void second(bool); 00209 * 00210 * CallChainOfFunctionPointerWithContext<bool> foo; 00211 * 00212 * foo.attach(first); 00213 * foo.attach(second); 00214 * 00215 * // call the callchain like a function 00216 * foo(true); 00217 * 00218 * @endcode 00219 */ 00220 void operator()(ContextType context) const { 00221 call(context); 00222 } 00223 00224 /** 00225 * Bool conversion operation. 00226 * 00227 * @return true if the callchain is not empty and false otherwise. 00228 */ 00229 bool toBool() const { 00230 return chainHead != NULL; 00231 } 00232 00233 private: 00234 /** 00235 * Add a callback to the head of the callchain. 00236 * 00237 * @return A pointer to the head of the callchain. 00238 */ 00239 pFunctionPointerWithContext_t common_add(pFunctionPointerWithContext_t pf) { 00240 if (chainHead == NULL) { 00241 chainHead = pf; 00242 } else { 00243 pf->chainAsNext(chainHead); 00244 chainHead = pf; 00245 } 00246 00247 return chainHead; 00248 } 00249 00250 private: 00251 /** 00252 * A pointer to the first callback in the callchain or NULL if the callchain is empty. 00253 */ 00254 pFunctionPointerWithContext_t chainHead; 00255 00256 /** 00257 * Iterator during a function call, this has to be mutable because the call function is const. 00258 * 00259 * @note Mutable is the correct behaviour here, the iterator never leaks outside the object. 00260 * so the object can still be seen as logically const even if it is modified. 00261 */ 00262 mutable pFunctionPointerWithContext_t currentCalled; 00263 00264 00265 /* Disallow copy constructor and assignment operators. */ 00266 private: 00267 CallChainOfFunctionPointersWithContext(const CallChainOfFunctionPointersWithContext &); 00268 CallChainOfFunctionPointersWithContext & operator = (const CallChainOfFunctionPointersWithContext &); 00269 }; 00270 00271 #endif
Generated on Tue Jul 12 2022 20:03:14 by
