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