Christopher Haster / mbed-hal

Dependencies:   target-freescale

Fork of mbed-hal by Morpheus

Committer:
Christopher Haster
Date:
Wed Apr 06 02:13:49 2016 -0500
Revision:
19:f1c94b98286f
Parent:
18:8c5ec1e88a9c
Added support for function objects to FuncPtrs

Who changed what in which revision?

UserRevisionLine numberNew contents of line
screamer 0:9c59db1fbc9e 1 /* mbed Microcontroller Library
screamer 0:9c59db1fbc9e 2 * Copyright (c) 2006-2015 ARM Limited
screamer 0:9c59db1fbc9e 3 *
screamer 0:9c59db1fbc9e 4 * Licensed under the Apache License, Version 2.0 (the "License");
screamer 0:9c59db1fbc9e 5 * you may not use this file except in compliance with the License.
screamer 0:9c59db1fbc9e 6 * You may obtain a copy of the License at
screamer 0:9c59db1fbc9e 7 *
screamer 0:9c59db1fbc9e 8 * http://www.apache.org/licenses/LICENSE-2.0
screamer 0:9c59db1fbc9e 9 *
screamer 0:9c59db1fbc9e 10 * Unless required by applicable law or agreed to in writing, software
screamer 0:9c59db1fbc9e 11 * distributed under the License is distributed on an "AS IS" BASIS,
screamer 0:9c59db1fbc9e 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
screamer 0:9c59db1fbc9e 13 * See the License for the specific language governing permissions and
screamer 0:9c59db1fbc9e 14 * limitations under the License.
screamer 0:9c59db1fbc9e 15 */
Christopher Haster 7:4fdb3a44f646 16 #ifndef MBED_FUNCTIONPOINTER_H
Christopher Haster 7:4fdb3a44f646 17 #define MBED_FUNCTIONPOINTER_H
screamer 0:9c59db1fbc9e 18
Christopher Haster 11:f08e03081748 19 #include <string.h>
Christopher Haster 11:f08e03081748 20 #include <stdint.h>
screamer 0:9c59db1fbc9e 21
screamer 0:9c59db1fbc9e 22 namespace mbed {
screamer 0:9c59db1fbc9e 23
Christopher Haster 14:4af7fef9cf08 24 // Reusable FuncPtr class based on template specialization
Christopher Haster 11:f08e03081748 25 template <typename F>
Christopher Haster 14:4af7fef9cf08 26 class FuncPtr;
Christopher Haster 11:f08e03081748 27
Christopher Haster 11:f08e03081748 28 /** A class for storing and calling a pointer to a static or member function
Christopher Haster 11:f08e03081748 29 */
Christopher Haster 11:f08e03081748 30 template <typename R, typename A1, typename A2, typename A3, typename A4>
Christopher Haster 14:4af7fef9cf08 31 class FuncPtr<R(A1, A2, A3, A4)> {
Christopher Haster 11:f08e03081748 32 public:
Christopher Haster 14:4af7fef9cf08 33 /** Create a FuncPtr, attaching a static function
Christopher Haster 11:f08e03081748 34 *
Christopher Haster 11:f08e03081748 35 * @param function The static function to attach (default is none)
Christopher Haster 11:f08e03081748 36 */
Christopher Haster 14:4af7fef9cf08 37 FuncPtr(R (*function)(A1, A2, A3, A4) = 0) {
Christopher Haster 11:f08e03081748 38 attach(function);
Christopher Haster 11:f08e03081748 39 }
Christopher Haster 11:f08e03081748 40
Christopher Haster 14:4af7fef9cf08 41 /** Create a FuncPtr, attaching a static function with bound pointer
Christopher Haster 11:f08e03081748 42 *
Christopher Haster 11:f08e03081748 43 * @param object Pointer to object to bind to function
Christopher Haster 11:f08e03081748 44 * @param function The static function to attach
Christopher Haster 11:f08e03081748 45 */
Christopher Haster 11:f08e03081748 46 template<typename T>
Christopher Haster 14:4af7fef9cf08 47 FuncPtr(T *object, R (*function)(T*, A1, A2, A3, A4)) {
Christopher Haster 11:f08e03081748 48 attach(object, function);
Christopher Haster 11:f08e03081748 49 }
Christopher Haster 11:f08e03081748 50
Christopher Haster 14:4af7fef9cf08 51 /** Create a FuncPtr, attaching a member function
Christopher Haster 11:f08e03081748 52 *
Christopher Haster 11:f08e03081748 53 * @param object The object pointer to invoke the member function on (i.e. the this pointer)
Christopher Haster 11:f08e03081748 54 * @param function The address of the member function to attach
Christopher Haster 11:f08e03081748 55 */
Christopher Haster 11:f08e03081748 56 template<typename T>
Christopher Haster 14:4af7fef9cf08 57 FuncPtr(T *object, R (T::*member)(A1, A2, A3, A4)) {
Christopher Haster 11:f08e03081748 58 attach(object, member);
Christopher Haster 11:f08e03081748 59 }
Christopher Haster 11:f08e03081748 60
Christopher Haster 19:f1c94b98286f 61 /** Create a FuncPtr, attaching a function object
Christopher Haster 19:f1c94b98286f 62 *
Christopher Haster 19:f1c94b98286f 63 * @param object Pointer to a function object to attach
Christopher Haster 19:f1c94b98286f 64 */
Christopher Haster 19:f1c94b98286f 65 template<typename T>
Christopher Haster 19:f1c94b98286f 66 FuncPtr(T *object) {
Christopher Haster 19:f1c94b98286f 67 attach(object, &T::operator());
Christopher Haster 19:f1c94b98286f 68 }
Christopher Haster 19:f1c94b98286f 69
Christopher Haster 14:4af7fef9cf08 70 /** Create a FuncPtr from another FuncPtr
Christopher Haster 11:f08e03081748 71 *
Christopher Haster 11:f08e03081748 72 * @param func The func to attach
Christopher Haster 11:f08e03081748 73 */
Christopher Haster 14:4af7fef9cf08 74 FuncPtr(const FuncPtr<R(A1, A2, A3, A4)> &func) {
Christopher Haster 11:f08e03081748 75 attach(func);
Christopher Haster 11:f08e03081748 76 }
Christopher Haster 11:f08e03081748 77
Christopher Haster 11:f08e03081748 78 /** Attach a static function
Christopher Haster 11:f08e03081748 79 *
Christopher Haster 11:f08e03081748 80 * @param function The static function to attach (default is none)
Christopher Haster 11:f08e03081748 81 */
Christopher Haster 11:f08e03081748 82 void attach(R (*function)(A1, A2, A3, A4)) {
Christopher Haster 11:f08e03081748 83 _object = 0;
Christopher Haster 18:8c5ec1e88a9c 84 memcpy(&_function, &function, sizeof function);
Christopher Haster 14:4af7fef9cf08 85 _thunk = &FuncPtr::staticthunk;
Christopher Haster 11:f08e03081748 86 }
Christopher Haster 11:f08e03081748 87
Christopher Haster 11:f08e03081748 88 /** Attach a static function with bound pointer
Christopher Haster 11:f08e03081748 89 *
Christopher Haster 11:f08e03081748 90 * @param object Pointer to object to bind to function
Christopher Haster 11:f08e03081748 91 * @param function The static function to attach
Christopher Haster 11:f08e03081748 92 */
Christopher Haster 11:f08e03081748 93 template <typename T>
Christopher Haster 15:1ce23ed6859a 94 void attach(T *object, R (*function)(T*, A1, A2, A3, A4)) {
Christopher Haster 11:f08e03081748 95 _object = static_cast<void*>(object);
Christopher Haster 18:8c5ec1e88a9c 96 memcpy(&_function, &function, sizeof function);
Christopher Haster 14:4af7fef9cf08 97 _thunk = &FuncPtr::boundthunk<T>;
Christopher Haster 11:f08e03081748 98 }
Christopher Haster 11:f08e03081748 99
Christopher Haster 11:f08e03081748 100 /** Attach a member function
Christopher Haster 11:f08e03081748 101 *
Christopher Haster 11:f08e03081748 102 * @param object The object pointer to invoke the member function on (i.e. the this pointer)
Christopher Haster 11:f08e03081748 103 * @param function The address of the member function to attach
Christopher Haster 11:f08e03081748 104 */
Christopher Haster 11:f08e03081748 105 template<typename T>
Christopher Haster 11:f08e03081748 106 void attach(T *object, R (T::*method)(A1, A2, A3, A4)) {
Christopher Haster 11:f08e03081748 107 _object = static_cast<void*>(object);
Christopher Haster 18:8c5ec1e88a9c 108 memcpy(&_function, &method, sizeof method);
Christopher Haster 14:4af7fef9cf08 109 _thunk = &FuncPtr::methodthunk<T>;
Christopher Haster 11:f08e03081748 110 }
Christopher Haster 11:f08e03081748 111
Christopher Haster 19:f1c94b98286f 112 /** Attach a function object
Christopher Haster 19:f1c94b98286f 113 *
Christopher Haster 19:f1c94b98286f 114 * @param object Pointer to a function object to attach
Christopher Haster 19:f1c94b98286f 115 */
Christopher Haster 19:f1c94b98286f 116 template<typename T>
Christopher Haster 19:f1c94b98286f 117 void attach(T *object) {
Christopher Haster 19:f1c94b98286f 118 attach(object, &T::operator());
Christopher Haster 19:f1c94b98286f 119 }
Christopher Haster 19:f1c94b98286f 120
Christopher Haster 14:4af7fef9cf08 121 /** Attach a FuncPtr
Christopher Haster 11:f08e03081748 122 *
Christopher Haster 11:f08e03081748 123 * @param func The func to attach
Christopher Haster 11:f08e03081748 124 */
Christopher Haster 14:4af7fef9cf08 125 void attach(const FuncPtr<R(A1, A2, A3, A4)> &func) {
Christopher Haster 11:f08e03081748 126 _object = func._object;
Christopher Haster 18:8c5ec1e88a9c 127 memcpy(&_function, &func._function, sizeof _function);
Christopher Haster 11:f08e03081748 128 _thunk = func._thunk;
Christopher Haster 11:f08e03081748 129 }
Christopher Haster 11:f08e03081748 130
Christopher Haster 11:f08e03081748 131 /** Call the attached static or member function
Christopher Haster 11:f08e03081748 132 */
Christopher Haster 11:f08e03081748 133 R call(A1 a1, A2 a2, A3 a3, A4 a4) {
Christopher Haster 11:f08e03081748 134 return _thunk(_object, _function, a1, a2, a3, a4);
Christopher Haster 11:f08e03081748 135 }
Christopher Haster 11:f08e03081748 136
Christopher Haster 11:f08e03081748 137 /** Get registered static function
Christopher Haster 11:f08e03081748 138 */
Christopher Haster 11:f08e03081748 139 R (*get_function(A1, A2, A3, A4))() {
Christopher Haster 11:f08e03081748 140 return reinterpret_cast<R (*)(A1, A2, A3, A4)>(_object ? 0 : _function);
Christopher Haster 11:f08e03081748 141 }
Christopher Haster 11:f08e03081748 142
Christopher Haster 11:f08e03081748 143 #ifdef MBED_OPERATORS
Christopher Haster 11:f08e03081748 144 R operator ()(A1 a1, A2 a2, A3 a3, A4 a4) {
Christopher Haster 11:f08e03081748 145 return call(a1, a2, a3, a4);
Christopher Haster 11:f08e03081748 146 }
Christopher Haster 11:f08e03081748 147 operator bool(void) const {
Christopher Haster 11:f08e03081748 148 return static_cast<bool>(_function);
Christopher Haster 11:f08e03081748 149 }
Christopher Haster 11:f08e03081748 150 #endif
Christopher Haster 11:f08e03081748 151 private:
Christopher Haster 11:f08e03081748 152 // Static thunks for various function types
Christopher Haster 15:1ce23ed6859a 153 static R staticthunk(void*, void *func, A1 a1, A2 a2, A3 a3, A4 a4) {
Christopher Haster 11:f08e03081748 154 R (*f)(A1, A2, A3, A4) = *reinterpret_cast<R (**)(A1, A2, A3, A4)>(func);
Christopher Haster 11:f08e03081748 155 return f(a1, a2, a3, a4);
Christopher Haster 11:f08e03081748 156 }
Christopher Haster 11:f08e03081748 157
Christopher Haster 11:f08e03081748 158 template<typename T>
Christopher Haster 11:f08e03081748 159 static R boundthunk(void *object, void *func, A1 a1, A2 a2, A3 a3, A4 a4) {
Christopher Haster 11:f08e03081748 160 T *o = static_cast<T*>(object);
Christopher Haster 17:fe43695d093a 161 R (*f)(T*, A1, A2, A3, A4) = *reinterpret_cast<R (**)(T*, A1, A2, A3, A4)>(func);
Christopher Haster 11:f08e03081748 162 return f(o, a1);
Christopher Haster 11:f08e03081748 163 }
Christopher Haster 11:f08e03081748 164
Christopher Haster 11:f08e03081748 165 template<typename T>
Christopher Haster 11:f08e03081748 166 static R methodthunk(void *object, void *member, A1 a1, A2 a2, A3 a3, A4 a4) {
Christopher Haster 11:f08e03081748 167 T* o = static_cast<T*>(object);
Christopher Haster 11:f08e03081748 168 R (T::*m)(A1, A2, A3, A4) = *reinterpret_cast<R (T::**)(A1, A2, A3, A4)>(member);
Christopher Haster 11:f08e03081748 169 return (o->*m)(a1, a2, a3, a4);
Christopher Haster 11:f08e03081748 170 }
Christopher Haster 11:f08e03081748 171
Christopher Haster 11:f08e03081748 172 // Forward declaration of an unknown class
Christopher Haster 11:f08e03081748 173 // this kind of declaration is authorized by the standard (see 8.3.3/2 of C++ 03 standard).
Christopher Haster 11:f08e03081748 174 // As a result, the compiler will allocate for UnknownFunctionMember_t the biggest size
Christopher Haster 11:f08e03081748 175 // and biggest alignment possible for member function.
Christopher Haster 11:f08e03081748 176 // This type can be used inside unions, it will help to provide the storage
Christopher Haster 11:f08e03081748 177 // with the proper size and alignment guarantees
Christopher Haster 11:f08e03081748 178 class UnknownClass;
Christopher Haster 11:f08e03081748 179
Christopher Haster 11:f08e03081748 180 // object this pointer
Christopher Haster 11:f08e03081748 181 void *_object;
Christopher Haster 11:f08e03081748 182
Christopher Haster 11:f08e03081748 183 // aligned raw member function pointer storage - converted back by registered thunk
Christopher Haster 11:f08e03081748 184 char _function[sizeof(void (UnknownClass::*)())];
Christopher Haster 11:f08e03081748 185
Christopher Haster 11:f08e03081748 186 // registered function to convert back and call _m.member on _object
Christopher Haster 11:f08e03081748 187 R (*_thunk)(void*, void*, A1, A2, A3, A4);
Christopher Haster 11:f08e03081748 188 };
Christopher Haster 11:f08e03081748 189
Christopher Haster 11:f08e03081748 190 /** A class for storing and calling a pointer to a static or member function
Christopher Haster 11:f08e03081748 191 */
Christopher Haster 11:f08e03081748 192 template <typename R, typename A1, typename A2, typename A3>
Christopher Haster 14:4af7fef9cf08 193 class FuncPtr<R(A1, A2, A3)> {
Christopher Haster 11:f08e03081748 194 public:
Christopher Haster 14:4af7fef9cf08 195 /** Create a FuncPtr, attaching a static function
Christopher Haster 11:f08e03081748 196 *
Christopher Haster 11:f08e03081748 197 * @param function The static function to attach (default is none)
Christopher Haster 11:f08e03081748 198 */
Christopher Haster 14:4af7fef9cf08 199 FuncPtr(R (*function)(A1, A2, A3) = 0) {
Christopher Haster 11:f08e03081748 200 attach(function);
Christopher Haster 11:f08e03081748 201 }
Christopher Haster 11:f08e03081748 202
Christopher Haster 14:4af7fef9cf08 203 /** Create a FuncPtr, attaching a static function with bound pointer
Christopher Haster 11:f08e03081748 204 *
Christopher Haster 11:f08e03081748 205 * @param object Pointer to object to bind to function
Christopher Haster 11:f08e03081748 206 * @param function The static function to attach
Christopher Haster 11:f08e03081748 207 */
Christopher Haster 11:f08e03081748 208 template<typename T>
Christopher Haster 14:4af7fef9cf08 209 FuncPtr(T *object, R (*function)(T*, A1, A2, A3)) {
Christopher Haster 11:f08e03081748 210 attach(object, function);
Christopher Haster 11:f08e03081748 211 }
Christopher Haster 11:f08e03081748 212
Christopher Haster 14:4af7fef9cf08 213 /** Create a FuncPtr, attaching a member function
Christopher Haster 11:f08e03081748 214 *
Christopher Haster 11:f08e03081748 215 * @param object The object pointer to invoke the member function on (i.e. the this pointer)
Christopher Haster 11:f08e03081748 216 * @param function The address of the member function to attach
Christopher Haster 11:f08e03081748 217 */
Christopher Haster 11:f08e03081748 218 template<typename T>
Christopher Haster 14:4af7fef9cf08 219 FuncPtr(T *object, R (T::*member)(A1, A2, A3)) {
Christopher Haster 11:f08e03081748 220 attach(object, member);
Christopher Haster 11:f08e03081748 221 }
Christopher Haster 11:f08e03081748 222
Christopher Haster 19:f1c94b98286f 223 /** Create a FuncPtr, attaching a function object
Christopher Haster 19:f1c94b98286f 224 *
Christopher Haster 19:f1c94b98286f 225 * @param object Pointer to a function object to attach
Christopher Haster 19:f1c94b98286f 226 */
Christopher Haster 19:f1c94b98286f 227 template<typename T>
Christopher Haster 19:f1c94b98286f 228 FuncPtr(T *object) {
Christopher Haster 19:f1c94b98286f 229 attach(object, &T::operator());
Christopher Haster 19:f1c94b98286f 230 }
Christopher Haster 19:f1c94b98286f 231
Christopher Haster 14:4af7fef9cf08 232 /** Create a FuncPtr from another FuncPtr
Christopher Haster 11:f08e03081748 233 *
Christopher Haster 11:f08e03081748 234 * @param func The func to attach
Christopher Haster 11:f08e03081748 235 */
Christopher Haster 14:4af7fef9cf08 236 FuncPtr(const FuncPtr<R(A1, A2, A3)> &func) {
Christopher Haster 11:f08e03081748 237 attach(func);
Christopher Haster 11:f08e03081748 238 }
Christopher Haster 11:f08e03081748 239
Christopher Haster 11:f08e03081748 240 /** Attach a static function
Christopher Haster 11:f08e03081748 241 *
Christopher Haster 11:f08e03081748 242 * @param function The static function to attach (default is none)
Christopher Haster 11:f08e03081748 243 */
Christopher Haster 11:f08e03081748 244 void attach(R (*function)(A1, A2, A3)) {
Christopher Haster 11:f08e03081748 245 _object = 0;
Christopher Haster 18:8c5ec1e88a9c 246 memcpy(&_function, &function, sizeof function);
Christopher Haster 14:4af7fef9cf08 247 _thunk = &FuncPtr::staticthunk;
Christopher Haster 11:f08e03081748 248 }
Christopher Haster 11:f08e03081748 249
Christopher Haster 11:f08e03081748 250 /** Attach a static function with bound pointer
Christopher Haster 11:f08e03081748 251 *
Christopher Haster 11:f08e03081748 252 * @param object Pointer to object to bind to function
Christopher Haster 11:f08e03081748 253 * @param function The static function to attach
Christopher Haster 11:f08e03081748 254 */
Christopher Haster 11:f08e03081748 255 template <typename T>
Christopher Haster 15:1ce23ed6859a 256 void attach(T *object, R (*function)(T*, A1, A2, A3)) {
Christopher Haster 11:f08e03081748 257 _object = static_cast<void*>(object);
Christopher Haster 18:8c5ec1e88a9c 258 memcpy(&_function, &function, sizeof function);
Christopher Haster 14:4af7fef9cf08 259 _thunk = &FuncPtr::boundthunk<T>;
Christopher Haster 11:f08e03081748 260 }
Christopher Haster 11:f08e03081748 261
Christopher Haster 11:f08e03081748 262 /** Attach a member function
Christopher Haster 11:f08e03081748 263 *
Christopher Haster 11:f08e03081748 264 * @param object The object pointer to invoke the member function on (i.e. the this pointer)
Christopher Haster 11:f08e03081748 265 * @param function The address of the member function to attach
Christopher Haster 11:f08e03081748 266 */
Christopher Haster 11:f08e03081748 267 template<typename T>
Christopher Haster 11:f08e03081748 268 void attach(T *object, R (T::*method)(A1, A2, A3)) {
Christopher Haster 11:f08e03081748 269 _object = static_cast<void*>(object);
Christopher Haster 18:8c5ec1e88a9c 270 memcpy(&_function, &method, sizeof method);
Christopher Haster 14:4af7fef9cf08 271 _thunk = &FuncPtr::methodthunk<T>;
Christopher Haster 11:f08e03081748 272 }
Christopher Haster 11:f08e03081748 273
Christopher Haster 19:f1c94b98286f 274 /** Attach a function object
Christopher Haster 19:f1c94b98286f 275 *
Christopher Haster 19:f1c94b98286f 276 * @param object Pointer to a function object to attach
Christopher Haster 19:f1c94b98286f 277 */
Christopher Haster 19:f1c94b98286f 278 template<typename T>
Christopher Haster 19:f1c94b98286f 279 void attach(T *object) {
Christopher Haster 19:f1c94b98286f 280 attach(object, &T::operator());
Christopher Haster 19:f1c94b98286f 281 }
Christopher Haster 19:f1c94b98286f 282
Christopher Haster 14:4af7fef9cf08 283 /** Attach a FuncPtr
Christopher Haster 11:f08e03081748 284 *
Christopher Haster 11:f08e03081748 285 * @param func The func to attach
Christopher Haster 11:f08e03081748 286 */
Christopher Haster 14:4af7fef9cf08 287 void attach(const FuncPtr<R(A1, A2, A3)> &func) {
Christopher Haster 11:f08e03081748 288 _object = func._object;
Christopher Haster 18:8c5ec1e88a9c 289 memcpy(&_function, &func._function, sizeof _function);
Christopher Haster 11:f08e03081748 290 _thunk = func._thunk;
Christopher Haster 11:f08e03081748 291 }
Christopher Haster 11:f08e03081748 292
Christopher Haster 11:f08e03081748 293 /** Call the attached static or member function
Christopher Haster 11:f08e03081748 294 */
Christopher Haster 11:f08e03081748 295 R call(A1 a1, A2 a2, A3 a3) {
Christopher Haster 11:f08e03081748 296 return _thunk(_object, _function, a1, a2, a3);
Christopher Haster 11:f08e03081748 297 }
Christopher Haster 11:f08e03081748 298
Christopher Haster 11:f08e03081748 299 /** Get registered static function
Christopher Haster 11:f08e03081748 300 */
Christopher Haster 11:f08e03081748 301 R (*get_function(A1, A2, A3))() {
Christopher Haster 11:f08e03081748 302 return reinterpret_cast<R (*)(A1, A2, A3)>(_object ? 0 : _function);
Christopher Haster 11:f08e03081748 303 }
Christopher Haster 11:f08e03081748 304
Christopher Haster 11:f08e03081748 305 #ifdef MBED_OPERATORS
Christopher Haster 11:f08e03081748 306 R operator ()(A1 a1, A2 a2, A3 a3) {
Christopher Haster 11:f08e03081748 307 return call(a1, a2, a3);
Christopher Haster 11:f08e03081748 308 }
Christopher Haster 11:f08e03081748 309 operator bool(void) const {
Christopher Haster 11:f08e03081748 310 return static_cast<bool>(_function);
Christopher Haster 11:f08e03081748 311 }
Christopher Haster 11:f08e03081748 312 #endif
Christopher Haster 11:f08e03081748 313 private:
Christopher Haster 11:f08e03081748 314 // Static thunks for various function types
Christopher Haster 15:1ce23ed6859a 315 static R staticthunk(void*, void *func, A1 a1, A2 a2, A3 a3) {
Christopher Haster 11:f08e03081748 316 R (*f)(A1, A2, A3) = *reinterpret_cast<R (**)(A1, A2, A3)>(func);
Christopher Haster 11:f08e03081748 317 return f(a1, a2, a3);
Christopher Haster 11:f08e03081748 318 }
Christopher Haster 11:f08e03081748 319
Christopher Haster 11:f08e03081748 320 template<typename T>
Christopher Haster 11:f08e03081748 321 static R boundthunk(void *object, void *func, A1 a1, A2 a2, A3 a3) {
Christopher Haster 11:f08e03081748 322 T *o = static_cast<T*>(object);
Christopher Haster 17:fe43695d093a 323 R (*f)(T*, A1, A2, A3) = *reinterpret_cast<R (**)(T*, A1, A2, A3)>(func);
Christopher Haster 11:f08e03081748 324 return f(o, a1);
Christopher Haster 11:f08e03081748 325 }
Christopher Haster 11:f08e03081748 326
Christopher Haster 11:f08e03081748 327 template<typename T>
Christopher Haster 11:f08e03081748 328 static R methodthunk(void *object, void *member, A1 a1, A2 a2, A3 a3) {
Christopher Haster 11:f08e03081748 329 T* o = static_cast<T*>(object);
Christopher Haster 11:f08e03081748 330 R (T::*m)(A1, A2, A3) = *reinterpret_cast<R (T::**)(A1, A2, A3)>(member);
Christopher Haster 11:f08e03081748 331 return (o->*m)(a1, a2, a3);
Christopher Haster 11:f08e03081748 332 }
Christopher Haster 11:f08e03081748 333
Christopher Haster 11:f08e03081748 334 // Forward declaration of an unknown class
Christopher Haster 11:f08e03081748 335 // this kind of declaration is authorized by the standard (see 8.3.3/2 of C++ 03 standard).
Christopher Haster 11:f08e03081748 336 // As a result, the compiler will allocate for UnknownFunctionMember_t the biggest size
Christopher Haster 11:f08e03081748 337 // and biggest alignment possible for member function.
Christopher Haster 11:f08e03081748 338 // This type can be used inside unions, it will help to provide the storage
Christopher Haster 11:f08e03081748 339 // with the proper size and alignment guarantees
Christopher Haster 11:f08e03081748 340 class UnknownClass;
Christopher Haster 11:f08e03081748 341
Christopher Haster 11:f08e03081748 342 // object this pointer
Christopher Haster 11:f08e03081748 343 void *_object;
Christopher Haster 11:f08e03081748 344
Christopher Haster 11:f08e03081748 345 // aligned raw member function pointer storage - converted back by registered thunk
Christopher Haster 11:f08e03081748 346 char _function[sizeof(void (UnknownClass::*)())];
Christopher Haster 11:f08e03081748 347
Christopher Haster 11:f08e03081748 348 // registered function to convert back and call _m.member on _object
Christopher Haster 11:f08e03081748 349 R (*_thunk)(void*, void*, A1, A2, A3);
Christopher Haster 11:f08e03081748 350 };
Christopher Haster 11:f08e03081748 351
Christopher Haster 11:f08e03081748 352 /** A class for storing and calling a pointer to a static or member function
Christopher Haster 11:f08e03081748 353 */
Christopher Haster 11:f08e03081748 354 template <typename R, typename A1, typename A2>
Christopher Haster 14:4af7fef9cf08 355 class FuncPtr<R(A1, A2)> {
Christopher Haster 11:f08e03081748 356 public:
Christopher Haster 14:4af7fef9cf08 357 /** Create a FuncPtr, attaching a static function
Christopher Haster 11:f08e03081748 358 *
Christopher Haster 11:f08e03081748 359 * @param function The static function to attach (default is none)
Christopher Haster 11:f08e03081748 360 */
Christopher Haster 14:4af7fef9cf08 361 FuncPtr(R (*function)(A1, A2) = 0) {
Christopher Haster 11:f08e03081748 362 attach(function);
Christopher Haster 11:f08e03081748 363 }
Christopher Haster 11:f08e03081748 364
Christopher Haster 14:4af7fef9cf08 365 /** Create a FuncPtr, attaching a static function with bound pointer
Christopher Haster 11:f08e03081748 366 *
Christopher Haster 11:f08e03081748 367 * @param object Pointer to object to bind to function
Christopher Haster 11:f08e03081748 368 * @param function The static function to attach
Christopher Haster 11:f08e03081748 369 */
Christopher Haster 11:f08e03081748 370 template<typename T>
Christopher Haster 14:4af7fef9cf08 371 FuncPtr(T *object, R (*function)(T*, A1, A2)) {
Christopher Haster 11:f08e03081748 372 attach(object, function);
Christopher Haster 11:f08e03081748 373 }
Christopher Haster 11:f08e03081748 374
Christopher Haster 14:4af7fef9cf08 375 /** Create a FuncPtr, attaching a member function
Christopher Haster 11:f08e03081748 376 *
Christopher Haster 11:f08e03081748 377 * @param object The object pointer to invoke the member function on (i.e. the this pointer)
Christopher Haster 11:f08e03081748 378 * @param function The address of the member function to attach
Christopher Haster 11:f08e03081748 379 */
Christopher Haster 11:f08e03081748 380 template<typename T>
Christopher Haster 14:4af7fef9cf08 381 FuncPtr(T *object, R (T::*member)(A1, A2)) {
Christopher Haster 11:f08e03081748 382 attach(object, member);
Christopher Haster 11:f08e03081748 383 }
Christopher Haster 11:f08e03081748 384
Christopher Haster 19:f1c94b98286f 385 /** Create a FuncPtr, attaching a function object
Christopher Haster 19:f1c94b98286f 386 *
Christopher Haster 19:f1c94b98286f 387 * @param object Pointer to a function object to attach
Christopher Haster 19:f1c94b98286f 388 */
Christopher Haster 19:f1c94b98286f 389 template<typename T>
Christopher Haster 19:f1c94b98286f 390 FuncPtr(T *object) {
Christopher Haster 19:f1c94b98286f 391 attach(object, &T::operator());
Christopher Haster 19:f1c94b98286f 392 }
Christopher Haster 19:f1c94b98286f 393
Christopher Haster 14:4af7fef9cf08 394 /** Create a FuncPtr from another FuncPtr
Christopher Haster 11:f08e03081748 395 *
Christopher Haster 11:f08e03081748 396 * @param func The func to attach
Christopher Haster 11:f08e03081748 397 */
Christopher Haster 14:4af7fef9cf08 398 FuncPtr(const FuncPtr<R(A1, A2)> &func) {
Christopher Haster 11:f08e03081748 399 attach(func);
Christopher Haster 11:f08e03081748 400 }
Christopher Haster 11:f08e03081748 401
Christopher Haster 11:f08e03081748 402 /** Attach a static function
Christopher Haster 11:f08e03081748 403 *
Christopher Haster 11:f08e03081748 404 * @param function The static function to attach (default is none)
Christopher Haster 11:f08e03081748 405 */
Christopher Haster 11:f08e03081748 406 void attach(R (*function)(A1, A2)) {
Christopher Haster 11:f08e03081748 407 _object = 0;
Christopher Haster 18:8c5ec1e88a9c 408 memcpy(&_function, &function, sizeof function);
Christopher Haster 14:4af7fef9cf08 409 _thunk = &FuncPtr::staticthunk;
Christopher Haster 11:f08e03081748 410 }
Christopher Haster 11:f08e03081748 411
Christopher Haster 11:f08e03081748 412 /** Attach a static function with bound pointer
Christopher Haster 11:f08e03081748 413 *
Christopher Haster 11:f08e03081748 414 * @param object Pointer to object to bind to function
Christopher Haster 11:f08e03081748 415 * @param function The static function to attach
Christopher Haster 11:f08e03081748 416 */
Christopher Haster 11:f08e03081748 417 template <typename T>
Christopher Haster 15:1ce23ed6859a 418 void attach(T *object, R (*function)(T*, A1, A2)) {
Christopher Haster 11:f08e03081748 419 _object = static_cast<void*>(object);
Christopher Haster 18:8c5ec1e88a9c 420 memcpy(&_function, &function, sizeof function);
Christopher Haster 14:4af7fef9cf08 421 _thunk = &FuncPtr::boundthunk<T>;
Christopher Haster 11:f08e03081748 422 }
Christopher Haster 11:f08e03081748 423
Christopher Haster 11:f08e03081748 424 /** Attach a member function
Christopher Haster 11:f08e03081748 425 *
Christopher Haster 11:f08e03081748 426 * @param object The object pointer to invoke the member function on (i.e. the this pointer)
Christopher Haster 11:f08e03081748 427 * @param function The address of the member function to attach
Christopher Haster 11:f08e03081748 428 */
Christopher Haster 11:f08e03081748 429 template<typename T>
Christopher Haster 11:f08e03081748 430 void attach(T *object, R (T::*method)(A1, A2)) {
Christopher Haster 11:f08e03081748 431 _object = static_cast<void*>(object);
Christopher Haster 18:8c5ec1e88a9c 432 memcpy(&_function, &method, sizeof method);
Christopher Haster 14:4af7fef9cf08 433 _thunk = &FuncPtr::methodthunk<T>;
Christopher Haster 11:f08e03081748 434 }
Christopher Haster 11:f08e03081748 435
Christopher Haster 19:f1c94b98286f 436 /** Attach a function object
Christopher Haster 19:f1c94b98286f 437 *
Christopher Haster 19:f1c94b98286f 438 * @param object Pointer to a function object to attach
Christopher Haster 19:f1c94b98286f 439 */
Christopher Haster 19:f1c94b98286f 440 template<typename T>
Christopher Haster 19:f1c94b98286f 441 void attach(T *object) {
Christopher Haster 19:f1c94b98286f 442 attach(object, &T::operator());
Christopher Haster 19:f1c94b98286f 443 }
Christopher Haster 19:f1c94b98286f 444
Christopher Haster 14:4af7fef9cf08 445 /** Attach a FuncPtr
Christopher Haster 11:f08e03081748 446 *
Christopher Haster 11:f08e03081748 447 * @param func The func to attach
Christopher Haster 11:f08e03081748 448 */
Christopher Haster 14:4af7fef9cf08 449 void attach(const FuncPtr<R(A1, A2)> &func) {
Christopher Haster 11:f08e03081748 450 _object = func._object;
Christopher Haster 18:8c5ec1e88a9c 451 memcpy(&_function, &func._function, sizeof _function);
Christopher Haster 11:f08e03081748 452 _thunk = func._thunk;
Christopher Haster 11:f08e03081748 453 }
Christopher Haster 11:f08e03081748 454
Christopher Haster 11:f08e03081748 455 /** Call the attached static or member function
Christopher Haster 11:f08e03081748 456 */
Christopher Haster 11:f08e03081748 457 R call(A1 a1, A2 a2) {
Christopher Haster 11:f08e03081748 458 return _thunk(_object, _function, a1, a2);
Christopher Haster 11:f08e03081748 459 }
Christopher Haster 11:f08e03081748 460
Christopher Haster 11:f08e03081748 461 /** Get registered static function
Christopher Haster 11:f08e03081748 462 */
Christopher Haster 11:f08e03081748 463 R (*get_function(A1, A2))() {
Christopher Haster 11:f08e03081748 464 return reinterpret_cast<R (*)(A1, A2)>(_object ? 0 : _function);
Christopher Haster 11:f08e03081748 465 }
Christopher Haster 11:f08e03081748 466
Christopher Haster 11:f08e03081748 467 #ifdef MBED_OPERATORS
Christopher Haster 11:f08e03081748 468 R operator ()(A1 a1, A2 a2) {
Christopher Haster 11:f08e03081748 469 return call(a1, a2);
Christopher Haster 11:f08e03081748 470 }
Christopher Haster 11:f08e03081748 471 operator bool(void) const {
Christopher Haster 11:f08e03081748 472 return static_cast<bool>(_function);
Christopher Haster 11:f08e03081748 473 }
Christopher Haster 11:f08e03081748 474 #endif
Christopher Haster 11:f08e03081748 475 private:
Christopher Haster 11:f08e03081748 476 // Static thunks for various function types
Christopher Haster 15:1ce23ed6859a 477 static R staticthunk(void*, void *func, A1 a1, A2 a2) {
Christopher Haster 11:f08e03081748 478 R (*f)(A1, A2) = *reinterpret_cast<R (**)(A1, A2)>(func);
Christopher Haster 11:f08e03081748 479 return f(a1, a2);
Christopher Haster 11:f08e03081748 480 }
Christopher Haster 11:f08e03081748 481
Christopher Haster 11:f08e03081748 482 template<typename T>
Christopher Haster 11:f08e03081748 483 static R boundthunk(void *object, void *func, A1 a1, A2 a2) {
Christopher Haster 11:f08e03081748 484 T *o = static_cast<T*>(object);
Christopher Haster 17:fe43695d093a 485 R (*f)(T*, A1, A2) = *reinterpret_cast<R (**)(T*, A1, A2)>(func);
Christopher Haster 11:f08e03081748 486 return f(o, a1);
Christopher Haster 11:f08e03081748 487 }
Christopher Haster 11:f08e03081748 488
Christopher Haster 11:f08e03081748 489 template<typename T>
Christopher Haster 11:f08e03081748 490 static R methodthunk(void *object, void *member, A1 a1, A2 a2) {
Christopher Haster 11:f08e03081748 491 T* o = static_cast<T*>(object);
Christopher Haster 11:f08e03081748 492 R (T::*m)(A1, A2) = *reinterpret_cast<R (T::**)(A1, A2)>(member);
Christopher Haster 11:f08e03081748 493 return (o->*m)(a1, a2);
Christopher Haster 11:f08e03081748 494 }
Christopher Haster 11:f08e03081748 495
Christopher Haster 11:f08e03081748 496 // Forward declaration of an unknown class
Christopher Haster 11:f08e03081748 497 // this kind of declaration is authorized by the standard (see 8.3.3/2 of C++ 03 standard).
Christopher Haster 11:f08e03081748 498 // As a result, the compiler will allocate for UnknownFunctionMember_t the biggest size
Christopher Haster 11:f08e03081748 499 // and biggest alignment possible for member function.
Christopher Haster 11:f08e03081748 500 // This type can be used inside unions, it will help to provide the storage
Christopher Haster 11:f08e03081748 501 // with the proper size and alignment guarantees
Christopher Haster 11:f08e03081748 502 class UnknownClass;
Christopher Haster 11:f08e03081748 503
Christopher Haster 11:f08e03081748 504 // object this pointer
Christopher Haster 11:f08e03081748 505 void *_object;
Christopher Haster 11:f08e03081748 506
Christopher Haster 11:f08e03081748 507 // aligned raw member function pointer storage - converted back by registered thunk
Christopher Haster 11:f08e03081748 508 char _function[sizeof(void (UnknownClass::*)())];
Christopher Haster 11:f08e03081748 509
Christopher Haster 11:f08e03081748 510 // registered function to convert back and call _m.member on _object
Christopher Haster 11:f08e03081748 511 R (*_thunk)(void*, void*, A1, A2);
Christopher Haster 11:f08e03081748 512 };
Christopher Haster 11:f08e03081748 513
Christopher Haster 11:f08e03081748 514 /** A class for storing and calling a pointer to a static or member function
Christopher Haster 11:f08e03081748 515 */
Christopher Haster 11:f08e03081748 516 template <typename R, typename A1>
Christopher Haster 14:4af7fef9cf08 517 class FuncPtr<R(A1)> {
Christopher Haster 11:f08e03081748 518 public:
Christopher Haster 14:4af7fef9cf08 519 /** Create a FuncPtr, attaching a static function
Christopher Haster 11:f08e03081748 520 *
Christopher Haster 11:f08e03081748 521 * @param function The static function to attach (default is none)
Christopher Haster 11:f08e03081748 522 */
Christopher Haster 14:4af7fef9cf08 523 FuncPtr(R (*function)(A1) = 0) {
Christopher Haster 11:f08e03081748 524 attach(function);
Christopher Haster 11:f08e03081748 525 }
Christopher Haster 11:f08e03081748 526
Christopher Haster 14:4af7fef9cf08 527 /** Create a FuncPtr, attaching a static function with bound pointer
Christopher Haster 11:f08e03081748 528 *
Christopher Haster 11:f08e03081748 529 * @param object Pointer to object to bind to function
Christopher Haster 11:f08e03081748 530 * @param function The static function to attach
Christopher Haster 11:f08e03081748 531 */
Christopher Haster 11:f08e03081748 532 template<typename T>
Christopher Haster 14:4af7fef9cf08 533 FuncPtr(T *object, R (*function)(T*, A1)) {
Christopher Haster 11:f08e03081748 534 attach(object, function);
Christopher Haster 11:f08e03081748 535 }
Christopher Haster 11:f08e03081748 536
Christopher Haster 14:4af7fef9cf08 537 /** Create a FuncPtr, attaching a member function
Christopher Haster 11:f08e03081748 538 *
Christopher Haster 11:f08e03081748 539 * @param object The object pointer to invoke the member function on (i.e. the this pointer)
Christopher Haster 11:f08e03081748 540 * @param function The address of the member function to attach
Christopher Haster 11:f08e03081748 541 */
Christopher Haster 11:f08e03081748 542 template<typename T>
Christopher Haster 14:4af7fef9cf08 543 FuncPtr(T *object, R (T::*member)(A1)) {
Christopher Haster 11:f08e03081748 544 attach(object, member);
Christopher Haster 11:f08e03081748 545 }
Christopher Haster 11:f08e03081748 546
Christopher Haster 19:f1c94b98286f 547 /** Create a FuncPtr, attaching a function object
Christopher Haster 19:f1c94b98286f 548 *
Christopher Haster 19:f1c94b98286f 549 * @param object Pointer to a function object to attach
Christopher Haster 19:f1c94b98286f 550 */
Christopher Haster 19:f1c94b98286f 551 template<typename T>
Christopher Haster 19:f1c94b98286f 552 FuncPtr(T *object) {
Christopher Haster 19:f1c94b98286f 553 attach(object, &T::operator());
Christopher Haster 19:f1c94b98286f 554 }
Christopher Haster 19:f1c94b98286f 555
Christopher Haster 14:4af7fef9cf08 556 /** Create a FuncPtr from another FuncPtr
Christopher Haster 11:f08e03081748 557 *
Christopher Haster 11:f08e03081748 558 * @param func The func to attach
Christopher Haster 11:f08e03081748 559 */
Christopher Haster 14:4af7fef9cf08 560 FuncPtr(const FuncPtr<R(A1)> &func) {
Christopher Haster 11:f08e03081748 561 attach(func);
Christopher Haster 11:f08e03081748 562 }
Christopher Haster 11:f08e03081748 563
Christopher Haster 11:f08e03081748 564 /** Attach a static function
Christopher Haster 11:f08e03081748 565 *
Christopher Haster 11:f08e03081748 566 * @param function The static function to attach (default is none)
Christopher Haster 11:f08e03081748 567 */
Christopher Haster 11:f08e03081748 568 void attach(R (*function)(A1)) {
Christopher Haster 11:f08e03081748 569 _object = 0;
Christopher Haster 18:8c5ec1e88a9c 570 memcpy(&_function, &function, sizeof function);
Christopher Haster 14:4af7fef9cf08 571 _thunk = &FuncPtr::staticthunk;
Christopher Haster 11:f08e03081748 572 }
Christopher Haster 11:f08e03081748 573
Christopher Haster 11:f08e03081748 574 /** Attach a static function with bound pointer
Christopher Haster 11:f08e03081748 575 *
Christopher Haster 11:f08e03081748 576 * @param object Pointer to object to bind to function
Christopher Haster 11:f08e03081748 577 * @param function The static function to attach
Christopher Haster 11:f08e03081748 578 */
Christopher Haster 11:f08e03081748 579 template <typename T>
Christopher Haster 15:1ce23ed6859a 580 void attach(T *object, R (*function)(T*, A1)) {
Christopher Haster 11:f08e03081748 581 _object = static_cast<void*>(object);
Christopher Haster 18:8c5ec1e88a9c 582 memcpy(&_function, &function, sizeof function);
Christopher Haster 14:4af7fef9cf08 583 _thunk = &FuncPtr::boundthunk<T>;
Christopher Haster 11:f08e03081748 584 }
Christopher Haster 11:f08e03081748 585
Christopher Haster 11:f08e03081748 586 /** Attach a member function
Christopher Haster 11:f08e03081748 587 *
Christopher Haster 11:f08e03081748 588 * @param object The object pointer to invoke the member function on (i.e. the this pointer)
Christopher Haster 11:f08e03081748 589 * @param function The address of the member function to attach
Christopher Haster 11:f08e03081748 590 */
Christopher Haster 11:f08e03081748 591 template<typename T>
Christopher Haster 11:f08e03081748 592 void attach(T *object, R (T::*method)(A1)) {
Christopher Haster 11:f08e03081748 593 _object = static_cast<void*>(object);
Christopher Haster 18:8c5ec1e88a9c 594 memcpy(&_function, &method, sizeof method);
Christopher Haster 14:4af7fef9cf08 595 _thunk = &FuncPtr::methodthunk<T>;
Christopher Haster 11:f08e03081748 596 }
Christopher Haster 11:f08e03081748 597
Christopher Haster 19:f1c94b98286f 598 /** Attach a function object
Christopher Haster 19:f1c94b98286f 599 *
Christopher Haster 19:f1c94b98286f 600 * @param object Pointer to a function object to attach
Christopher Haster 19:f1c94b98286f 601 */
Christopher Haster 19:f1c94b98286f 602 template<typename T>
Christopher Haster 19:f1c94b98286f 603 void attach(T *object) {
Christopher Haster 19:f1c94b98286f 604 attach(object, &T::operator());
Christopher Haster 19:f1c94b98286f 605 }
Christopher Haster 19:f1c94b98286f 606
Christopher Haster 14:4af7fef9cf08 607 /** Attach a FuncPtr
Christopher Haster 11:f08e03081748 608 *
Christopher Haster 11:f08e03081748 609 * @param func The func to attach
Christopher Haster 11:f08e03081748 610 */
Christopher Haster 14:4af7fef9cf08 611 void attach(const FuncPtr<R(A1)> &func) {
Christopher Haster 11:f08e03081748 612 _object = func._object;
Christopher Haster 18:8c5ec1e88a9c 613 memcpy(&_function, &func._function, sizeof _function);
Christopher Haster 11:f08e03081748 614 _thunk = func._thunk;
Christopher Haster 11:f08e03081748 615 }
Christopher Haster 11:f08e03081748 616
Christopher Haster 11:f08e03081748 617 /** Call the attached static or member function
Christopher Haster 11:f08e03081748 618 */
Christopher Haster 11:f08e03081748 619 R call(A1 a1) {
Christopher Haster 11:f08e03081748 620 return _thunk(_object, _function, a1);
Christopher Haster 11:f08e03081748 621 }
Christopher Haster 11:f08e03081748 622
Christopher Haster 11:f08e03081748 623 /** Get registered static function
Christopher Haster 11:f08e03081748 624 */
Christopher Haster 11:f08e03081748 625 R (*get_function(A1))() {
Christopher Haster 11:f08e03081748 626 return reinterpret_cast<R (*)(A1)>(_object ? 0 : _function);
Christopher Haster 11:f08e03081748 627 }
Christopher Haster 11:f08e03081748 628
Christopher Haster 11:f08e03081748 629 #ifdef MBED_OPERATORS
Christopher Haster 11:f08e03081748 630 R operator ()(A1 a1) {
Christopher Haster 11:f08e03081748 631 return call(a1);
Christopher Haster 11:f08e03081748 632 }
Christopher Haster 11:f08e03081748 633 operator bool(void) const {
Christopher Haster 11:f08e03081748 634 return static_cast<bool>(_function);
Christopher Haster 11:f08e03081748 635 }
Christopher Haster 11:f08e03081748 636 #endif
Christopher Haster 11:f08e03081748 637 private:
Christopher Haster 11:f08e03081748 638 // Static thunks for various function types
Christopher Haster 15:1ce23ed6859a 639 static R staticthunk(void*, void *func, A1 a1) {
Christopher Haster 11:f08e03081748 640 R (*f)(A1) = *reinterpret_cast<R (**)(A1)>(func);
Christopher Haster 11:f08e03081748 641 return f(a1);
Christopher Haster 11:f08e03081748 642 }
Christopher Haster 11:f08e03081748 643
Christopher Haster 11:f08e03081748 644 template<typename T>
Christopher Haster 11:f08e03081748 645 static R boundthunk(void *object, void *func, A1 a1) {
Christopher Haster 11:f08e03081748 646 T *o = static_cast<T*>(object);
Christopher Haster 11:f08e03081748 647 R (*f)(T*, A1) = *reinterpret_cast<R (**)(T*, A1)>(func);
Christopher Haster 11:f08e03081748 648 return f(o, a1);
Christopher Haster 11:f08e03081748 649 }
Christopher Haster 11:f08e03081748 650
Christopher Haster 11:f08e03081748 651 template<typename T>
Christopher Haster 11:f08e03081748 652 static R methodthunk(void *object, void *member, A1 a1) {
Christopher Haster 11:f08e03081748 653 T* o = static_cast<T*>(object);
Christopher Haster 11:f08e03081748 654 R (T::*m)(A1) = *reinterpret_cast<R (T::**)(A1)>(member);
Christopher Haster 11:f08e03081748 655 return (o->*m)(a1);
Christopher Haster 11:f08e03081748 656 }
Christopher Haster 11:f08e03081748 657
Christopher Haster 11:f08e03081748 658 // Forward declaration of an unknown class
Christopher Haster 11:f08e03081748 659 // this kind of declaration is authorized by the standard (see 8.3.3/2 of C++ 03 standard).
Christopher Haster 11:f08e03081748 660 // As a result, the compiler will allocate for UnknownFunctionMember_t the biggest size
Christopher Haster 11:f08e03081748 661 // and biggest alignment possible for member function.
Christopher Haster 11:f08e03081748 662 // This type can be used inside unions, it will help to provide the storage
Christopher Haster 11:f08e03081748 663 // with the proper size and alignment guarantees
Christopher Haster 11:f08e03081748 664 class UnknownClass;
Christopher Haster 11:f08e03081748 665
Christopher Haster 11:f08e03081748 666 // object this pointer
Christopher Haster 11:f08e03081748 667 void *_object;
Christopher Haster 11:f08e03081748 668
Christopher Haster 11:f08e03081748 669 // aligned raw member function pointer storage - converted back by registered thunk
Christopher Haster 11:f08e03081748 670 char _function[sizeof(void (UnknownClass::*)())];
Christopher Haster 11:f08e03081748 671
Christopher Haster 11:f08e03081748 672 // registered function to convert back and call _m.member on _object
Christopher Haster 11:f08e03081748 673 R (*_thunk)(void*, void*, A1);
Christopher Haster 11:f08e03081748 674 };
Christopher Haster 11:f08e03081748 675
Christopher Haster 11:f08e03081748 676 /** A class for storing and calling a pointer to a static or member function
Christopher Haster 11:f08e03081748 677 */
Christopher Haster 11:f08e03081748 678 template <typename R>
Christopher Haster 14:4af7fef9cf08 679 class FuncPtr<R()> {
Christopher Haster 11:f08e03081748 680 public:
Christopher Haster 14:4af7fef9cf08 681 /** Create a FuncPtr, attaching a static function
Christopher Haster 11:f08e03081748 682 *
Christopher Haster 11:f08e03081748 683 * @param function The static function to attach (default is none)
Christopher Haster 11:f08e03081748 684 */
Christopher Haster 14:4af7fef9cf08 685 FuncPtr(R (*function)() = 0) {
Christopher Haster 11:f08e03081748 686 attach(function);
Christopher Haster 11:f08e03081748 687 }
Christopher Haster 11:f08e03081748 688
Christopher Haster 14:4af7fef9cf08 689 /** Create a FuncPtr, attaching a static function with bound pointer
Christopher Haster 11:f08e03081748 690 *
Christopher Haster 11:f08e03081748 691 * @param object Pointer to object to bind to function
Christopher Haster 11:f08e03081748 692 * @param function The static function to attach
Christopher Haster 11:f08e03081748 693 */
Christopher Haster 11:f08e03081748 694 template<typename T>
Christopher Haster 14:4af7fef9cf08 695 FuncPtr(T *object, R (*function)(T*)) {
Christopher Haster 11:f08e03081748 696 attach(object, function);
Christopher Haster 11:f08e03081748 697 }
Christopher Haster 11:f08e03081748 698
Christopher Haster 14:4af7fef9cf08 699 /** Create a FuncPtr, attaching a member function
Christopher Haster 11:f08e03081748 700 *
Christopher Haster 11:f08e03081748 701 * @param object The object pointer to invoke the member function on (i.e. the this pointer)
Christopher Haster 11:f08e03081748 702 * @param function The address of the member function to attach
Christopher Haster 11:f08e03081748 703 */
Christopher Haster 11:f08e03081748 704 template<typename T>
Christopher Haster 14:4af7fef9cf08 705 FuncPtr(T *object, R (T::*member)()) {
Christopher Haster 11:f08e03081748 706 attach(object, member);
Christopher Haster 11:f08e03081748 707 }
Christopher Haster 11:f08e03081748 708
Christopher Haster 19:f1c94b98286f 709 /** Create a FuncPtr, attaching a function object
Christopher Haster 19:f1c94b98286f 710 *
Christopher Haster 19:f1c94b98286f 711 * @param object Pointer to a function object to attach
Christopher Haster 19:f1c94b98286f 712 */
Christopher Haster 19:f1c94b98286f 713 template<typename T>
Christopher Haster 19:f1c94b98286f 714 FuncPtr(T *object) {
Christopher Haster 19:f1c94b98286f 715 attach(object, &T::operator());
Christopher Haster 19:f1c94b98286f 716 }
Christopher Haster 19:f1c94b98286f 717
Christopher Haster 14:4af7fef9cf08 718 /** Create a FuncPtr from another FuncPtr
Christopher Haster 11:f08e03081748 719 *
Christopher Haster 11:f08e03081748 720 * @param func The func to attach
Christopher Haster 11:f08e03081748 721 */
Christopher Haster 14:4af7fef9cf08 722 FuncPtr(const FuncPtr<R()> &func) {
Christopher Haster 11:f08e03081748 723 attach(func);
Christopher Haster 11:f08e03081748 724 }
Christopher Haster 11:f08e03081748 725
Christopher Haster 11:f08e03081748 726 /** Attach a static function
Christopher Haster 11:f08e03081748 727 *
Christopher Haster 11:f08e03081748 728 * @param function The static function to attach (default is none)
Christopher Haster 11:f08e03081748 729 */
Christopher Haster 11:f08e03081748 730 void attach(R (*function)()) {
Christopher Haster 11:f08e03081748 731 _object = 0;
Christopher Haster 18:8c5ec1e88a9c 732 memcpy(&_function, &function, sizeof function);
Christopher Haster 14:4af7fef9cf08 733 _thunk = &FuncPtr::staticthunk;
Christopher Haster 11:f08e03081748 734 }
Christopher Haster 11:f08e03081748 735
Christopher Haster 11:f08e03081748 736 /** Attach a static function with bound pointer
Christopher Haster 11:f08e03081748 737 *
Christopher Haster 11:f08e03081748 738 * @param object Pointer to object to bind to function
Christopher Haster 11:f08e03081748 739 * @param function The static function to attach
Christopher Haster 11:f08e03081748 740 */
Christopher Haster 11:f08e03081748 741 template <typename T>
Christopher Haster 15:1ce23ed6859a 742 void attach(T *object, R (*function)(T*)) {
Christopher Haster 11:f08e03081748 743 _object = static_cast<void*>(object);
Christopher Haster 18:8c5ec1e88a9c 744 memcpy(&_function, &function, sizeof function);
Christopher Haster 14:4af7fef9cf08 745 _thunk = &FuncPtr::boundthunk<T>;
Christopher Haster 11:f08e03081748 746 }
Christopher Haster 11:f08e03081748 747
Christopher Haster 11:f08e03081748 748 /** Attach a member function
Christopher Haster 11:f08e03081748 749 *
Christopher Haster 11:f08e03081748 750 * @param object The object pointer to invoke the member function on (i.e. the this pointer)
Christopher Haster 11:f08e03081748 751 * @param function The address of the member function to attach
Christopher Haster 11:f08e03081748 752 */
Christopher Haster 11:f08e03081748 753 template<typename T>
Christopher Haster 11:f08e03081748 754 void attach(T *object, R (T::*method)()) {
Christopher Haster 11:f08e03081748 755 _object = static_cast<void*>(object);
Christopher Haster 18:8c5ec1e88a9c 756 memcpy(&_function, &method, sizeof method);
Christopher Haster 14:4af7fef9cf08 757 _thunk = &FuncPtr::methodthunk<T>;
Christopher Haster 11:f08e03081748 758 }
Christopher Haster 11:f08e03081748 759
Christopher Haster 19:f1c94b98286f 760 /** Attach a function object
Christopher Haster 19:f1c94b98286f 761 *
Christopher Haster 19:f1c94b98286f 762 * @param object Pointer to a function object to attach
Christopher Haster 19:f1c94b98286f 763 */
Christopher Haster 19:f1c94b98286f 764 template<typename T>
Christopher Haster 19:f1c94b98286f 765 void attach(T *object) {
Christopher Haster 19:f1c94b98286f 766 attach(object, &T::operator());
Christopher Haster 19:f1c94b98286f 767 }
Christopher Haster 19:f1c94b98286f 768
Christopher Haster 14:4af7fef9cf08 769 /** Attach a FuncPtr
Christopher Haster 11:f08e03081748 770 *
Christopher Haster 11:f08e03081748 771 * @param func The func to attach
Christopher Haster 11:f08e03081748 772 */
Christopher Haster 14:4af7fef9cf08 773 void attach(const FuncPtr<R()> &func) {
Christopher Haster 11:f08e03081748 774 _object = func._object;
Christopher Haster 18:8c5ec1e88a9c 775 memcpy(&_function, &func._function, sizeof _function);
Christopher Haster 11:f08e03081748 776 _thunk = func._thunk;
Christopher Haster 11:f08e03081748 777 }
Christopher Haster 11:f08e03081748 778
Christopher Haster 11:f08e03081748 779 /** Call the attached static or member function
Christopher Haster 11:f08e03081748 780 */
Christopher Haster 11:f08e03081748 781 R call() {
Christopher Haster 11:f08e03081748 782 return _thunk(_object, _function);
Christopher Haster 11:f08e03081748 783 }
Christopher Haster 11:f08e03081748 784
Christopher Haster 11:f08e03081748 785 /** Get registered static function
Christopher Haster 11:f08e03081748 786 */
Christopher Haster 11:f08e03081748 787 R (*get_function())() {
Christopher Haster 11:f08e03081748 788 return reinterpret_cast<R (*)()>(_object ? 0 : _function);
Christopher Haster 11:f08e03081748 789 }
Christopher Haster 11:f08e03081748 790
Christopher Haster 11:f08e03081748 791 #ifdef MBED_OPERATORS
Christopher Haster 11:f08e03081748 792 R operator ()() {
Christopher Haster 11:f08e03081748 793 return call();
Christopher Haster 11:f08e03081748 794 }
Christopher Haster 11:f08e03081748 795 operator bool(void) const {
Christopher Haster 11:f08e03081748 796 return static_cast<bool>(_function);
Christopher Haster 11:f08e03081748 797 }
Christopher Haster 11:f08e03081748 798 #endif
Christopher Haster 11:f08e03081748 799 private:
Christopher Haster 11:f08e03081748 800 // Static thunks for various function types
Christopher Haster 15:1ce23ed6859a 801 static R staticthunk(void*, void *func) {
Christopher Haster 11:f08e03081748 802 R (*f)() = *reinterpret_cast<R (**)()>(func);
Christopher Haster 11:f08e03081748 803 return f();
Christopher Haster 11:f08e03081748 804 }
Christopher Haster 11:f08e03081748 805
Christopher Haster 11:f08e03081748 806 template<typename T>
Christopher Haster 11:f08e03081748 807 static R boundthunk(void *object, void *func) {
Christopher Haster 11:f08e03081748 808 T *o = static_cast<T*>(object);
Christopher Haster 11:f08e03081748 809 R (*f)(T*) = *reinterpret_cast<R (**)(T*)>(func);
Christopher Haster 11:f08e03081748 810 return f(o);
Christopher Haster 11:f08e03081748 811 }
Christopher Haster 11:f08e03081748 812
Christopher Haster 11:f08e03081748 813 template<typename T>
Christopher Haster 11:f08e03081748 814 static R methodthunk(void *object, void *member) {
Christopher Haster 11:f08e03081748 815 T* o = static_cast<T*>(object);
Christopher Haster 11:f08e03081748 816 R (T::*m)() = *reinterpret_cast<R (T::**)()>(member);
Christopher Haster 11:f08e03081748 817 return (o->*m)();
Christopher Haster 11:f08e03081748 818 }
Christopher Haster 11:f08e03081748 819
Christopher Haster 11:f08e03081748 820 // Forward declaration of an unknown class
Christopher Haster 11:f08e03081748 821 // this kind of declaration is authorized by the standard (see 8.3.3/2 of C++ 03 standard).
Christopher Haster 11:f08e03081748 822 // As a result, the compiler will allocate for UnknownFunctionMember_t the biggest size
Christopher Haster 11:f08e03081748 823 // and biggest alignment possible for member function.
Christopher Haster 11:f08e03081748 824 // This type can be used inside unions, it will help to provide the storage
Christopher Haster 11:f08e03081748 825 // with the proper size and alignment guarantees
Christopher Haster 11:f08e03081748 826 class UnknownClass;
Christopher Haster 11:f08e03081748 827
Christopher Haster 11:f08e03081748 828 // object this pointer
Christopher Haster 11:f08e03081748 829 void *_object;
Christopher Haster 11:f08e03081748 830
Christopher Haster 11:f08e03081748 831 // aligned raw member function pointer storage - converted back by registered thunk
Christopher Haster 11:f08e03081748 832 union {
Christopher Haster 11:f08e03081748 833 char _function[sizeof(void (UnknownClass::*)())];
Christopher Haster 11:f08e03081748 834 void (UnknownClass::*_unknownMethod)();
Christopher Haster 11:f08e03081748 835 };
Christopher Haster 11:f08e03081748 836
Christopher Haster 11:f08e03081748 837 // registered function to convert back and call _m.member on _object
Christopher Haster 11:f08e03081748 838 R (*_thunk)(void*, void*);
Christopher Haster 11:f08e03081748 839 };
Christopher Haster 11:f08e03081748 840
Christopher Haster 6:c2a3aa792960 841 // Overloads for backwards compatibility
Christopher Haster 6:c2a3aa792960 842 template <typename R, typename A1>
Christopher Haster 14:4af7fef9cf08 843 class FunctionPointerArg1 : public FuncPtr<R(A1)> {};
Christopher Haster 6:c2a3aa792960 844
Christopher Haster 6:c2a3aa792960 845 template <typename R>
Christopher Haster 14:4af7fef9cf08 846 class FunctionPointerArg1<R, void> : public FuncPtr<R()> {};
Christopher Haster 6:c2a3aa792960 847
Christopher Haster 14:4af7fef9cf08 848 typedef FuncPtr<void()> FunctionPointer;
Christopher Haster 14:4af7fef9cf08 849 typedef FuncPtr<void(int)> event_callback_t;
screamer 0:9c59db1fbc9e 850
screamer 0:9c59db1fbc9e 851 } // namespace mbed
screamer 0:9c59db1fbc9e 852
screamer 0:9c59db1fbc9e 853 #endif