Marco Zecchini
/
Example_RTOS
Rtos API example
mbed-os/features/FEATURE_BLE/ble/FunctionPointerWithContext.h@0:9fca2b23d0ba, 2019-02-23 (annotated)
- Committer:
- marcozecchini
- Date:
- Sat Feb 23 12:13:36 2019 +0000
- Revision:
- 0:9fca2b23d0ba
final commit
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
marcozecchini | 0:9fca2b23d0ba | 1 | /* mbed Microcontroller Library |
marcozecchini | 0:9fca2b23d0ba | 2 | * Copyright (c) 2006-2013 ARM Limited |
marcozecchini | 0:9fca2b23d0ba | 3 | * |
marcozecchini | 0:9fca2b23d0ba | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
marcozecchini | 0:9fca2b23d0ba | 5 | * you may not use this file except in compliance with the License. |
marcozecchini | 0:9fca2b23d0ba | 6 | * You may obtain a copy of the License at |
marcozecchini | 0:9fca2b23d0ba | 7 | * |
marcozecchini | 0:9fca2b23d0ba | 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
marcozecchini | 0:9fca2b23d0ba | 9 | * |
marcozecchini | 0:9fca2b23d0ba | 10 | * Unless required by applicable law or agreed to in writing, software |
marcozecchini | 0:9fca2b23d0ba | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
marcozecchini | 0:9fca2b23d0ba | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
marcozecchini | 0:9fca2b23d0ba | 13 | * See the License for the specific language governing permissions and |
marcozecchini | 0:9fca2b23d0ba | 14 | * limitations under the License. |
marcozecchini | 0:9fca2b23d0ba | 15 | */ |
marcozecchini | 0:9fca2b23d0ba | 16 | |
marcozecchini | 0:9fca2b23d0ba | 17 | #ifndef MBED_FUNCTIONPOINTER_WITH_CONTEXT_H |
marcozecchini | 0:9fca2b23d0ba | 18 | #define MBED_FUNCTIONPOINTER_WITH_CONTEXT_H |
marcozecchini | 0:9fca2b23d0ba | 19 | |
marcozecchini | 0:9fca2b23d0ba | 20 | #include <string.h> |
marcozecchini | 0:9fca2b23d0ba | 21 | #include "SafeBool.h" |
marcozecchini | 0:9fca2b23d0ba | 22 | |
marcozecchini | 0:9fca2b23d0ba | 23 | /** |
marcozecchini | 0:9fca2b23d0ba | 24 | * @file |
marcozecchini | 0:9fca2b23d0ba | 25 | * @addtogroup ble |
marcozecchini | 0:9fca2b23d0ba | 26 | * @{ |
marcozecchini | 0:9fca2b23d0ba | 27 | * @addtogroup common |
marcozecchini | 0:9fca2b23d0ba | 28 | * @{ |
marcozecchini | 0:9fca2b23d0ba | 29 | */ |
marcozecchini | 0:9fca2b23d0ba | 30 | |
marcozecchini | 0:9fca2b23d0ba | 31 | /** |
marcozecchini | 0:9fca2b23d0ba | 32 | * Function like object adapter over freestanding and member functions. |
marcozecchini | 0:9fca2b23d0ba | 33 | * |
marcozecchini | 0:9fca2b23d0ba | 34 | * Freestanding and member functions are two distinct types in C++. One is |
marcozecchini | 0:9fca2b23d0ba | 35 | * not convertible into the other, and the call syntax between the two is |
marcozecchini | 0:9fca2b23d0ba | 36 | * different even if conceptually they are similar: Both primitives can be |
marcozecchini | 0:9fca2b23d0ba | 37 | * copied, called and produce a result. |
marcozecchini | 0:9fca2b23d0ba | 38 | * |
marcozecchini | 0:9fca2b23d0ba | 39 | * To solve incompatibilities, this class adapts freestanding and member functions |
marcozecchini | 0:9fca2b23d0ba | 40 | * to a common interface. The interface chosen is similar to the freestanding |
marcozecchini | 0:9fca2b23d0ba | 41 | * function pointers interface: |
marcozecchini | 0:9fca2b23d0ba | 42 | * - Copyable. |
marcozecchini | 0:9fca2b23d0ba | 43 | * - Nullable. |
marcozecchini | 0:9fca2b23d0ba | 44 | * - Callable. |
marcozecchini | 0:9fca2b23d0ba | 45 | * |
marcozecchini | 0:9fca2b23d0ba | 46 | * This class also offers a mechanism to chain other instances to it. When an |
marcozecchini | 0:9fca2b23d0ba | 47 | * instance is called, all the instances being part of the chain are called. |
marcozecchini | 0:9fca2b23d0ba | 48 | * |
marcozecchini | 0:9fca2b23d0ba | 49 | * @important freestanding or member function adapted must accept a single |
marcozecchini | 0:9fca2b23d0ba | 50 | * argument, and this argument is a pointer to ContextType. Adapted |
marcozecchini | 0:9fca2b23d0ba | 51 | * primitives do not return anything. |
marcozecchini | 0:9fca2b23d0ba | 52 | * |
marcozecchini | 0:9fca2b23d0ba | 53 | * @tparam ContextType Type of the argument pointee. |
marcozecchini | 0:9fca2b23d0ba | 54 | */ |
marcozecchini | 0:9fca2b23d0ba | 55 | template <typename ContextType> |
marcozecchini | 0:9fca2b23d0ba | 56 | class FunctionPointerWithContext : public SafeBool<FunctionPointerWithContext<ContextType> > { |
marcozecchini | 0:9fca2b23d0ba | 57 | public: |
marcozecchini | 0:9fca2b23d0ba | 58 | typedef FunctionPointerWithContext<ContextType> *pFunctionPointerWithContext_t; |
marcozecchini | 0:9fca2b23d0ba | 59 | typedef const FunctionPointerWithContext<ContextType> *cpFunctionPointerWithContext_t; |
marcozecchini | 0:9fca2b23d0ba | 60 | typedef void (*pvoidfcontext_t)(ContextType context); |
marcozecchini | 0:9fca2b23d0ba | 61 | |
marcozecchini | 0:9fca2b23d0ba | 62 | /** |
marcozecchini | 0:9fca2b23d0ba | 63 | * Create a FunctionPointerWithContext from a pointer to a freestanding |
marcozecchini | 0:9fca2b23d0ba | 64 | * function. |
marcozecchini | 0:9fca2b23d0ba | 65 | * |
marcozecchini | 0:9fca2b23d0ba | 66 | * @param[in] function The freestanding function to attach. |
marcozecchini | 0:9fca2b23d0ba | 67 | */ |
marcozecchini | 0:9fca2b23d0ba | 68 | FunctionPointerWithContext(void (*function)(ContextType context) = NULL) : |
marcozecchini | 0:9fca2b23d0ba | 69 | _memberFunctionAndPointer(), _caller(NULL), _next(NULL) |
marcozecchini | 0:9fca2b23d0ba | 70 | { |
marcozecchini | 0:9fca2b23d0ba | 71 | attach(function); |
marcozecchini | 0:9fca2b23d0ba | 72 | } |
marcozecchini | 0:9fca2b23d0ba | 73 | |
marcozecchini | 0:9fca2b23d0ba | 74 | /** |
marcozecchini | 0:9fca2b23d0ba | 75 | * Create a FunctionPointerWithContext from a pointer to a member function |
marcozecchini | 0:9fca2b23d0ba | 76 | * and the instance which is used to call it. |
marcozecchini | 0:9fca2b23d0ba | 77 | * |
marcozecchini | 0:9fca2b23d0ba | 78 | * @param[in] object Pointer to the instance which is used to invoke @p |
marcozecchini | 0:9fca2b23d0ba | 79 | * member. |
marcozecchini | 0:9fca2b23d0ba | 80 | * @param[in] Pointer to the member function to adapt. |
marcozecchini | 0:9fca2b23d0ba | 81 | */ |
marcozecchini | 0:9fca2b23d0ba | 82 | template<typename T> |
marcozecchini | 0:9fca2b23d0ba | 83 | FunctionPointerWithContext(T *object, void (T::*member)(ContextType context)) : |
marcozecchini | 0:9fca2b23d0ba | 84 | _memberFunctionAndPointer(), _caller(NULL), _next(NULL) |
marcozecchini | 0:9fca2b23d0ba | 85 | { |
marcozecchini | 0:9fca2b23d0ba | 86 | attach(object, member); |
marcozecchini | 0:9fca2b23d0ba | 87 | } |
marcozecchini | 0:9fca2b23d0ba | 88 | |
marcozecchini | 0:9fca2b23d0ba | 89 | /** |
marcozecchini | 0:9fca2b23d0ba | 90 | * Copy construction. |
marcozecchini | 0:9fca2b23d0ba | 91 | * |
marcozecchini | 0:9fca2b23d0ba | 92 | * @param[in] that The FunctionPointerWithContext instance used to create |
marcozecchini | 0:9fca2b23d0ba | 93 | * this. |
marcozecchini | 0:9fca2b23d0ba | 94 | */ |
marcozecchini | 0:9fca2b23d0ba | 95 | FunctionPointerWithContext(const FunctionPointerWithContext &that) : |
marcozecchini | 0:9fca2b23d0ba | 96 | _memberFunctionAndPointer(that._memberFunctionAndPointer), |
marcozecchini | 0:9fca2b23d0ba | 97 | _caller(that._caller), _next(NULL) { |
marcozecchini | 0:9fca2b23d0ba | 98 | } |
marcozecchini | 0:9fca2b23d0ba | 99 | |
marcozecchini | 0:9fca2b23d0ba | 100 | /** |
marcozecchini | 0:9fca2b23d0ba | 101 | * Copy assignment. |
marcozecchini | 0:9fca2b23d0ba | 102 | * |
marcozecchini | 0:9fca2b23d0ba | 103 | * @param[in] that The FunctionPointerWithContext instance copied into this. |
marcozecchini | 0:9fca2b23d0ba | 104 | */ |
marcozecchini | 0:9fca2b23d0ba | 105 | FunctionPointerWithContext &operator=(const FunctionPointerWithContext &that) |
marcozecchini | 0:9fca2b23d0ba | 106 | { |
marcozecchini | 0:9fca2b23d0ba | 107 | _memberFunctionAndPointer = that._memberFunctionAndPointer; |
marcozecchini | 0:9fca2b23d0ba | 108 | _caller = that._caller; |
marcozecchini | 0:9fca2b23d0ba | 109 | _next = NULL; |
marcozecchini | 0:9fca2b23d0ba | 110 | return *this; |
marcozecchini | 0:9fca2b23d0ba | 111 | } |
marcozecchini | 0:9fca2b23d0ba | 112 | |
marcozecchini | 0:9fca2b23d0ba | 113 | /** |
marcozecchini | 0:9fca2b23d0ba | 114 | * Adapt a freestanding function. |
marcozecchini | 0:9fca2b23d0ba | 115 | * |
marcozecchini | 0:9fca2b23d0ba | 116 | * Previous content adapted is discarded while @p function replaces it. |
marcozecchini | 0:9fca2b23d0ba | 117 | * |
marcozecchini | 0:9fca2b23d0ba | 118 | * @note This function is equivalent to a call to the copy assignment |
marcozecchini | 0:9fca2b23d0ba | 119 | * operator. |
marcozecchini | 0:9fca2b23d0ba | 120 | * |
marcozecchini | 0:9fca2b23d0ba | 121 | * @param[in] function The freestanding function to attach. |
marcozecchini | 0:9fca2b23d0ba | 122 | */ |
marcozecchini | 0:9fca2b23d0ba | 123 | void attach(void (*function)(ContextType context) = NULL) |
marcozecchini | 0:9fca2b23d0ba | 124 | { |
marcozecchini | 0:9fca2b23d0ba | 125 | _function = function; |
marcozecchini | 0:9fca2b23d0ba | 126 | _caller = functioncaller; |
marcozecchini | 0:9fca2b23d0ba | 127 | } |
marcozecchini | 0:9fca2b23d0ba | 128 | |
marcozecchini | 0:9fca2b23d0ba | 129 | /** |
marcozecchini | 0:9fca2b23d0ba | 130 | * Adapt a pointer to member function and the instance to use to call it. |
marcozecchini | 0:9fca2b23d0ba | 131 | * |
marcozecchini | 0:9fca2b23d0ba | 132 | * Previous content adapted is discarded while the adaptation |
marcozecchini | 0:9fca2b23d0ba | 133 | * of the pair @p object and @p member replaces it. |
marcozecchini | 0:9fca2b23d0ba | 134 | * |
marcozecchini | 0:9fca2b23d0ba | 135 | * @note This function is equivalent to a call to the copy assignment |
marcozecchini | 0:9fca2b23d0ba | 136 | * operator. |
marcozecchini | 0:9fca2b23d0ba | 137 | * |
marcozecchini | 0:9fca2b23d0ba | 138 | * @param[in] object Pointer to the instance is used to invoke @p member. |
marcozecchini | 0:9fca2b23d0ba | 139 | * @param[in] function Pointer to the member function to adapt. |
marcozecchini | 0:9fca2b23d0ba | 140 | */ |
marcozecchini | 0:9fca2b23d0ba | 141 | template<typename T> |
marcozecchini | 0:9fca2b23d0ba | 142 | void attach(T *object, void (T::*member)(ContextType context)) |
marcozecchini | 0:9fca2b23d0ba | 143 | { |
marcozecchini | 0:9fca2b23d0ba | 144 | _memberFunctionAndPointer._object = static_cast<void *>(object); |
marcozecchini | 0:9fca2b23d0ba | 145 | memcpy( |
marcozecchini | 0:9fca2b23d0ba | 146 | _memberFunctionAndPointer._memberFunction, |
marcozecchini | 0:9fca2b23d0ba | 147 | (char*) &member, |
marcozecchini | 0:9fca2b23d0ba | 148 | sizeof(member) |
marcozecchini | 0:9fca2b23d0ba | 149 | ); |
marcozecchini | 0:9fca2b23d0ba | 150 | _caller = &FunctionPointerWithContext::membercaller<T>; |
marcozecchini | 0:9fca2b23d0ba | 151 | } |
marcozecchini | 0:9fca2b23d0ba | 152 | |
marcozecchini | 0:9fca2b23d0ba | 153 | /** |
marcozecchini | 0:9fca2b23d0ba | 154 | * Call the adapted function and functions chained to the instance. |
marcozecchini | 0:9fca2b23d0ba | 155 | * |
marcozecchini | 0:9fca2b23d0ba | 156 | * @param[in] context parameter to pass to chain of adapted functions. |
marcozecchini | 0:9fca2b23d0ba | 157 | */ |
marcozecchini | 0:9fca2b23d0ba | 158 | void call(ContextType context) const |
marcozecchini | 0:9fca2b23d0ba | 159 | { |
marcozecchini | 0:9fca2b23d0ba | 160 | _caller(this, context); |
marcozecchini | 0:9fca2b23d0ba | 161 | } |
marcozecchini | 0:9fca2b23d0ba | 162 | |
marcozecchini | 0:9fca2b23d0ba | 163 | /** |
marcozecchini | 0:9fca2b23d0ba | 164 | * Call the adapted function and functions chained to the instance. |
marcozecchini | 0:9fca2b23d0ba | 165 | * |
marcozecchini | 0:9fca2b23d0ba | 166 | * @param[in] context parameter to pass to chain of adapted functions. |
marcozecchini | 0:9fca2b23d0ba | 167 | */ |
marcozecchini | 0:9fca2b23d0ba | 168 | void call(ContextType context) |
marcozecchini | 0:9fca2b23d0ba | 169 | { |
marcozecchini | 0:9fca2b23d0ba | 170 | ((const FunctionPointerWithContext*) this)->call(context); |
marcozecchini | 0:9fca2b23d0ba | 171 | } |
marcozecchini | 0:9fca2b23d0ba | 172 | |
marcozecchini | 0:9fca2b23d0ba | 173 | /** |
marcozecchini | 0:9fca2b23d0ba | 174 | * Call the adapted function and functions chained to the instance. |
marcozecchini | 0:9fca2b23d0ba | 175 | * |
marcozecchini | 0:9fca2b23d0ba | 176 | * @param[in] context parameter to pass to chain of adapted functions. |
marcozecchini | 0:9fca2b23d0ba | 177 | */ |
marcozecchini | 0:9fca2b23d0ba | 178 | void operator()(ContextType context) const |
marcozecchini | 0:9fca2b23d0ba | 179 | { |
marcozecchini | 0:9fca2b23d0ba | 180 | call(context); |
marcozecchini | 0:9fca2b23d0ba | 181 | } |
marcozecchini | 0:9fca2b23d0ba | 182 | |
marcozecchini | 0:9fca2b23d0ba | 183 | typedef void (FunctionPointerWithContext::*bool_type)() const; |
marcozecchini | 0:9fca2b23d0ba | 184 | |
marcozecchini | 0:9fca2b23d0ba | 185 | /** |
marcozecchini | 0:9fca2b23d0ba | 186 | * Indicate if a callable object is being adapted. |
marcozecchini | 0:9fca2b23d0ba | 187 | * |
marcozecchini | 0:9fca2b23d0ba | 188 | * @note implementation of safe bool operator. |
marcozecchini | 0:9fca2b23d0ba | 189 | * |
marcozecchini | 0:9fca2b23d0ba | 190 | * @return true if the content of the instance can be invoked and false |
marcozecchini | 0:9fca2b23d0ba | 191 | * otherwise. |
marcozecchini | 0:9fca2b23d0ba | 192 | */ |
marcozecchini | 0:9fca2b23d0ba | 193 | bool toBool() const |
marcozecchini | 0:9fca2b23d0ba | 194 | { |
marcozecchini | 0:9fca2b23d0ba | 195 | return (_function || _memberFunctionAndPointer._object); |
marcozecchini | 0:9fca2b23d0ba | 196 | } |
marcozecchini | 0:9fca2b23d0ba | 197 | |
marcozecchini | 0:9fca2b23d0ba | 198 | /** |
marcozecchini | 0:9fca2b23d0ba | 199 | * Set a FunctionPointer instance as the next element in the chain of |
marcozecchini | 0:9fca2b23d0ba | 200 | * callable objects. |
marcozecchini | 0:9fca2b23d0ba | 201 | * |
marcozecchini | 0:9fca2b23d0ba | 202 | * @note Invoking call() on the head FunctionPointer invokes all |
marcozecchini | 0:9fca2b23d0ba | 203 | * chained callbacks. |
marcozecchini | 0:9fca2b23d0ba | 204 | * |
marcozecchini | 0:9fca2b23d0ba | 205 | * @note Refer to CallChainOfFunctionPointerWithContext as an alternative. |
marcozecchini | 0:9fca2b23d0ba | 206 | * |
marcozecchini | 0:9fca2b23d0ba | 207 | * @param next The instance to set as the next element in the chain of |
marcozecchini | 0:9fca2b23d0ba | 208 | * callable objects. |
marcozecchini | 0:9fca2b23d0ba | 209 | */ |
marcozecchini | 0:9fca2b23d0ba | 210 | void chainAsNext(pFunctionPointerWithContext_t next) |
marcozecchini | 0:9fca2b23d0ba | 211 | { |
marcozecchini | 0:9fca2b23d0ba | 212 | _next = next; |
marcozecchini | 0:9fca2b23d0ba | 213 | } |
marcozecchini | 0:9fca2b23d0ba | 214 | |
marcozecchini | 0:9fca2b23d0ba | 215 | /** |
marcozecchini | 0:9fca2b23d0ba | 216 | * Access the next element in the call chain. |
marcozecchini | 0:9fca2b23d0ba | 217 | * |
marcozecchini | 0:9fca2b23d0ba | 218 | * If there is no next element in the chain, this function returns NULL. |
marcozecchini | 0:9fca2b23d0ba | 219 | * |
marcozecchini | 0:9fca2b23d0ba | 220 | * @return A pointer to the next FunctionPointerWithContext instance in the |
marcozecchini | 0:9fca2b23d0ba | 221 | * chain. |
marcozecchini | 0:9fca2b23d0ba | 222 | */ |
marcozecchini | 0:9fca2b23d0ba | 223 | pFunctionPointerWithContext_t getNext(void) const |
marcozecchini | 0:9fca2b23d0ba | 224 | { |
marcozecchini | 0:9fca2b23d0ba | 225 | return _next; |
marcozecchini | 0:9fca2b23d0ba | 226 | } |
marcozecchini | 0:9fca2b23d0ba | 227 | |
marcozecchini | 0:9fca2b23d0ba | 228 | /** |
marcozecchini | 0:9fca2b23d0ba | 229 | * Access the next element in the call chain. |
marcozecchini | 0:9fca2b23d0ba | 230 | * |
marcozecchini | 0:9fca2b23d0ba | 231 | * If there is no next element in the chain, this function returns NULL. |
marcozecchini | 0:9fca2b23d0ba | 232 | * |
marcozecchini | 0:9fca2b23d0ba | 233 | * @return A pointer to the next FunctionPointerWithContext instance in the |
marcozecchini | 0:9fca2b23d0ba | 234 | * chain. |
marcozecchini | 0:9fca2b23d0ba | 235 | */ |
marcozecchini | 0:9fca2b23d0ba | 236 | pvoidfcontext_t get_function() const |
marcozecchini | 0:9fca2b23d0ba | 237 | { |
marcozecchini | 0:9fca2b23d0ba | 238 | return (pvoidfcontext_t)_function; |
marcozecchini | 0:9fca2b23d0ba | 239 | } |
marcozecchini | 0:9fca2b23d0ba | 240 | |
marcozecchini | 0:9fca2b23d0ba | 241 | /** |
marcozecchini | 0:9fca2b23d0ba | 242 | * Equal to operator between two FunctionPointerWithContext instances. |
marcozecchini | 0:9fca2b23d0ba | 243 | * |
marcozecchini | 0:9fca2b23d0ba | 244 | * @param[in] lhs Left hand side of the expression. |
marcozecchini | 0:9fca2b23d0ba | 245 | * @param[in] rhs Right hand side of the expression. |
marcozecchini | 0:9fca2b23d0ba | 246 | * |
marcozecchini | 0:9fca2b23d0ba | 247 | * @return true if lhs and rhs adapt the same object and false otherwise. |
marcozecchini | 0:9fca2b23d0ba | 248 | */ |
marcozecchini | 0:9fca2b23d0ba | 249 | friend bool operator==( |
marcozecchini | 0:9fca2b23d0ba | 250 | const FunctionPointerWithContext &lhs, |
marcozecchini | 0:9fca2b23d0ba | 251 | const FunctionPointerWithContext &rhs |
marcozecchini | 0:9fca2b23d0ba | 252 | ) { |
marcozecchini | 0:9fca2b23d0ba | 253 | return rhs._caller == lhs._caller && |
marcozecchini | 0:9fca2b23d0ba | 254 | memcmp( |
marcozecchini | 0:9fca2b23d0ba | 255 | &rhs._memberFunctionAndPointer, |
marcozecchini | 0:9fca2b23d0ba | 256 | &lhs._memberFunctionAndPointer, |
marcozecchini | 0:9fca2b23d0ba | 257 | sizeof(rhs._memberFunctionAndPointer) |
marcozecchini | 0:9fca2b23d0ba | 258 | ) == 0; |
marcozecchini | 0:9fca2b23d0ba | 259 | } |
marcozecchini | 0:9fca2b23d0ba | 260 | |
marcozecchini | 0:9fca2b23d0ba | 261 | private: |
marcozecchini | 0:9fca2b23d0ba | 262 | template<typename T> |
marcozecchini | 0:9fca2b23d0ba | 263 | static void membercaller(cpFunctionPointerWithContext_t self, ContextType context) { |
marcozecchini | 0:9fca2b23d0ba | 264 | if (self->_memberFunctionAndPointer._object) { |
marcozecchini | 0:9fca2b23d0ba | 265 | T *o = static_cast<T *>(self->_memberFunctionAndPointer._object); |
marcozecchini | 0:9fca2b23d0ba | 266 | void (T::*m)(ContextType); |
marcozecchini | 0:9fca2b23d0ba | 267 | memcpy((char*) &m, self->_memberFunctionAndPointer._memberFunction, sizeof(m)); |
marcozecchini | 0:9fca2b23d0ba | 268 | (o->*m)(context); |
marcozecchini | 0:9fca2b23d0ba | 269 | } |
marcozecchini | 0:9fca2b23d0ba | 270 | } |
marcozecchini | 0:9fca2b23d0ba | 271 | |
marcozecchini | 0:9fca2b23d0ba | 272 | static void functioncaller(cpFunctionPointerWithContext_t self, ContextType context) { |
marcozecchini | 0:9fca2b23d0ba | 273 | if (self->_function) { |
marcozecchini | 0:9fca2b23d0ba | 274 | self->_function(context); |
marcozecchini | 0:9fca2b23d0ba | 275 | } |
marcozecchini | 0:9fca2b23d0ba | 276 | } |
marcozecchini | 0:9fca2b23d0ba | 277 | |
marcozecchini | 0:9fca2b23d0ba | 278 | struct MemberFunctionAndPtr { |
marcozecchini | 0:9fca2b23d0ba | 279 | /* |
marcozecchini | 0:9fca2b23d0ba | 280 | * Forward declaration of a class and a member function to this class. |
marcozecchini | 0:9fca2b23d0ba | 281 | * Because the compiler doesn't know anything about the forwarded member |
marcozecchini | 0:9fca2b23d0ba | 282 | * function, it always uses the biggest size and the biggest alignment |
marcozecchini | 0:9fca2b23d0ba | 283 | * that a member function can take for objects of type UndefinedMemberFunction. |
marcozecchini | 0:9fca2b23d0ba | 284 | */ |
marcozecchini | 0:9fca2b23d0ba | 285 | class UndefinedClass; |
marcozecchini | 0:9fca2b23d0ba | 286 | typedef void (UndefinedClass::*UndefinedMemberFunction)(ContextType); |
marcozecchini | 0:9fca2b23d0ba | 287 | |
marcozecchini | 0:9fca2b23d0ba | 288 | void* _object; |
marcozecchini | 0:9fca2b23d0ba | 289 | union { |
marcozecchini | 0:9fca2b23d0ba | 290 | char _memberFunction[sizeof(UndefinedMemberFunction)]; |
marcozecchini | 0:9fca2b23d0ba | 291 | UndefinedMemberFunction _alignment; |
marcozecchini | 0:9fca2b23d0ba | 292 | }; |
marcozecchini | 0:9fca2b23d0ba | 293 | }; |
marcozecchini | 0:9fca2b23d0ba | 294 | |
marcozecchini | 0:9fca2b23d0ba | 295 | union { |
marcozecchini | 0:9fca2b23d0ba | 296 | pvoidfcontext_t _function; /**< Static function pointer - NULL if none attached */ |
marcozecchini | 0:9fca2b23d0ba | 297 | /** |
marcozecchini | 0:9fca2b23d0ba | 298 | * object this pointer and pointer to member - |
marcozecchini | 0:9fca2b23d0ba | 299 | * _memberFunctionAndPointer._object will be NULL if none attached |
marcozecchini | 0:9fca2b23d0ba | 300 | */ |
marcozecchini | 0:9fca2b23d0ba | 301 | mutable MemberFunctionAndPtr _memberFunctionAndPointer; |
marcozecchini | 0:9fca2b23d0ba | 302 | }; |
marcozecchini | 0:9fca2b23d0ba | 303 | |
marcozecchini | 0:9fca2b23d0ba | 304 | void (*_caller)(const FunctionPointerWithContext*, ContextType); |
marcozecchini | 0:9fca2b23d0ba | 305 | |
marcozecchini | 0:9fca2b23d0ba | 306 | pFunctionPointerWithContext_t _next; /**< Optional link to make a chain out of functionPointers. This |
marcozecchini | 0:9fca2b23d0ba | 307 | * allows chaining function pointers without requiring |
marcozecchini | 0:9fca2b23d0ba | 308 | * external memory to manage the chain. Refer to |
marcozecchini | 0:9fca2b23d0ba | 309 | * 'CallChain' as an alternative. */ |
marcozecchini | 0:9fca2b23d0ba | 310 | }; |
marcozecchini | 0:9fca2b23d0ba | 311 | |
marcozecchini | 0:9fca2b23d0ba | 312 | /** |
marcozecchini | 0:9fca2b23d0ba | 313 | * Factory of adapted member function pointers. |
marcozecchini | 0:9fca2b23d0ba | 314 | * |
marcozecchini | 0:9fca2b23d0ba | 315 | * This factory eliminates the need to invoke the qualified constructor of |
marcozecchini | 0:9fca2b23d0ba | 316 | * FunctionPointerWithContext by using automatic type deduction of function |
marcozecchini | 0:9fca2b23d0ba | 317 | * templates. |
marcozecchini | 0:9fca2b23d0ba | 318 | * |
marcozecchini | 0:9fca2b23d0ba | 319 | * @code |
marcozecchini | 0:9fca2b23d0ba | 320 | * |
marcozecchini | 0:9fca2b23d0ba | 321 | * struct ReadHandler { |
marcozecchini | 0:9fca2b23d0ba | 322 | * void on_data_read(const GattReadCallbackParams*); |
marcozecchini | 0:9fca2b23d0ba | 323 | * }; |
marcozecchini | 0:9fca2b23d0ba | 324 | * |
marcozecchini | 0:9fca2b23d0ba | 325 | * ReadHandler read_handler; |
marcozecchini | 0:9fca2b23d0ba | 326 | * |
marcozecchini | 0:9fca2b23d0ba | 327 | * GattClient& client; |
marcozecchini | 0:9fca2b23d0ba | 328 | * |
marcozecchini | 0:9fca2b23d0ba | 329 | * client.onDataRead( |
marcozecchini | 0:9fca2b23d0ba | 330 | * makeFunctionPointer(&read_handler, &ReadHandler::on_data_read) |
marcozecchini | 0:9fca2b23d0ba | 331 | * ); |
marcozecchini | 0:9fca2b23d0ba | 332 | * |
marcozecchini | 0:9fca2b23d0ba | 333 | * // instead of |
marcozecchini | 0:9fca2b23d0ba | 334 | * |
marcozecchini | 0:9fca2b23d0ba | 335 | * client.onDataRead( |
marcozecchini | 0:9fca2b23d0ba | 336 | * FunctionPointerWithContext<const GattReadCallbackParams*>( |
marcozecchini | 0:9fca2b23d0ba | 337 | * &read_handler, |
marcozecchini | 0:9fca2b23d0ba | 338 | * &ReadHandler::on_data_read |
marcozecchini | 0:9fca2b23d0ba | 339 | * ) |
marcozecchini | 0:9fca2b23d0ba | 340 | * ); |
marcozecchini | 0:9fca2b23d0ba | 341 | * @endcode |
marcozecchini | 0:9fca2b23d0ba | 342 | * |
marcozecchini | 0:9fca2b23d0ba | 343 | * |
marcozecchini | 0:9fca2b23d0ba | 344 | * @param[in] object Instance to bound with @p member. |
marcozecchini | 0:9fca2b23d0ba | 345 | * @param member The member being adapted. |
marcozecchini | 0:9fca2b23d0ba | 346 | * |
marcozecchini | 0:9fca2b23d0ba | 347 | * @return Adaptation of the parameters in a FunctionPointerWithContext instance. |
marcozecchini | 0:9fca2b23d0ba | 348 | */ |
marcozecchini | 0:9fca2b23d0ba | 349 | template<typename T, typename ContextType> |
marcozecchini | 0:9fca2b23d0ba | 350 | FunctionPointerWithContext<ContextType> makeFunctionPointer( |
marcozecchini | 0:9fca2b23d0ba | 351 | T *object, |
marcozecchini | 0:9fca2b23d0ba | 352 | void (T::*member)(ContextType context) |
marcozecchini | 0:9fca2b23d0ba | 353 | ) { |
marcozecchini | 0:9fca2b23d0ba | 354 | return FunctionPointerWithContext<ContextType>(object, member); |
marcozecchini | 0:9fca2b23d0ba | 355 | } |
marcozecchini | 0:9fca2b23d0ba | 356 | |
marcozecchini | 0:9fca2b23d0ba | 357 | /** |
marcozecchini | 0:9fca2b23d0ba | 358 | * @} |
marcozecchini | 0:9fca2b23d0ba | 359 | * @} |
marcozecchini | 0:9fca2b23d0ba | 360 | */ |
marcozecchini | 0:9fca2b23d0ba | 361 | |
marcozecchini | 0:9fca2b23d0ba | 362 | #endif // ifndef MBED_FUNCTIONPOINTER_WITH_CONTEXT_H |