just a fork
Fork of BLE_API by
ble/CallChainOfFunctionPointersWithContext.h@1179:4ab722f8dca0, 2016-04-06 (annotated)
- Committer:
- vcoubard
- Date:
- Wed Apr 06 19:15:30 2016 +0100
- Revision:
- 1179:4ab722f8dca0
- Parent:
- 1177:f9060dc8c5ab
- Child:
- 1183:1589830dbdb7
Synchronized with git rev ca632aaf
Author: Andres Amaya Garcia
Update Gap state after advertising times out
The BLE API was not updating the Gap internal state when the advertising stops
because of a user timeout. This commit fixes the issue by updating the internal
state structure in Gap just before the registered callbacks are notified of the
advertising timeout.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
vcoubard | 1146:3fbf341b09dd | 1 | /* mbed Microcontroller Library |
vcoubard | 1146:3fbf341b09dd | 2 | * Copyright (c) 2006-2013 ARM Limited |
vcoubard | 1146:3fbf341b09dd | 3 | * |
vcoubard | 1146:3fbf341b09dd | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
vcoubard | 1146:3fbf341b09dd | 5 | * you may not use this file except in compliance with the License. |
vcoubard | 1146:3fbf341b09dd | 6 | * You may obtain a copy of the License at |
vcoubard | 1146:3fbf341b09dd | 7 | * |
vcoubard | 1146:3fbf341b09dd | 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
vcoubard | 1146:3fbf341b09dd | 9 | * |
vcoubard | 1146:3fbf341b09dd | 10 | * Unless required by applicable law or agreed to in writing, software |
vcoubard | 1146:3fbf341b09dd | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
vcoubard | 1146:3fbf341b09dd | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
vcoubard | 1146:3fbf341b09dd | 13 | * See the License for the specific language governing permissions and |
vcoubard | 1146:3fbf341b09dd | 14 | * limitations under the License. |
vcoubard | 1146:3fbf341b09dd | 15 | */ |
vcoubard | 1146:3fbf341b09dd | 16 | #ifndef MBED_CALLCHAIN_OF_FUNCTION_POINTERS_WITH_CONTEXT_H |
vcoubard | 1146:3fbf341b09dd | 17 | #define MBED_CALLCHAIN_OF_FUNCTION_POINTERS_WITH_CONTEXT_H |
vcoubard | 1146:3fbf341b09dd | 18 | |
vcoubard | 1146:3fbf341b09dd | 19 | #include <string.h> |
vcoubard | 1146:3fbf341b09dd | 20 | #include "FunctionPointerWithContext.h" |
vcoubard | 1146:3fbf341b09dd | 21 | #include "SafeBool.h" |
vcoubard | 1146:3fbf341b09dd | 22 | |
vcoubard | 1146:3fbf341b09dd | 23 | |
vcoubard | 1146:3fbf341b09dd | 24 | /** Group one or more functions in an instance of a CallChainOfFunctionPointersWithContext, then call them in |
vcoubard | 1146:3fbf341b09dd | 25 | * sequence using CallChainOfFunctionPointersWithContext::call(). Used mostly by the interrupt chaining code, |
vcoubard | 1146:3fbf341b09dd | 26 | * but can be used for other purposes. |
vcoubard | 1146:3fbf341b09dd | 27 | * |
vcoubard | 1146:3fbf341b09dd | 28 | * Example: |
vcoubard | 1146:3fbf341b09dd | 29 | * @code |
vcoubard | 1146:3fbf341b09dd | 30 | * |
vcoubard | 1146:3fbf341b09dd | 31 | * CallChainOfFunctionPointersWithContext<void *> chain; |
vcoubard | 1146:3fbf341b09dd | 32 | * |
vcoubard | 1146:3fbf341b09dd | 33 | * void first(void *context) { |
vcoubard | 1146:3fbf341b09dd | 34 | * printf("'first' function.\n"); |
vcoubard | 1146:3fbf341b09dd | 35 | * } |
vcoubard | 1146:3fbf341b09dd | 36 | * |
vcoubard | 1146:3fbf341b09dd | 37 | * void second(void *context) { |
vcoubard | 1146:3fbf341b09dd | 38 | * printf("'second' function.\n"); |
vcoubard | 1146:3fbf341b09dd | 39 | * } |
vcoubard | 1146:3fbf341b09dd | 40 | * |
vcoubard | 1146:3fbf341b09dd | 41 | * class Test { |
vcoubard | 1146:3fbf341b09dd | 42 | * public: |
vcoubard | 1146:3fbf341b09dd | 43 | * void f(void *context) { |
vcoubard | 1146:3fbf341b09dd | 44 | * printf("A::f (class member).\n"); |
vcoubard | 1146:3fbf341b09dd | 45 | * } |
vcoubard | 1146:3fbf341b09dd | 46 | * }; |
vcoubard | 1146:3fbf341b09dd | 47 | * |
vcoubard | 1146:3fbf341b09dd | 48 | * int main() { |
vcoubard | 1146:3fbf341b09dd | 49 | * Test test; |
vcoubard | 1146:3fbf341b09dd | 50 | * |
vcoubard | 1146:3fbf341b09dd | 51 | * chain.add(second); |
vcoubard | 1146:3fbf341b09dd | 52 | * chain.add_front(first); |
vcoubard | 1146:3fbf341b09dd | 53 | * chain.add(&test, &Test::f); |
vcoubard | 1146:3fbf341b09dd | 54 | * chain.call(); |
vcoubard | 1146:3fbf341b09dd | 55 | * } |
vcoubard | 1146:3fbf341b09dd | 56 | * @endcode |
vcoubard | 1146:3fbf341b09dd | 57 | */ |
vcoubard | 1179:4ab722f8dca0 | 58 | |
vcoubard | 1146:3fbf341b09dd | 59 | template <typename ContextType> |
vcoubard | 1146:3fbf341b09dd | 60 | class CallChainOfFunctionPointersWithContext : public SafeBool<CallChainOfFunctionPointersWithContext<ContextType> > { |
vcoubard | 1146:3fbf341b09dd | 61 | public: |
vcoubard | 1146:3fbf341b09dd | 62 | typedef FunctionPointerWithContext<ContextType> *pFunctionPointerWithContext_t; |
vcoubard | 1146:3fbf341b09dd | 63 | |
vcoubard | 1146:3fbf341b09dd | 64 | public: |
vcoubard | 1179:4ab722f8dca0 | 65 | /** Create an empty chain. |
vcoubard | 1179:4ab722f8dca0 | 66 | * |
vcoubard | 1179:4ab722f8dca0 | 67 | * @param size (optional) Initial size of the chain. |
vcoubard | 1146:3fbf341b09dd | 68 | */ |
vcoubard | 1146:3fbf341b09dd | 69 | CallChainOfFunctionPointersWithContext() : chainHead(NULL) { |
vcoubard | 1146:3fbf341b09dd | 70 | /* empty */ |
vcoubard | 1146:3fbf341b09dd | 71 | } |
vcoubard | 1146:3fbf341b09dd | 72 | |
vcoubard | 1146:3fbf341b09dd | 73 | virtual ~CallChainOfFunctionPointersWithContext() { |
vcoubard | 1146:3fbf341b09dd | 74 | clear(); |
vcoubard | 1146:3fbf341b09dd | 75 | } |
vcoubard | 1146:3fbf341b09dd | 76 | |
vcoubard | 1179:4ab722f8dca0 | 77 | /** Add a function at the front of the chain. |
vcoubard | 1146:3fbf341b09dd | 78 | * |
vcoubard | 1179:4ab722f8dca0 | 79 | * @param function A pointer to a void function. |
vcoubard | 1146:3fbf341b09dd | 80 | * |
vcoubard | 1179:4ab722f8dca0 | 81 | * @returns |
vcoubard | 1179:4ab722f8dca0 | 82 | * The function object created for 'function'. |
vcoubard | 1146:3fbf341b09dd | 83 | */ |
vcoubard | 1146:3fbf341b09dd | 84 | pFunctionPointerWithContext_t add(void (*function)(ContextType context)) { |
vcoubard | 1146:3fbf341b09dd | 85 | return common_add(new FunctionPointerWithContext<ContextType>(function)); |
vcoubard | 1146:3fbf341b09dd | 86 | } |
vcoubard | 1146:3fbf341b09dd | 87 | |
vcoubard | 1179:4ab722f8dca0 | 88 | /** Add a function at the front of the chain. |
vcoubard | 1146:3fbf341b09dd | 89 | * |
vcoubard | 1179:4ab722f8dca0 | 90 | * @param tptr Pointer to the object to call the member function on. |
vcoubard | 1179:4ab722f8dca0 | 91 | * @param mptr Pointer to the member function to be called. |
vcoubard | 1146:3fbf341b09dd | 92 | * |
vcoubard | 1179:4ab722f8dca0 | 93 | * @returns |
vcoubard | 1179:4ab722f8dca0 | 94 | * The function object created for 'tptr' and 'mptr'. |
vcoubard | 1146:3fbf341b09dd | 95 | */ |
vcoubard | 1146:3fbf341b09dd | 96 | template<typename T> |
vcoubard | 1146:3fbf341b09dd | 97 | pFunctionPointerWithContext_t add(T *tptr, void (T::*mptr)(ContextType context)) { |
vcoubard | 1146:3fbf341b09dd | 98 | return common_add(new FunctionPointerWithContext<ContextType>(tptr, mptr)); |
vcoubard | 1146:3fbf341b09dd | 99 | } |
vcoubard | 1146:3fbf341b09dd | 100 | |
vcoubard | 1179:4ab722f8dca0 | 101 | /** Add a function at the front of the chain. |
vcoubard | 1146:3fbf341b09dd | 102 | * |
vcoubard | 1179:4ab722f8dca0 | 103 | * @param func The FunctionPointerWithContext to add. |
vcoubard | 1146:3fbf341b09dd | 104 | */ |
vcoubard | 1146:3fbf341b09dd | 105 | pFunctionPointerWithContext_t add(const FunctionPointerWithContext<ContextType>& func) { |
vcoubard | 1146:3fbf341b09dd | 106 | return common_add(new FunctionPointerWithContext<ContextType>(func)); |
vcoubard | 1146:3fbf341b09dd | 107 | } |
vcoubard | 1146:3fbf341b09dd | 108 | |
vcoubard | 1179:4ab722f8dca0 | 109 | /** |
vcoubard | 1179:4ab722f8dca0 | 110 | * Detach a function pointer from a callchain |
vcoubard | 1179:4ab722f8dca0 | 111 | * |
vcoubard | 1179:4ab722f8dca0 | 112 | * @oaram toDetach FunctionPointerWithContext to detach from this callchain |
vcoubard | 1179:4ab722f8dca0 | 113 | * |
vcoubard | 1179:4ab722f8dca0 | 114 | * @return true if a function pointer has been detached and false otherwise |
vcoubard | 1179:4ab722f8dca0 | 115 | */ |
vcoubard | 1179:4ab722f8dca0 | 116 | bool detach(const FunctionPointerWithContext<ContextType>& toDetach) { |
vcoubard | 1146:3fbf341b09dd | 117 | pFunctionPointerWithContext_t current = chainHead; |
vcoubard | 1146:3fbf341b09dd | 118 | pFunctionPointerWithContext_t previous = NULL; |
vcoubard | 1146:3fbf341b09dd | 119 | |
vcoubard | 1146:3fbf341b09dd | 120 | while (current) { |
vcoubard | 1179:4ab722f8dca0 | 121 | if(*current == toDetach) { |
vcoubard | 1146:3fbf341b09dd | 122 | if(previous == NULL) { |
vcoubard | 1179:4ab722f8dca0 | 123 | if(currentCalled == current) { |
vcoubard | 1146:3fbf341b09dd | 124 | currentCalled = NULL; |
vcoubard | 1146:3fbf341b09dd | 125 | } |
vcoubard | 1146:3fbf341b09dd | 126 | chainHead = current->getNext(); |
vcoubard | 1146:3fbf341b09dd | 127 | } else { |
vcoubard | 1179:4ab722f8dca0 | 128 | if(currentCalled == current) { |
vcoubard | 1146:3fbf341b09dd | 129 | currentCalled = previous; |
vcoubard | 1146:3fbf341b09dd | 130 | } |
vcoubard | 1146:3fbf341b09dd | 131 | previous->chainAsNext(current->getNext()); |
vcoubard | 1146:3fbf341b09dd | 132 | } |
vcoubard | 1146:3fbf341b09dd | 133 | delete current; |
vcoubard | 1146:3fbf341b09dd | 134 | return true; |
vcoubard | 1146:3fbf341b09dd | 135 | } |
vcoubard | 1146:3fbf341b09dd | 136 | |
vcoubard | 1146:3fbf341b09dd | 137 | previous = current; |
vcoubard | 1146:3fbf341b09dd | 138 | current = current->getNext(); |
vcoubard | 1146:3fbf341b09dd | 139 | } |
vcoubard | 1146:3fbf341b09dd | 140 | |
vcoubard | 1146:3fbf341b09dd | 141 | return false; |
vcoubard | 1146:3fbf341b09dd | 142 | } |
vcoubard | 1146:3fbf341b09dd | 143 | |
vcoubard | 1179:4ab722f8dca0 | 144 | /** Clear the call chain (remove all functions in the chain). |
vcoubard | 1146:3fbf341b09dd | 145 | */ |
vcoubard | 1146:3fbf341b09dd | 146 | void clear(void) { |
vcoubard | 1146:3fbf341b09dd | 147 | pFunctionPointerWithContext_t fptr = chainHead; |
vcoubard | 1146:3fbf341b09dd | 148 | while (fptr) { |
vcoubard | 1146:3fbf341b09dd | 149 | pFunctionPointerWithContext_t deadPtr = fptr; |
vcoubard | 1146:3fbf341b09dd | 150 | fptr = deadPtr->getNext(); |
vcoubard | 1146:3fbf341b09dd | 151 | delete deadPtr; |
vcoubard | 1146:3fbf341b09dd | 152 | } |
vcoubard | 1146:3fbf341b09dd | 153 | |
vcoubard | 1146:3fbf341b09dd | 154 | chainHead = NULL; |
vcoubard | 1146:3fbf341b09dd | 155 | } |
vcoubard | 1146:3fbf341b09dd | 156 | |
vcoubard | 1146:3fbf341b09dd | 157 | bool hasCallbacksAttached(void) const { |
vcoubard | 1146:3fbf341b09dd | 158 | return (chainHead != NULL); |
vcoubard | 1146:3fbf341b09dd | 159 | } |
vcoubard | 1146:3fbf341b09dd | 160 | |
vcoubard | 1179:4ab722f8dca0 | 161 | /** Call all the functions in the chain in sequence |
vcoubard | 1146:3fbf341b09dd | 162 | */ |
vcoubard | 1146:3fbf341b09dd | 163 | void call(ContextType context) { |
vcoubard | 1146:3fbf341b09dd | 164 | ((const CallChainOfFunctionPointersWithContext*) this)->call(context); |
vcoubard | 1146:3fbf341b09dd | 165 | } |
vcoubard | 1146:3fbf341b09dd | 166 | |
vcoubard | 1146:3fbf341b09dd | 167 | /** |
vcoubard | 1179:4ab722f8dca0 | 168 | * @brief same as above but const |
vcoubard | 1146:3fbf341b09dd | 169 | */ |
vcoubard | 1146:3fbf341b09dd | 170 | void call(ContextType context) const { |
vcoubard | 1146:3fbf341b09dd | 171 | currentCalled = chainHead; |
vcoubard | 1146:3fbf341b09dd | 172 | |
vcoubard | 1179:4ab722f8dca0 | 173 | while(currentCalled) { |
vcoubard | 1146:3fbf341b09dd | 174 | currentCalled->call(context); |
vcoubard | 1146:3fbf341b09dd | 175 | // if this was the head and the call removed the head |
vcoubard | 1179:4ab722f8dca0 | 176 | if(currentCalled == NULL) { |
vcoubard | 1146:3fbf341b09dd | 177 | currentCalled = chainHead; |
vcoubard | 1146:3fbf341b09dd | 178 | } else { |
vcoubard | 1146:3fbf341b09dd | 179 | currentCalled = currentCalled->getNext(); |
vcoubard | 1146:3fbf341b09dd | 180 | } |
vcoubard | 1146:3fbf341b09dd | 181 | } |
vcoubard | 1146:3fbf341b09dd | 182 | } |
vcoubard | 1146:3fbf341b09dd | 183 | |
vcoubard | 1146:3fbf341b09dd | 184 | /** |
vcoubard | 1179:4ab722f8dca0 | 185 | * @brief same as above but with function call operator |
vcoubard | 1179:4ab722f8dca0 | 186 | * \code |
vcoubard | 1179:4ab722f8dca0 | 187 | * |
vcoubard | 1146:3fbf341b09dd | 188 | * void first(bool); |
vcoubard | 1146:3fbf341b09dd | 189 | * void second(bool); |
vcoubard | 1179:4ab722f8dca0 | 190 | * |
vcoubard | 1146:3fbf341b09dd | 191 | * CallChainOfFunctionPointerWithContext<bool> foo; |
vcoubard | 1179:4ab722f8dca0 | 192 | * |
vcoubard | 1146:3fbf341b09dd | 193 | * foo.attach(first); |
vcoubard | 1146:3fbf341b09dd | 194 | * foo.attach(second); |
vcoubard | 1179:4ab722f8dca0 | 195 | * |
vcoubard | 1146:3fbf341b09dd | 196 | * // call the callchain like a function |
vcoubard | 1146:3fbf341b09dd | 197 | * foo(true); |
vcoubard | 1179:4ab722f8dca0 | 198 | * |
vcoubard | 1179:4ab722f8dca0 | 199 | * \endcode |
vcoubard | 1146:3fbf341b09dd | 200 | */ |
vcoubard | 1146:3fbf341b09dd | 201 | void operator()(ContextType context) const { |
vcoubard | 1146:3fbf341b09dd | 202 | call(context); |
vcoubard | 1146:3fbf341b09dd | 203 | } |
vcoubard | 1146:3fbf341b09dd | 204 | |
vcoubard | 1146:3fbf341b09dd | 205 | /** |
vcoubard | 1179:4ab722f8dca0 | 206 | * @brief bool conversion operation |
vcoubard | 1146:3fbf341b09dd | 207 | */ |
vcoubard | 1146:3fbf341b09dd | 208 | bool toBool() const { |
vcoubard | 1146:3fbf341b09dd | 209 | return chainHead != NULL; |
vcoubard | 1146:3fbf341b09dd | 210 | } |
vcoubard | 1146:3fbf341b09dd | 211 | |
vcoubard | 1146:3fbf341b09dd | 212 | private: |
vcoubard | 1146:3fbf341b09dd | 213 | pFunctionPointerWithContext_t common_add(pFunctionPointerWithContext_t pf) { |
vcoubard | 1146:3fbf341b09dd | 214 | if (chainHead == NULL) { |
vcoubard | 1146:3fbf341b09dd | 215 | chainHead = pf; |
vcoubard | 1146:3fbf341b09dd | 216 | } else { |
vcoubard | 1146:3fbf341b09dd | 217 | pf->chainAsNext(chainHead); |
vcoubard | 1146:3fbf341b09dd | 218 | chainHead = pf; |
vcoubard | 1146:3fbf341b09dd | 219 | } |
vcoubard | 1146:3fbf341b09dd | 220 | |
vcoubard | 1146:3fbf341b09dd | 221 | return chainHead; |
vcoubard | 1146:3fbf341b09dd | 222 | } |
vcoubard | 1146:3fbf341b09dd | 223 | |
vcoubard | 1146:3fbf341b09dd | 224 | private: |
vcoubard | 1146:3fbf341b09dd | 225 | pFunctionPointerWithContext_t chainHead; |
vcoubard | 1179:4ab722f8dca0 | 226 | // iterator during a function call, this has to be mutable because the call function is const. |
vcoubard | 1179:4ab722f8dca0 | 227 | // Note: mutable is the correct behaviour here, the iterator never leak outside the object. |
vcoubard | 1179:4ab722f8dca0 | 228 | // So the object can still be seen as logically const even if it change its internal state |
vcoubard | 1146:3fbf341b09dd | 229 | mutable pFunctionPointerWithContext_t currentCalled; |
vcoubard | 1146:3fbf341b09dd | 230 | |
vcoubard | 1146:3fbf341b09dd | 231 | |
vcoubard | 1146:3fbf341b09dd | 232 | /* Disallow copy constructor and assignment operators. */ |
vcoubard | 1146:3fbf341b09dd | 233 | private: |
vcoubard | 1146:3fbf341b09dd | 234 | CallChainOfFunctionPointersWithContext(const CallChainOfFunctionPointersWithContext &); |
vcoubard | 1146:3fbf341b09dd | 235 | CallChainOfFunctionPointersWithContext & operator = (const CallChainOfFunctionPointersWithContext &); |
vcoubard | 1146:3fbf341b09dd | 236 | }; |
vcoubard | 1146:3fbf341b09dd | 237 | |
rgrover1 | 710:b2e1a2660ec2 | 238 | #endif |