High level Bluetooth Low Energy API and radio abstraction layer
Dependents: BLE_ANCS_SDAPI BLE_temperature BLE_HeartRate BLE_ANCS_SDAPI_IRC ... more
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 12:49:01 by 1.7.2