Bike service

Fork of BLE_API by Bluetooth Low Energy

Committer:
vcoubard
Date:
Wed Apr 06 19:14:34 2016 +0100
Revision:
1156:e28c7aac64ab
Parent:
1148:79a44226e47a
Child:
1157:e1ea38b576c6
Synchronized with git rev e20c8c58
Author: Vincent Coubard
Merge pull request #163 from ARMmbed/develop

merge version 2.5.0 into master

Who changed what in which revision?

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