Official Sheffield ARMBand micro:bit program

Committer:
MrBedfordVan
Date:
Mon Oct 17 12:41:20 2016 +0000
Revision:
0:b9164b348919
Official Sheffield ARMBand Micro:bit program

Who changed what in which revision?

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