BLE_API

Committer:
Vincent Coubard
Date:
Wed Sep 14 14:18:00 2016 +0100
Revision:
1208:65474dc93927
Parent:
1183:1589830dbdb7
Sync with 8d97fced5440d78c9557693b6d1632f1ab5d77b7

2016-09-01 08:21:37+01:00: Vincent Coubard
version v2.7.0

Who changed what in which revision?

UserRevisionLine numberNew 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 1146:3fbf341b09dd 58 template <typename ContextType>
vcoubard 1146:3fbf341b09dd 59 class CallChainOfFunctionPointersWithContext : public SafeBool<CallChainOfFunctionPointersWithContext<ContextType> > {
vcoubard 1146:3fbf341b09dd 60 public:
vcoubard 1183:1589830dbdb7 61 /**
vcoubard 1183:1589830dbdb7 62 * The type of each callback in the callchain.
vcoubard 1183:1589830dbdb7 63 */
vcoubard 1146:3fbf341b09dd 64 typedef FunctionPointerWithContext<ContextType> *pFunctionPointerWithContext_t;
vcoubard 1146:3fbf341b09dd 65
vcoubard 1146:3fbf341b09dd 66 public:
vcoubard 1183:1589830dbdb7 67 /**
vcoubard 1183:1589830dbdb7 68 * Create an empty chain.
vcoubard 1146:3fbf341b09dd 69 */
vcoubard 1146:3fbf341b09dd 70 CallChainOfFunctionPointersWithContext() : chainHead(NULL) {
vcoubard 1146:3fbf341b09dd 71 /* empty */
vcoubard 1146:3fbf341b09dd 72 }
vcoubard 1146:3fbf341b09dd 73
vcoubard 1146:3fbf341b09dd 74 virtual ~CallChainOfFunctionPointersWithContext() {
vcoubard 1146:3fbf341b09dd 75 clear();
vcoubard 1146:3fbf341b09dd 76 }
vcoubard 1146:3fbf341b09dd 77
vcoubard 1183:1589830dbdb7 78 /**
vcoubard 1183:1589830dbdb7 79 * Add a function at the front of the chain.
vcoubard 1146:3fbf341b09dd 80 *
vcoubard 1183:1589830dbdb7 81 * @param[in] function
vcoubard 1183:1589830dbdb7 82 * A pointer to a void function.
vcoubard 1146:3fbf341b09dd 83 *
vcoubard 1183:1589830dbdb7 84 * @return The function object created for @p function.
vcoubard 1146:3fbf341b09dd 85 */
vcoubard 1146:3fbf341b09dd 86 pFunctionPointerWithContext_t add(void (*function)(ContextType context)) {
vcoubard 1146:3fbf341b09dd 87 return common_add(new FunctionPointerWithContext<ContextType>(function));
vcoubard 1146:3fbf341b09dd 88 }
vcoubard 1146:3fbf341b09dd 89
vcoubard 1183:1589830dbdb7 90 /**
vcoubard 1183:1589830dbdb7 91 * Add a function at the front of the chain.
vcoubard 1146:3fbf341b09dd 92 *
vcoubard 1183:1589830dbdb7 93 * @param[in] tptr
vcoubard 1183:1589830dbdb7 94 * Pointer to the object to call the member function on.
vcoubard 1183:1589830dbdb7 95 * @param[in] mptr
vcoubard 1183:1589830dbdb7 96 * Pointer to the member function to be called.
vcoubard 1146:3fbf341b09dd 97 *
vcoubard 1183:1589830dbdb7 98 * @return The function object created for @p tptr and @p mptr.
vcoubard 1146:3fbf341b09dd 99 */
vcoubard 1146:3fbf341b09dd 100 template<typename T>
vcoubard 1146:3fbf341b09dd 101 pFunctionPointerWithContext_t add(T *tptr, void (T::*mptr)(ContextType context)) {
vcoubard 1146:3fbf341b09dd 102 return common_add(new FunctionPointerWithContext<ContextType>(tptr, mptr));
vcoubard 1146:3fbf341b09dd 103 }
vcoubard 1146:3fbf341b09dd 104
vcoubard 1183:1589830dbdb7 105 /**
vcoubard 1183:1589830dbdb7 106 * Add a function at the front of the chain.
vcoubard 1146:3fbf341b09dd 107 *
vcoubard 1183:1589830dbdb7 108 * @param[in] func
vcoubard 1183:1589830dbdb7 109 * The FunctionPointerWithContext to add.
vcoubard 1183:1589830dbdb7 110 *
vcoubard 1183:1589830dbdb7 111 * @return The function object created for @p func.
vcoubard 1146:3fbf341b09dd 112 */
vcoubard 1146:3fbf341b09dd 113 pFunctionPointerWithContext_t add(const FunctionPointerWithContext<ContextType>& func) {
vcoubard 1146:3fbf341b09dd 114 return common_add(new FunctionPointerWithContext<ContextType>(func));
vcoubard 1146:3fbf341b09dd 115 }
vcoubard 1146:3fbf341b09dd 116
vcoubard 1183:1589830dbdb7 117 /**
vcoubard 1183:1589830dbdb7 118 * Detach a function pointer from a callchain.
vcoubard 1183:1589830dbdb7 119 *
vcoubard 1183:1589830dbdb7 120 * @param[in] toDetach
vcoubard 1183:1589830dbdb7 121 * FunctionPointerWithContext to detach from this callchain.
vcoubard 1183:1589830dbdb7 122 *
vcoubard 1183:1589830dbdb7 123 * @return true if a function pointer has been detached and false otherwise.
vcoubard 1183:1589830dbdb7 124 *
vcoubard 1183:1589830dbdb7 125 * @note It is safe to remove a function pointer while the chain is
vcoubard 1183:1589830dbdb7 126 * traversed by call(ContextType).
vcoubard 1183:1589830dbdb7 127 */
vcoubard 1183:1589830dbdb7 128 bool detach(const FunctionPointerWithContext<ContextType>& toDetach) {
vcoubard 1146:3fbf341b09dd 129 pFunctionPointerWithContext_t current = chainHead;
vcoubard 1146:3fbf341b09dd 130 pFunctionPointerWithContext_t previous = NULL;
vcoubard 1146:3fbf341b09dd 131
vcoubard 1146:3fbf341b09dd 132 while (current) {
vcoubard 1183:1589830dbdb7 133 if(*current == toDetach) {
vcoubard 1146:3fbf341b09dd 134 if(previous == NULL) {
vcoubard 1183:1589830dbdb7 135 if(currentCalled == current) {
vcoubard 1146:3fbf341b09dd 136 currentCalled = NULL;
vcoubard 1146:3fbf341b09dd 137 }
vcoubard 1146:3fbf341b09dd 138 chainHead = current->getNext();
vcoubard 1146:3fbf341b09dd 139 } else {
vcoubard 1183:1589830dbdb7 140 if(currentCalled == current) {
vcoubard 1146:3fbf341b09dd 141 currentCalled = previous;
vcoubard 1146:3fbf341b09dd 142 }
vcoubard 1146:3fbf341b09dd 143 previous->chainAsNext(current->getNext());
vcoubard 1146:3fbf341b09dd 144 }
vcoubard 1146:3fbf341b09dd 145 delete current;
vcoubard 1146:3fbf341b09dd 146 return true;
vcoubard 1146:3fbf341b09dd 147 }
vcoubard 1146:3fbf341b09dd 148
vcoubard 1146:3fbf341b09dd 149 previous = current;
vcoubard 1146:3fbf341b09dd 150 current = current->getNext();
vcoubard 1146:3fbf341b09dd 151 }
vcoubard 1146:3fbf341b09dd 152
vcoubard 1146:3fbf341b09dd 153 return false;
vcoubard 1146:3fbf341b09dd 154 }
vcoubard 1146:3fbf341b09dd 155
vcoubard 1183:1589830dbdb7 156 /**
vcoubard 1183:1589830dbdb7 157 * Clear the call chain (remove all functions in the chain).
vcoubard 1146:3fbf341b09dd 158 */
vcoubard 1146:3fbf341b09dd 159 void clear(void) {
vcoubard 1146:3fbf341b09dd 160 pFunctionPointerWithContext_t fptr = chainHead;
vcoubard 1146:3fbf341b09dd 161 while (fptr) {
vcoubard 1146:3fbf341b09dd 162 pFunctionPointerWithContext_t deadPtr = fptr;
vcoubard 1146:3fbf341b09dd 163 fptr = deadPtr->getNext();
vcoubard 1146:3fbf341b09dd 164 delete deadPtr;
vcoubard 1146:3fbf341b09dd 165 }
vcoubard 1146:3fbf341b09dd 166
vcoubard 1146:3fbf341b09dd 167 chainHead = NULL;
vcoubard 1146:3fbf341b09dd 168 }
vcoubard 1146:3fbf341b09dd 169
vcoubard 1183:1589830dbdb7 170 /**
vcoubard 1183:1589830dbdb7 171 * Check whether the callchain contains any callbacks.
vcoubard 1183:1589830dbdb7 172 *
vcoubard 1183:1589830dbdb7 173 * @return true if the callchain is not empty and false otherwise.
vcoubard 1183:1589830dbdb7 174 */
vcoubard 1146:3fbf341b09dd 175 bool hasCallbacksAttached(void) const {
vcoubard 1146:3fbf341b09dd 176 return (chainHead != NULL);
vcoubard 1146:3fbf341b09dd 177 }
vcoubard 1146:3fbf341b09dd 178
vcoubard 1183:1589830dbdb7 179 /**
vcoubard 1183:1589830dbdb7 180 * Call all the functions in the chain in sequence.
vcoubard 1146:3fbf341b09dd 181 */
vcoubard 1146:3fbf341b09dd 182 void call(ContextType context) {
vcoubard 1146:3fbf341b09dd 183 ((const CallChainOfFunctionPointersWithContext*) this)->call(context);
vcoubard 1146:3fbf341b09dd 184 }
vcoubard 1146:3fbf341b09dd 185
vcoubard 1146:3fbf341b09dd 186 /**
vcoubard 1183:1589830dbdb7 187 * Same as call() above, but const.
vcoubard 1146:3fbf341b09dd 188 */
vcoubard 1146:3fbf341b09dd 189 void call(ContextType context) const {
vcoubard 1146:3fbf341b09dd 190 currentCalled = chainHead;
vcoubard 1146:3fbf341b09dd 191
vcoubard 1183:1589830dbdb7 192 while(currentCalled) {
vcoubard 1146:3fbf341b09dd 193 currentCalled->call(context);
vcoubard 1146:3fbf341b09dd 194 // if this was the head and the call removed the head
vcoubard 1183:1589830dbdb7 195 if(currentCalled == NULL) {
vcoubard 1146:3fbf341b09dd 196 currentCalled = chainHead;
vcoubard 1146:3fbf341b09dd 197 } else {
vcoubard 1146:3fbf341b09dd 198 currentCalled = currentCalled->getNext();
vcoubard 1146:3fbf341b09dd 199 }
vcoubard 1146:3fbf341b09dd 200 }
vcoubard 1146:3fbf341b09dd 201 }
vcoubard 1146:3fbf341b09dd 202
vcoubard 1146:3fbf341b09dd 203 /**
vcoubard 1183:1589830dbdb7 204 * Same as call(), but with function call operator.
vcoubard 1183:1589830dbdb7 205 * @code
vcoubard 1183:1589830dbdb7 206 *
vcoubard 1146:3fbf341b09dd 207 * void first(bool);
vcoubard 1146:3fbf341b09dd 208 * void second(bool);
vcoubard 1183:1589830dbdb7 209 *
vcoubard 1146:3fbf341b09dd 210 * CallChainOfFunctionPointerWithContext<bool> foo;
vcoubard 1183:1589830dbdb7 211 *
vcoubard 1146:3fbf341b09dd 212 * foo.attach(first);
vcoubard 1146:3fbf341b09dd 213 * foo.attach(second);
vcoubard 1183:1589830dbdb7 214 *
vcoubard 1146:3fbf341b09dd 215 * // call the callchain like a function
vcoubard 1146:3fbf341b09dd 216 * foo(true);
vcoubard 1183:1589830dbdb7 217 *
vcoubard 1183:1589830dbdb7 218 * @endcode
vcoubard 1146:3fbf341b09dd 219 */
vcoubard 1146:3fbf341b09dd 220 void operator()(ContextType context) const {
vcoubard 1146:3fbf341b09dd 221 call(context);
vcoubard 1146:3fbf341b09dd 222 }
vcoubard 1146:3fbf341b09dd 223
vcoubard 1146:3fbf341b09dd 224 /**
vcoubard 1183:1589830dbdb7 225 * Bool conversion operation.
vcoubard 1183:1589830dbdb7 226 *
vcoubard 1183:1589830dbdb7 227 * @return true if the callchain is not empty and false otherwise.
vcoubard 1146:3fbf341b09dd 228 */
vcoubard 1146:3fbf341b09dd 229 bool toBool() const {
vcoubard 1146:3fbf341b09dd 230 return chainHead != NULL;
vcoubard 1146:3fbf341b09dd 231 }
vcoubard 1146:3fbf341b09dd 232
vcoubard 1146:3fbf341b09dd 233 private:
vcoubard 1183:1589830dbdb7 234 /**
vcoubard 1183:1589830dbdb7 235 * Add a callback to the head of the callchain.
vcoubard 1183:1589830dbdb7 236 *
vcoubard 1183:1589830dbdb7 237 * @return A pointer to the head of the callchain.
vcoubard 1183:1589830dbdb7 238 */
vcoubard 1146:3fbf341b09dd 239 pFunctionPointerWithContext_t common_add(pFunctionPointerWithContext_t pf) {
vcoubard 1146:3fbf341b09dd 240 if (chainHead == NULL) {
vcoubard 1146:3fbf341b09dd 241 chainHead = pf;
vcoubard 1146:3fbf341b09dd 242 } else {
vcoubard 1146:3fbf341b09dd 243 pf->chainAsNext(chainHead);
vcoubard 1146:3fbf341b09dd 244 chainHead = pf;
vcoubard 1146:3fbf341b09dd 245 }
vcoubard 1146:3fbf341b09dd 246
vcoubard 1146:3fbf341b09dd 247 return chainHead;
vcoubard 1146:3fbf341b09dd 248 }
vcoubard 1146:3fbf341b09dd 249
vcoubard 1146:3fbf341b09dd 250 private:
vcoubard 1183:1589830dbdb7 251 /**
vcoubard 1183:1589830dbdb7 252 * A pointer to the first callback in the callchain or NULL if the callchain is empty.
vcoubard 1183:1589830dbdb7 253 */
vcoubard 1146:3fbf341b09dd 254 pFunctionPointerWithContext_t chainHead;
vcoubard 1183:1589830dbdb7 255
vcoubard 1183:1589830dbdb7 256 /**
vcoubard 1183:1589830dbdb7 257 * Iterator during a function call, this has to be mutable because the call function is const.
vcoubard 1183:1589830dbdb7 258 *
vcoubard 1183:1589830dbdb7 259 * @note Mutable is the correct behaviour here, the iterator never leaks outside the object.
vcoubard 1183:1589830dbdb7 260 * so the object can still be seen as logically const even if it is modified.
vcoubard 1183:1589830dbdb7 261 */
vcoubard 1146:3fbf341b09dd 262 mutable pFunctionPointerWithContext_t currentCalled;
vcoubard 1146:3fbf341b09dd 263
vcoubard 1146:3fbf341b09dd 264
vcoubard 1146:3fbf341b09dd 265 /* Disallow copy constructor and assignment operators. */
vcoubard 1146:3fbf341b09dd 266 private:
vcoubard 1146:3fbf341b09dd 267 CallChainOfFunctionPointersWithContext(const CallChainOfFunctionPointersWithContext &);
vcoubard 1146:3fbf341b09dd 268 CallChainOfFunctionPointersWithContext & operator = (const CallChainOfFunctionPointersWithContext &);
vcoubard 1146:3fbf341b09dd 269 };
vcoubard 1146:3fbf341b09dd 270
rgrover1 710:b2e1a2660ec2 271 #endif