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
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 00059 template <typename ContextType> 00060 class CallChainOfFunctionPointersWithContext : public SafeBool<CallChainOfFunctionPointersWithContext<ContextType> > { 00061 public: 00062 typedef FunctionPointerWithContext<ContextType> *pFunctionPointerWithContext_t; 00063 00064 public: 00065 /** Create an empty chain. 00066 * 00067 * @param size (optional) Initial size of the chain. 00068 */ 00069 CallChainOfFunctionPointersWithContext() : chainHead(NULL) { 00070 /* empty */ 00071 } 00072 00073 virtual ~CallChainOfFunctionPointersWithContext() { 00074 clear(); 00075 } 00076 00077 /** Add a function at the front of the chain. 00078 * 00079 * @param function A pointer to a void function. 00080 * 00081 * @returns 00082 * The function object created for 'function'. 00083 */ 00084 pFunctionPointerWithContext_t add(void (*function)(ContextType context)) { 00085 return common_add(new FunctionPointerWithContext<ContextType>(function)); 00086 } 00087 00088 /** Add a function at the front of the chain. 00089 * 00090 * @param tptr Pointer to the object to call the member function on. 00091 * @param mptr Pointer to the member function to be called. 00092 * 00093 * @returns 00094 * The function object created for 'tptr' and 'mptr'. 00095 */ 00096 template<typename T> 00097 pFunctionPointerWithContext_t add(T *tptr, void (T::*mptr)(ContextType context)) { 00098 return common_add(new FunctionPointerWithContext<ContextType>(tptr, mptr)); 00099 } 00100 00101 /** Add a function at the front of the chain. 00102 * 00103 * @param func The FunctionPointerWithContext to add. 00104 */ 00105 pFunctionPointerWithContext_t add(const FunctionPointerWithContext<ContextType>& func) { 00106 return common_add(new FunctionPointerWithContext<ContextType>(func)); 00107 } 00108 00109 /** 00110 * Detach a function pointer from a callchain 00111 * 00112 * @oaram toDetach FunctionPointerWithContext to detach from this callchain 00113 * 00114 * @return true if a function pointer has been detached and false otherwise 00115 */ 00116 bool detach(const FunctionPointerWithContext<ContextType>& toDetach) { 00117 pFunctionPointerWithContext_t current = chainHead; 00118 pFunctionPointerWithContext_t previous = NULL; 00119 00120 while (current) { 00121 if(*current == toDetach) { 00122 if(previous == NULL) { 00123 if(currentCalled == current) { 00124 currentCalled = NULL; 00125 } 00126 chainHead = current->getNext(); 00127 } else { 00128 if(currentCalled == current) { 00129 currentCalled = previous; 00130 } 00131 previous->chainAsNext(current->getNext()); 00132 } 00133 delete current; 00134 return true; 00135 } 00136 00137 previous = current; 00138 current = current->getNext(); 00139 } 00140 00141 return false; 00142 } 00143 00144 /** Clear the call chain (remove all functions in the chain). 00145 */ 00146 void clear(void) { 00147 pFunctionPointerWithContext_t fptr = chainHead; 00148 while (fptr) { 00149 pFunctionPointerWithContext_t deadPtr = fptr; 00150 fptr = deadPtr->getNext(); 00151 delete deadPtr; 00152 } 00153 00154 chainHead = NULL; 00155 } 00156 00157 bool hasCallbacksAttached(void) const { 00158 return (chainHead != NULL); 00159 } 00160 00161 /** Call all the functions in the chain in sequence 00162 */ 00163 void call(ContextType context) { 00164 ((const CallChainOfFunctionPointersWithContext*) this)->call(context); 00165 } 00166 00167 /** 00168 * @brief same as above but const 00169 */ 00170 void call(ContextType context) const { 00171 currentCalled = chainHead; 00172 00173 while(currentCalled) { 00174 currentCalled->call(context); 00175 // if this was the head and the call removed the head 00176 if(currentCalled == NULL) { 00177 currentCalled = chainHead; 00178 } else { 00179 currentCalled = currentCalled->getNext(); 00180 } 00181 } 00182 } 00183 00184 /** 00185 * @brief same as above but with function call operator 00186 * \code 00187 * 00188 * void first(bool); 00189 * void second(bool); 00190 * 00191 * CallChainOfFunctionPointerWithContext<bool> foo; 00192 * 00193 * foo.attach(first); 00194 * foo.attach(second); 00195 * 00196 * // call the callchain like a function 00197 * foo(true); 00198 * 00199 * \endcode 00200 */ 00201 void operator()(ContextType context) const { 00202 call(context); 00203 } 00204 00205 /** 00206 * @brief bool conversion operation 00207 */ 00208 bool toBool() const { 00209 return chainHead != NULL; 00210 } 00211 00212 private: 00213 pFunctionPointerWithContext_t common_add(pFunctionPointerWithContext_t pf) { 00214 if (chainHead == NULL) { 00215 chainHead = pf; 00216 } else { 00217 pf->chainAsNext(chainHead); 00218 chainHead = pf; 00219 } 00220 00221 return chainHead; 00222 } 00223 00224 private: 00225 pFunctionPointerWithContext_t chainHead; 00226 // iterator during a function call, this has to be mutable because the call function is const. 00227 // Note: mutable is the correct behaviour here, the iterator never leak outside the object. 00228 // So the object can still be seen as logically const even if it change its internal state 00229 mutable pFunctionPointerWithContext_t currentCalled; 00230 00231 00232 /* Disallow copy constructor and assignment operators. */ 00233 private: 00234 CallChainOfFunctionPointersWithContext(const CallChainOfFunctionPointersWithContext &); 00235 CallChainOfFunctionPointersWithContext & operator = (const CallChainOfFunctionPointersWithContext &); 00236 }; 00237 00238 #endif
Generated on Tue Jul 12 2022 16:00:19 by
