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