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.
Dependencies: target-freescale
Fork of mbed-hal by
api/FunctionPointer.h@15:1ce23ed6859a, 2016-04-01 (annotated)
- Committer:
- Christopher Haster
- Date:
- Fri Apr 01 01:16:52 2016 -0500
- Revision:
- 15:1ce23ed6859a
- Parent:
- 14:4af7fef9cf08
- Child:
- 17:fe43695d093a
Removed unused variable warnings
Who changed what in which revision?
User | Revision | Line number | New 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 |
14:4af7fef9cf08 | 61 | /** Create a FuncPtr from another FuncPtr |
Christopher Haster |
11:f08e03081748 | 62 | * |
Christopher Haster |
11:f08e03081748 | 63 | * @param func The func to attach |
Christopher Haster |
11:f08e03081748 | 64 | */ |
Christopher Haster |
14:4af7fef9cf08 | 65 | FuncPtr(const FuncPtr<R(A1, A2, A3, A4)> &func) { |
Christopher Haster |
11:f08e03081748 | 66 | attach(func); |
Christopher Haster |
11:f08e03081748 | 67 | } |
Christopher Haster |
11:f08e03081748 | 68 | |
Christopher Haster |
11:f08e03081748 | 69 | /** Attach a static function |
Christopher Haster |
11:f08e03081748 | 70 | * |
Christopher Haster |
11:f08e03081748 | 71 | * @param function The static function to attach (default is none) |
Christopher Haster |
11:f08e03081748 | 72 | */ |
Christopher Haster |
11:f08e03081748 | 73 | void attach(R (*function)(A1, A2, A3, A4)) { |
Christopher Haster |
11:f08e03081748 | 74 | _object = 0; |
Christopher Haster |
11:f08e03081748 | 75 | *reinterpret_cast<R (**)(A1)>(_function) = function; |
Christopher Haster |
14:4af7fef9cf08 | 76 | _thunk = &FuncPtr::staticthunk; |
Christopher Haster |
11:f08e03081748 | 77 | } |
Christopher Haster |
11:f08e03081748 | 78 | |
Christopher Haster |
11:f08e03081748 | 79 | /** Attach a static function with bound pointer |
Christopher Haster |
11:f08e03081748 | 80 | * |
Christopher Haster |
11:f08e03081748 | 81 | * @param object Pointer to object to bind to function |
Christopher Haster |
11:f08e03081748 | 82 | * @param function The static function to attach |
Christopher Haster |
11:f08e03081748 | 83 | */ |
Christopher Haster |
11:f08e03081748 | 84 | template <typename T> |
Christopher Haster |
15:1ce23ed6859a | 85 | void attach(T *object, R (*function)(T*, A1, A2, A3, A4)) { |
Christopher Haster |
11:f08e03081748 | 86 | _object = static_cast<void*>(object); |
Christopher Haster |
11:f08e03081748 | 87 | *reinterpret_cast<R (**)(T*, A1)>(_function) = function; |
Christopher Haster |
14:4af7fef9cf08 | 88 | _thunk = &FuncPtr::boundthunk<T>; |
Christopher Haster |
11:f08e03081748 | 89 | } |
Christopher Haster |
11:f08e03081748 | 90 | |
Christopher Haster |
11:f08e03081748 | 91 | /** Attach a member function |
Christopher Haster |
11:f08e03081748 | 92 | * |
Christopher Haster |
11:f08e03081748 | 93 | * @param object The object pointer to invoke the member function on (i.e. the this pointer) |
Christopher Haster |
11:f08e03081748 | 94 | * @param function The address of the member function to attach |
Christopher Haster |
11:f08e03081748 | 95 | */ |
Christopher Haster |
11:f08e03081748 | 96 | template<typename T> |
Christopher Haster |
11:f08e03081748 | 97 | void attach(T *object, R (T::*method)(A1, A2, A3, A4)) { |
Christopher Haster |
11:f08e03081748 | 98 | _object = static_cast<void*>(object); |
Christopher Haster |
11:f08e03081748 | 99 | *reinterpret_cast<R (T::**)(A1)>(_function) = method; |
Christopher Haster |
14:4af7fef9cf08 | 100 | _thunk = &FuncPtr::methodthunk<T>; |
Christopher Haster |
11:f08e03081748 | 101 | } |
Christopher Haster |
11:f08e03081748 | 102 | |
Christopher Haster |
14:4af7fef9cf08 | 103 | /** Attach a FuncPtr |
Christopher Haster |
11:f08e03081748 | 104 | * |
Christopher Haster |
11:f08e03081748 | 105 | * @param func The func to attach |
Christopher Haster |
11:f08e03081748 | 106 | */ |
Christopher Haster |
14:4af7fef9cf08 | 107 | void attach(const FuncPtr<R(A1, A2, A3, A4)> &func) { |
Christopher Haster |
11:f08e03081748 | 108 | _object = func._object; |
Christopher Haster |
11:f08e03081748 | 109 | memcpy(_function, func._function, sizeof _function); |
Christopher Haster |
11:f08e03081748 | 110 | _thunk = func._thunk; |
Christopher Haster |
11:f08e03081748 | 111 | } |
Christopher Haster |
11:f08e03081748 | 112 | |
Christopher Haster |
11:f08e03081748 | 113 | /** Call the attached static or member function |
Christopher Haster |
11:f08e03081748 | 114 | */ |
Christopher Haster |
11:f08e03081748 | 115 | R call(A1 a1, A2 a2, A3 a3, A4 a4) { |
Christopher Haster |
11:f08e03081748 | 116 | return _thunk(_object, _function, a1, a2, a3, a4); |
Christopher Haster |
11:f08e03081748 | 117 | } |
Christopher Haster |
11:f08e03081748 | 118 | |
Christopher Haster |
11:f08e03081748 | 119 | /** Get registered static function |
Christopher Haster |
11:f08e03081748 | 120 | */ |
Christopher Haster |
11:f08e03081748 | 121 | R (*get_function(A1, A2, A3, A4))() { |
Christopher Haster |
11:f08e03081748 | 122 | return reinterpret_cast<R (*)(A1, A2, A3, A4)>(_object ? 0 : _function); |
Christopher Haster |
11:f08e03081748 | 123 | } |
Christopher Haster |
11:f08e03081748 | 124 | |
Christopher Haster |
11:f08e03081748 | 125 | #ifdef MBED_OPERATORS |
Christopher Haster |
11:f08e03081748 | 126 | R operator ()(A1 a1, A2 a2, A3 a3, A4 a4) { |
Christopher Haster |
11:f08e03081748 | 127 | return call(a1, a2, a3, a4); |
Christopher Haster |
11:f08e03081748 | 128 | } |
Christopher Haster |
11:f08e03081748 | 129 | operator bool(void) const { |
Christopher Haster |
11:f08e03081748 | 130 | return static_cast<bool>(_function); |
Christopher Haster |
11:f08e03081748 | 131 | } |
Christopher Haster |
11:f08e03081748 | 132 | #endif |
Christopher Haster |
11:f08e03081748 | 133 | private: |
Christopher Haster |
11:f08e03081748 | 134 | // Static thunks for various function types |
Christopher Haster |
15:1ce23ed6859a | 135 | static R staticthunk(void*, void *func, A1 a1, A2 a2, A3 a3, A4 a4) { |
Christopher Haster |
11:f08e03081748 | 136 | R (*f)(A1, A2, A3, A4) = *reinterpret_cast<R (**)(A1, A2, A3, A4)>(func); |
Christopher Haster |
11:f08e03081748 | 137 | return f(a1, a2, a3, a4); |
Christopher Haster |
11:f08e03081748 | 138 | } |
Christopher Haster |
11:f08e03081748 | 139 | |
Christopher Haster |
11:f08e03081748 | 140 | template<typename T> |
Christopher Haster |
11:f08e03081748 | 141 | static R boundthunk(void *object, void *func, A1 a1, A2 a2, A3 a3, A4 a4) { |
Christopher Haster |
11:f08e03081748 | 142 | T *o = static_cast<T*>(object); |
Christopher Haster |
11:f08e03081748 | 143 | R (*f)(T*, A1) = *reinterpret_cast<R (**)(T*, A1)>(func); |
Christopher Haster |
11:f08e03081748 | 144 | return f(o, a1); |
Christopher Haster |
11:f08e03081748 | 145 | } |
Christopher Haster |
11:f08e03081748 | 146 | |
Christopher Haster |
11:f08e03081748 | 147 | template<typename T> |
Christopher Haster |
11:f08e03081748 | 148 | static R methodthunk(void *object, void *member, A1 a1, A2 a2, A3 a3, A4 a4) { |
Christopher Haster |
11:f08e03081748 | 149 | T* o = static_cast<T*>(object); |
Christopher Haster |
11:f08e03081748 | 150 | R (T::*m)(A1, A2, A3, A4) = *reinterpret_cast<R (T::**)(A1, A2, A3, A4)>(member); |
Christopher Haster |
11:f08e03081748 | 151 | return (o->*m)(a1, a2, a3, a4); |
Christopher Haster |
11:f08e03081748 | 152 | } |
Christopher Haster |
11:f08e03081748 | 153 | |
Christopher Haster |
11:f08e03081748 | 154 | // Forward declaration of an unknown class |
Christopher Haster |
11:f08e03081748 | 155 | // this kind of declaration is authorized by the standard (see 8.3.3/2 of C++ 03 standard). |
Christopher Haster |
11:f08e03081748 | 156 | // As a result, the compiler will allocate for UnknownFunctionMember_t the biggest size |
Christopher Haster |
11:f08e03081748 | 157 | // and biggest alignment possible for member function. |
Christopher Haster |
11:f08e03081748 | 158 | // This type can be used inside unions, it will help to provide the storage |
Christopher Haster |
11:f08e03081748 | 159 | // with the proper size and alignment guarantees |
Christopher Haster |
11:f08e03081748 | 160 | class UnknownClass; |
Christopher Haster |
11:f08e03081748 | 161 | |
Christopher Haster |
11:f08e03081748 | 162 | // object this pointer |
Christopher Haster |
11:f08e03081748 | 163 | void *_object; |
Christopher Haster |
11:f08e03081748 | 164 | |
Christopher Haster |
11:f08e03081748 | 165 | // aligned raw member function pointer storage - converted back by registered thunk |
Christopher Haster |
11:f08e03081748 | 166 | char _function[sizeof(void (UnknownClass::*)())]; |
Christopher Haster |
11:f08e03081748 | 167 | |
Christopher Haster |
11:f08e03081748 | 168 | // registered function to convert back and call _m.member on _object |
Christopher Haster |
11:f08e03081748 | 169 | R (*_thunk)(void*, void*, A1, A2, A3, A4); |
Christopher Haster |
11:f08e03081748 | 170 | }; |
Christopher Haster |
11:f08e03081748 | 171 | |
Christopher Haster |
11:f08e03081748 | 172 | /** A class for storing and calling a pointer to a static or member function |
Christopher Haster |
11:f08e03081748 | 173 | */ |
Christopher Haster |
11:f08e03081748 | 174 | template <typename R, typename A1, typename A2, typename A3> |
Christopher Haster |
14:4af7fef9cf08 | 175 | class FuncPtr<R(A1, A2, A3)> { |
Christopher Haster |
11:f08e03081748 | 176 | public: |
Christopher Haster |
14:4af7fef9cf08 | 177 | /** Create a FuncPtr, attaching a static function |
Christopher Haster |
11:f08e03081748 | 178 | * |
Christopher Haster |
11:f08e03081748 | 179 | * @param function The static function to attach (default is none) |
Christopher Haster |
11:f08e03081748 | 180 | */ |
Christopher Haster |
14:4af7fef9cf08 | 181 | FuncPtr(R (*function)(A1, A2, A3) = 0) { |
Christopher Haster |
11:f08e03081748 | 182 | attach(function); |
Christopher Haster |
11:f08e03081748 | 183 | } |
Christopher Haster |
11:f08e03081748 | 184 | |
Christopher Haster |
14:4af7fef9cf08 | 185 | /** Create a FuncPtr, attaching a static function with bound pointer |
Christopher Haster |
11:f08e03081748 | 186 | * |
Christopher Haster |
11:f08e03081748 | 187 | * @param object Pointer to object to bind to function |
Christopher Haster |
11:f08e03081748 | 188 | * @param function The static function to attach |
Christopher Haster |
11:f08e03081748 | 189 | */ |
Christopher Haster |
11:f08e03081748 | 190 | template<typename T> |
Christopher Haster |
14:4af7fef9cf08 | 191 | FuncPtr(T *object, R (*function)(T*, A1, A2, A3)) { |
Christopher Haster |
11:f08e03081748 | 192 | attach(object, function); |
Christopher Haster |
11:f08e03081748 | 193 | } |
Christopher Haster |
11:f08e03081748 | 194 | |
Christopher Haster |
14:4af7fef9cf08 | 195 | /** Create a FuncPtr, attaching a member function |
Christopher Haster |
11:f08e03081748 | 196 | * |
Christopher Haster |
11:f08e03081748 | 197 | * @param object The object pointer to invoke the member function on (i.e. the this pointer) |
Christopher Haster |
11:f08e03081748 | 198 | * @param function The address of the member function to attach |
Christopher Haster |
11:f08e03081748 | 199 | */ |
Christopher Haster |
11:f08e03081748 | 200 | template<typename T> |
Christopher Haster |
14:4af7fef9cf08 | 201 | FuncPtr(T *object, R (T::*member)(A1, A2, A3)) { |
Christopher Haster |
11:f08e03081748 | 202 | attach(object, member); |
Christopher Haster |
11:f08e03081748 | 203 | } |
Christopher Haster |
11:f08e03081748 | 204 | |
Christopher Haster |
14:4af7fef9cf08 | 205 | /** Create a FuncPtr from another FuncPtr |
Christopher Haster |
11:f08e03081748 | 206 | * |
Christopher Haster |
11:f08e03081748 | 207 | * @param func The func to attach |
Christopher Haster |
11:f08e03081748 | 208 | */ |
Christopher Haster |
14:4af7fef9cf08 | 209 | FuncPtr(const FuncPtr<R(A1, A2, A3)> &func) { |
Christopher Haster |
11:f08e03081748 | 210 | attach(func); |
Christopher Haster |
11:f08e03081748 | 211 | } |
Christopher Haster |
11:f08e03081748 | 212 | |
Christopher Haster |
11:f08e03081748 | 213 | /** Attach a static function |
Christopher Haster |
11:f08e03081748 | 214 | * |
Christopher Haster |
11:f08e03081748 | 215 | * @param function The static function to attach (default is none) |
Christopher Haster |
11:f08e03081748 | 216 | */ |
Christopher Haster |
11:f08e03081748 | 217 | void attach(R (*function)(A1, A2, A3)) { |
Christopher Haster |
11:f08e03081748 | 218 | _object = 0; |
Christopher Haster |
11:f08e03081748 | 219 | *reinterpret_cast<R (**)(A1)>(_function) = function; |
Christopher Haster |
14:4af7fef9cf08 | 220 | _thunk = &FuncPtr::staticthunk; |
Christopher Haster |
11:f08e03081748 | 221 | } |
Christopher Haster |
11:f08e03081748 | 222 | |
Christopher Haster |
11:f08e03081748 | 223 | /** Attach a static function with bound pointer |
Christopher Haster |
11:f08e03081748 | 224 | * |
Christopher Haster |
11:f08e03081748 | 225 | * @param object Pointer to object to bind to function |
Christopher Haster |
11:f08e03081748 | 226 | * @param function The static function to attach |
Christopher Haster |
11:f08e03081748 | 227 | */ |
Christopher Haster |
11:f08e03081748 | 228 | template <typename T> |
Christopher Haster |
15:1ce23ed6859a | 229 | void attach(T *object, R (*function)(T*, A1, A2, A3)) { |
Christopher Haster |
11:f08e03081748 | 230 | _object = static_cast<void*>(object); |
Christopher Haster |
11:f08e03081748 | 231 | *reinterpret_cast<R (**)(T*, A1)>(_function) = function; |
Christopher Haster |
14:4af7fef9cf08 | 232 | _thunk = &FuncPtr::boundthunk<T>; |
Christopher Haster |
11:f08e03081748 | 233 | } |
Christopher Haster |
11:f08e03081748 | 234 | |
Christopher Haster |
11:f08e03081748 | 235 | /** Attach a member function |
Christopher Haster |
11:f08e03081748 | 236 | * |
Christopher Haster |
11:f08e03081748 | 237 | * @param object The object pointer to invoke the member function on (i.e. the this pointer) |
Christopher Haster |
11:f08e03081748 | 238 | * @param function The address of the member function to attach |
Christopher Haster |
11:f08e03081748 | 239 | */ |
Christopher Haster |
11:f08e03081748 | 240 | template<typename T> |
Christopher Haster |
11:f08e03081748 | 241 | void attach(T *object, R (T::*method)(A1, A2, A3)) { |
Christopher Haster |
11:f08e03081748 | 242 | _object = static_cast<void*>(object); |
Christopher Haster |
11:f08e03081748 | 243 | *reinterpret_cast<R (T::**)(A1)>(_function) = method; |
Christopher Haster |
14:4af7fef9cf08 | 244 | _thunk = &FuncPtr::methodthunk<T>; |
Christopher Haster |
11:f08e03081748 | 245 | } |
Christopher Haster |
11:f08e03081748 | 246 | |
Christopher Haster |
14:4af7fef9cf08 | 247 | /** Attach a FuncPtr |
Christopher Haster |
11:f08e03081748 | 248 | * |
Christopher Haster |
11:f08e03081748 | 249 | * @param func The func to attach |
Christopher Haster |
11:f08e03081748 | 250 | */ |
Christopher Haster |
14:4af7fef9cf08 | 251 | void attach(const FuncPtr<R(A1, A2, A3)> &func) { |
Christopher Haster |
11:f08e03081748 | 252 | _object = func._object; |
Christopher Haster |
11:f08e03081748 | 253 | memcpy(_function, func._function, sizeof _function); |
Christopher Haster |
11:f08e03081748 | 254 | _thunk = func._thunk; |
Christopher Haster |
11:f08e03081748 | 255 | } |
Christopher Haster |
11:f08e03081748 | 256 | |
Christopher Haster |
11:f08e03081748 | 257 | /** Call the attached static or member function |
Christopher Haster |
11:f08e03081748 | 258 | */ |
Christopher Haster |
11:f08e03081748 | 259 | R call(A1 a1, A2 a2, A3 a3) { |
Christopher Haster |
11:f08e03081748 | 260 | return _thunk(_object, _function, a1, a2, a3); |
Christopher Haster |
11:f08e03081748 | 261 | } |
Christopher Haster |
11:f08e03081748 | 262 | |
Christopher Haster |
11:f08e03081748 | 263 | /** Get registered static function |
Christopher Haster |
11:f08e03081748 | 264 | */ |
Christopher Haster |
11:f08e03081748 | 265 | R (*get_function(A1, A2, A3))() { |
Christopher Haster |
11:f08e03081748 | 266 | return reinterpret_cast<R (*)(A1, A2, A3)>(_object ? 0 : _function); |
Christopher Haster |
11:f08e03081748 | 267 | } |
Christopher Haster |
11:f08e03081748 | 268 | |
Christopher Haster |
11:f08e03081748 | 269 | #ifdef MBED_OPERATORS |
Christopher Haster |
11:f08e03081748 | 270 | R operator ()(A1 a1, A2 a2, A3 a3) { |
Christopher Haster |
11:f08e03081748 | 271 | return call(a1, a2, a3); |
Christopher Haster |
11:f08e03081748 | 272 | } |
Christopher Haster |
11:f08e03081748 | 273 | operator bool(void) const { |
Christopher Haster |
11:f08e03081748 | 274 | return static_cast<bool>(_function); |
Christopher Haster |
11:f08e03081748 | 275 | } |
Christopher Haster |
11:f08e03081748 | 276 | #endif |
Christopher Haster |
11:f08e03081748 | 277 | private: |
Christopher Haster |
11:f08e03081748 | 278 | // Static thunks for various function types |
Christopher Haster |
15:1ce23ed6859a | 279 | static R staticthunk(void*, void *func, A1 a1, A2 a2, A3 a3) { |
Christopher Haster |
11:f08e03081748 | 280 | R (*f)(A1, A2, A3) = *reinterpret_cast<R (**)(A1, A2, A3)>(func); |
Christopher Haster |
11:f08e03081748 | 281 | return f(a1, a2, a3); |
Christopher Haster |
11:f08e03081748 | 282 | } |
Christopher Haster |
11:f08e03081748 | 283 | |
Christopher Haster |
11:f08e03081748 | 284 | template<typename T> |
Christopher Haster |
11:f08e03081748 | 285 | static R boundthunk(void *object, void *func, A1 a1, A2 a2, A3 a3) { |
Christopher Haster |
11:f08e03081748 | 286 | T *o = static_cast<T*>(object); |
Christopher Haster |
11:f08e03081748 | 287 | R (*f)(T*, A1) = *reinterpret_cast<R (**)(T*, A1)>(func); |
Christopher Haster |
11:f08e03081748 | 288 | return f(o, a1); |
Christopher Haster |
11:f08e03081748 | 289 | } |
Christopher Haster |
11:f08e03081748 | 290 | |
Christopher Haster |
11:f08e03081748 | 291 | template<typename T> |
Christopher Haster |
11:f08e03081748 | 292 | static R methodthunk(void *object, void *member, A1 a1, A2 a2, A3 a3) { |
Christopher Haster |
11:f08e03081748 | 293 | T* o = static_cast<T*>(object); |
Christopher Haster |
11:f08e03081748 | 294 | R (T::*m)(A1, A2, A3) = *reinterpret_cast<R (T::**)(A1, A2, A3)>(member); |
Christopher Haster |
11:f08e03081748 | 295 | return (o->*m)(a1, a2, a3); |
Christopher Haster |
11:f08e03081748 | 296 | } |
Christopher Haster |
11:f08e03081748 | 297 | |
Christopher Haster |
11:f08e03081748 | 298 | // Forward declaration of an unknown class |
Christopher Haster |
11:f08e03081748 | 299 | // this kind of declaration is authorized by the standard (see 8.3.3/2 of C++ 03 standard). |
Christopher Haster |
11:f08e03081748 | 300 | // As a result, the compiler will allocate for UnknownFunctionMember_t the biggest size |
Christopher Haster |
11:f08e03081748 | 301 | // and biggest alignment possible for member function. |
Christopher Haster |
11:f08e03081748 | 302 | // This type can be used inside unions, it will help to provide the storage |
Christopher Haster |
11:f08e03081748 | 303 | // with the proper size and alignment guarantees |
Christopher Haster |
11:f08e03081748 | 304 | class UnknownClass; |
Christopher Haster |
11:f08e03081748 | 305 | |
Christopher Haster |
11:f08e03081748 | 306 | // object this pointer |
Christopher Haster |
11:f08e03081748 | 307 | void *_object; |
Christopher Haster |
11:f08e03081748 | 308 | |
Christopher Haster |
11:f08e03081748 | 309 | // aligned raw member function pointer storage - converted back by registered thunk |
Christopher Haster |
11:f08e03081748 | 310 | char _function[sizeof(void (UnknownClass::*)())]; |
Christopher Haster |
11:f08e03081748 | 311 | |
Christopher Haster |
11:f08e03081748 | 312 | // registered function to convert back and call _m.member on _object |
Christopher Haster |
11:f08e03081748 | 313 | R (*_thunk)(void*, void*, A1, A2, A3); |
Christopher Haster |
11:f08e03081748 | 314 | }; |
Christopher Haster |
11:f08e03081748 | 315 | |
Christopher Haster |
11:f08e03081748 | 316 | /** A class for storing and calling a pointer to a static or member function |
Christopher Haster |
11:f08e03081748 | 317 | */ |
Christopher Haster |
11:f08e03081748 | 318 | template <typename R, typename A1, typename A2> |
Christopher Haster |
14:4af7fef9cf08 | 319 | class FuncPtr<R(A1, A2)> { |
Christopher Haster |
11:f08e03081748 | 320 | public: |
Christopher Haster |
14:4af7fef9cf08 | 321 | /** Create a FuncPtr, attaching a static function |
Christopher Haster |
11:f08e03081748 | 322 | * |
Christopher Haster |
11:f08e03081748 | 323 | * @param function The static function to attach (default is none) |
Christopher Haster |
11:f08e03081748 | 324 | */ |
Christopher Haster |
14:4af7fef9cf08 | 325 | FuncPtr(R (*function)(A1, A2) = 0) { |
Christopher Haster |
11:f08e03081748 | 326 | attach(function); |
Christopher Haster |
11:f08e03081748 | 327 | } |
Christopher Haster |
11:f08e03081748 | 328 | |
Christopher Haster |
14:4af7fef9cf08 | 329 | /** Create a FuncPtr, attaching a static function with bound pointer |
Christopher Haster |
11:f08e03081748 | 330 | * |
Christopher Haster |
11:f08e03081748 | 331 | * @param object Pointer to object to bind to function |
Christopher Haster |
11:f08e03081748 | 332 | * @param function The static function to attach |
Christopher Haster |
11:f08e03081748 | 333 | */ |
Christopher Haster |
11:f08e03081748 | 334 | template<typename T> |
Christopher Haster |
14:4af7fef9cf08 | 335 | FuncPtr(T *object, R (*function)(T*, A1, A2)) { |
Christopher Haster |
11:f08e03081748 | 336 | attach(object, function); |
Christopher Haster |
11:f08e03081748 | 337 | } |
Christopher Haster |
11:f08e03081748 | 338 | |
Christopher Haster |
14:4af7fef9cf08 | 339 | /** Create a FuncPtr, attaching a member function |
Christopher Haster |
11:f08e03081748 | 340 | * |
Christopher Haster |
11:f08e03081748 | 341 | * @param object The object pointer to invoke the member function on (i.e. the this pointer) |
Christopher Haster |
11:f08e03081748 | 342 | * @param function The address of the member function to attach |
Christopher Haster |
11:f08e03081748 | 343 | */ |
Christopher Haster |
11:f08e03081748 | 344 | template<typename T> |
Christopher Haster |
14:4af7fef9cf08 | 345 | FuncPtr(T *object, R (T::*member)(A1, A2)) { |
Christopher Haster |
11:f08e03081748 | 346 | attach(object, member); |
Christopher Haster |
11:f08e03081748 | 347 | } |
Christopher Haster |
11:f08e03081748 | 348 | |
Christopher Haster |
14:4af7fef9cf08 | 349 | /** Create a FuncPtr from another FuncPtr |
Christopher Haster |
11:f08e03081748 | 350 | * |
Christopher Haster |
11:f08e03081748 | 351 | * @param func The func to attach |
Christopher Haster |
11:f08e03081748 | 352 | */ |
Christopher Haster |
14:4af7fef9cf08 | 353 | FuncPtr(const FuncPtr<R(A1, A2)> &func) { |
Christopher Haster |
11:f08e03081748 | 354 | attach(func); |
Christopher Haster |
11:f08e03081748 | 355 | } |
Christopher Haster |
11:f08e03081748 | 356 | |
Christopher Haster |
11:f08e03081748 | 357 | /** Attach 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 |
11:f08e03081748 | 361 | void attach(R (*function)(A1, A2)) { |
Christopher Haster |
11:f08e03081748 | 362 | _object = 0; |
Christopher Haster |
11:f08e03081748 | 363 | *reinterpret_cast<R (**)(A1)>(_function) = function; |
Christopher Haster |
14:4af7fef9cf08 | 364 | _thunk = &FuncPtr::staticthunk; |
Christopher Haster |
11:f08e03081748 | 365 | } |
Christopher Haster |
11:f08e03081748 | 366 | |
Christopher Haster |
11:f08e03081748 | 367 | /** Attach a static function with bound pointer |
Christopher Haster |
11:f08e03081748 | 368 | * |
Christopher Haster |
11:f08e03081748 | 369 | * @param object Pointer to object to bind to function |
Christopher Haster |
11:f08e03081748 | 370 | * @param function The static function to attach |
Christopher Haster |
11:f08e03081748 | 371 | */ |
Christopher Haster |
11:f08e03081748 | 372 | template <typename T> |
Christopher Haster |
15:1ce23ed6859a | 373 | void attach(T *object, R (*function)(T*, A1, A2)) { |
Christopher Haster |
11:f08e03081748 | 374 | _object = static_cast<void*>(object); |
Christopher Haster |
11:f08e03081748 | 375 | *reinterpret_cast<R (**)(T*, A1)>(_function) = function; |
Christopher Haster |
14:4af7fef9cf08 | 376 | _thunk = &FuncPtr::boundthunk<T>; |
Christopher Haster |
11:f08e03081748 | 377 | } |
Christopher Haster |
11:f08e03081748 | 378 | |
Christopher Haster |
11:f08e03081748 | 379 | /** Attach a member function |
Christopher Haster |
11:f08e03081748 | 380 | * |
Christopher Haster |
11:f08e03081748 | 381 | * @param object The object pointer to invoke the member function on (i.e. the this pointer) |
Christopher Haster |
11:f08e03081748 | 382 | * @param function The address of the member function to attach |
Christopher Haster |
11:f08e03081748 | 383 | */ |
Christopher Haster |
11:f08e03081748 | 384 | template<typename T> |
Christopher Haster |
11:f08e03081748 | 385 | void attach(T *object, R (T::*method)(A1, A2)) { |
Christopher Haster |
11:f08e03081748 | 386 | _object = static_cast<void*>(object); |
Christopher Haster |
11:f08e03081748 | 387 | *reinterpret_cast<R (T::**)(A1)>(_function) = method; |
Christopher Haster |
14:4af7fef9cf08 | 388 | _thunk = &FuncPtr::methodthunk<T>; |
Christopher Haster |
11:f08e03081748 | 389 | } |
Christopher Haster |
11:f08e03081748 | 390 | |
Christopher Haster |
14:4af7fef9cf08 | 391 | /** Attach a FuncPtr |
Christopher Haster |
11:f08e03081748 | 392 | * |
Christopher Haster |
11:f08e03081748 | 393 | * @param func The func to attach |
Christopher Haster |
11:f08e03081748 | 394 | */ |
Christopher Haster |
14:4af7fef9cf08 | 395 | void attach(const FuncPtr<R(A1, A2)> &func) { |
Christopher Haster |
11:f08e03081748 | 396 | _object = func._object; |
Christopher Haster |
11:f08e03081748 | 397 | memcpy(_function, func._function, sizeof _function); |
Christopher Haster |
11:f08e03081748 | 398 | _thunk = func._thunk; |
Christopher Haster |
11:f08e03081748 | 399 | } |
Christopher Haster |
11:f08e03081748 | 400 | |
Christopher Haster |
11:f08e03081748 | 401 | /** Call the attached static or member function |
Christopher Haster |
11:f08e03081748 | 402 | */ |
Christopher Haster |
11:f08e03081748 | 403 | R call(A1 a1, A2 a2) { |
Christopher Haster |
11:f08e03081748 | 404 | return _thunk(_object, _function, a1, a2); |
Christopher Haster |
11:f08e03081748 | 405 | } |
Christopher Haster |
11:f08e03081748 | 406 | |
Christopher Haster |
11:f08e03081748 | 407 | /** Get registered static function |
Christopher Haster |
11:f08e03081748 | 408 | */ |
Christopher Haster |
11:f08e03081748 | 409 | R (*get_function(A1, A2))() { |
Christopher Haster |
11:f08e03081748 | 410 | return reinterpret_cast<R (*)(A1, A2)>(_object ? 0 : _function); |
Christopher Haster |
11:f08e03081748 | 411 | } |
Christopher Haster |
11:f08e03081748 | 412 | |
Christopher Haster |
11:f08e03081748 | 413 | #ifdef MBED_OPERATORS |
Christopher Haster |
11:f08e03081748 | 414 | R operator ()(A1 a1, A2 a2) { |
Christopher Haster |
11:f08e03081748 | 415 | return call(a1, a2); |
Christopher Haster |
11:f08e03081748 | 416 | } |
Christopher Haster |
11:f08e03081748 | 417 | operator bool(void) const { |
Christopher Haster |
11:f08e03081748 | 418 | return static_cast<bool>(_function); |
Christopher Haster |
11:f08e03081748 | 419 | } |
Christopher Haster |
11:f08e03081748 | 420 | #endif |
Christopher Haster |
11:f08e03081748 | 421 | private: |
Christopher Haster |
11:f08e03081748 | 422 | // Static thunks for various function types |
Christopher Haster |
15:1ce23ed6859a | 423 | static R staticthunk(void*, void *func, A1 a1, A2 a2) { |
Christopher Haster |
11:f08e03081748 | 424 | R (*f)(A1, A2) = *reinterpret_cast<R (**)(A1, A2)>(func); |
Christopher Haster |
11:f08e03081748 | 425 | return f(a1, a2); |
Christopher Haster |
11:f08e03081748 | 426 | } |
Christopher Haster |
11:f08e03081748 | 427 | |
Christopher Haster |
11:f08e03081748 | 428 | template<typename T> |
Christopher Haster |
11:f08e03081748 | 429 | static R boundthunk(void *object, void *func, A1 a1, A2 a2) { |
Christopher Haster |
11:f08e03081748 | 430 | T *o = static_cast<T*>(object); |
Christopher Haster |
11:f08e03081748 | 431 | R (*f)(T*, A1) = *reinterpret_cast<R (**)(T*, A1)>(func); |
Christopher Haster |
11:f08e03081748 | 432 | return f(o, a1); |
Christopher Haster |
11:f08e03081748 | 433 | } |
Christopher Haster |
11:f08e03081748 | 434 | |
Christopher Haster |
11:f08e03081748 | 435 | template<typename T> |
Christopher Haster |
11:f08e03081748 | 436 | static R methodthunk(void *object, void *member, A1 a1, A2 a2) { |
Christopher Haster |
11:f08e03081748 | 437 | T* o = static_cast<T*>(object); |
Christopher Haster |
11:f08e03081748 | 438 | R (T::*m)(A1, A2) = *reinterpret_cast<R (T::**)(A1, A2)>(member); |
Christopher Haster |
11:f08e03081748 | 439 | return (o->*m)(a1, a2); |
Christopher Haster |
11:f08e03081748 | 440 | } |
Christopher Haster |
11:f08e03081748 | 441 | |
Christopher Haster |
11:f08e03081748 | 442 | // Forward declaration of an unknown class |
Christopher Haster |
11:f08e03081748 | 443 | // this kind of declaration is authorized by the standard (see 8.3.3/2 of C++ 03 standard). |
Christopher Haster |
11:f08e03081748 | 444 | // As a result, the compiler will allocate for UnknownFunctionMember_t the biggest size |
Christopher Haster |
11:f08e03081748 | 445 | // and biggest alignment possible for member function. |
Christopher Haster |
11:f08e03081748 | 446 | // This type can be used inside unions, it will help to provide the storage |
Christopher Haster |
11:f08e03081748 | 447 | // with the proper size and alignment guarantees |
Christopher Haster |
11:f08e03081748 | 448 | class UnknownClass; |
Christopher Haster |
11:f08e03081748 | 449 | |
Christopher Haster |
11:f08e03081748 | 450 | // object this pointer |
Christopher Haster |
11:f08e03081748 | 451 | void *_object; |
Christopher Haster |
11:f08e03081748 | 452 | |
Christopher Haster |
11:f08e03081748 | 453 | // aligned raw member function pointer storage - converted back by registered thunk |
Christopher Haster |
11:f08e03081748 | 454 | char _function[sizeof(void (UnknownClass::*)())]; |
Christopher Haster |
11:f08e03081748 | 455 | |
Christopher Haster |
11:f08e03081748 | 456 | // registered function to convert back and call _m.member on _object |
Christopher Haster |
11:f08e03081748 | 457 | R (*_thunk)(void*, void*, A1, A2); |
Christopher Haster |
11:f08e03081748 | 458 | }; |
Christopher Haster |
11:f08e03081748 | 459 | |
Christopher Haster |
11:f08e03081748 | 460 | /** A class for storing and calling a pointer to a static or member function |
Christopher Haster |
11:f08e03081748 | 461 | */ |
Christopher Haster |
11:f08e03081748 | 462 | template <typename R, typename A1> |
Christopher Haster |
14:4af7fef9cf08 | 463 | class FuncPtr<R(A1)> { |
Christopher Haster |
11:f08e03081748 | 464 | public: |
Christopher Haster |
14:4af7fef9cf08 | 465 | /** Create a FuncPtr, attaching a static function |
Christopher Haster |
11:f08e03081748 | 466 | * |
Christopher Haster |
11:f08e03081748 | 467 | * @param function The static function to attach (default is none) |
Christopher Haster |
11:f08e03081748 | 468 | */ |
Christopher Haster |
14:4af7fef9cf08 | 469 | FuncPtr(R (*function)(A1) = 0) { |
Christopher Haster |
11:f08e03081748 | 470 | attach(function); |
Christopher Haster |
11:f08e03081748 | 471 | } |
Christopher Haster |
11:f08e03081748 | 472 | |
Christopher Haster |
14:4af7fef9cf08 | 473 | /** Create a FuncPtr, attaching a static function with bound pointer |
Christopher Haster |
11:f08e03081748 | 474 | * |
Christopher Haster |
11:f08e03081748 | 475 | * @param object Pointer to object to bind to function |
Christopher Haster |
11:f08e03081748 | 476 | * @param function The static function to attach |
Christopher Haster |
11:f08e03081748 | 477 | */ |
Christopher Haster |
11:f08e03081748 | 478 | template<typename T> |
Christopher Haster |
14:4af7fef9cf08 | 479 | FuncPtr(T *object, R (*function)(T*, A1)) { |
Christopher Haster |
11:f08e03081748 | 480 | attach(object, function); |
Christopher Haster |
11:f08e03081748 | 481 | } |
Christopher Haster |
11:f08e03081748 | 482 | |
Christopher Haster |
14:4af7fef9cf08 | 483 | /** Create a FuncPtr, attaching a member function |
Christopher Haster |
11:f08e03081748 | 484 | * |
Christopher Haster |
11:f08e03081748 | 485 | * @param object The object pointer to invoke the member function on (i.e. the this pointer) |
Christopher Haster |
11:f08e03081748 | 486 | * @param function The address of the member function to attach |
Christopher Haster |
11:f08e03081748 | 487 | */ |
Christopher Haster |
11:f08e03081748 | 488 | template<typename T> |
Christopher Haster |
14:4af7fef9cf08 | 489 | FuncPtr(T *object, R (T::*member)(A1)) { |
Christopher Haster |
11:f08e03081748 | 490 | attach(object, member); |
Christopher Haster |
11:f08e03081748 | 491 | } |
Christopher Haster |
11:f08e03081748 | 492 | |
Christopher Haster |
14:4af7fef9cf08 | 493 | /** Create a FuncPtr from another FuncPtr |
Christopher Haster |
11:f08e03081748 | 494 | * |
Christopher Haster |
11:f08e03081748 | 495 | * @param func The func to attach |
Christopher Haster |
11:f08e03081748 | 496 | */ |
Christopher Haster |
14:4af7fef9cf08 | 497 | FuncPtr(const FuncPtr<R(A1)> &func) { |
Christopher Haster |
11:f08e03081748 | 498 | attach(func); |
Christopher Haster |
11:f08e03081748 | 499 | } |
Christopher Haster |
11:f08e03081748 | 500 | |
Christopher Haster |
11:f08e03081748 | 501 | /** Attach a static function |
Christopher Haster |
11:f08e03081748 | 502 | * |
Christopher Haster |
11:f08e03081748 | 503 | * @param function The static function to attach (default is none) |
Christopher Haster |
11:f08e03081748 | 504 | */ |
Christopher Haster |
11:f08e03081748 | 505 | void attach(R (*function)(A1)) { |
Christopher Haster |
11:f08e03081748 | 506 | _object = 0; |
Christopher Haster |
11:f08e03081748 | 507 | *reinterpret_cast<R (**)(A1)>(_function) = function; |
Christopher Haster |
14:4af7fef9cf08 | 508 | _thunk = &FuncPtr::staticthunk; |
Christopher Haster |
11:f08e03081748 | 509 | } |
Christopher Haster |
11:f08e03081748 | 510 | |
Christopher Haster |
11:f08e03081748 | 511 | /** Attach a static function with bound pointer |
Christopher Haster |
11:f08e03081748 | 512 | * |
Christopher Haster |
11:f08e03081748 | 513 | * @param object Pointer to object to bind to function |
Christopher Haster |
11:f08e03081748 | 514 | * @param function The static function to attach |
Christopher Haster |
11:f08e03081748 | 515 | */ |
Christopher Haster |
11:f08e03081748 | 516 | template <typename T> |
Christopher Haster |
15:1ce23ed6859a | 517 | void attach(T *object, R (*function)(T*, A1)) { |
Christopher Haster |
11:f08e03081748 | 518 | _object = static_cast<void*>(object); |
Christopher Haster |
11:f08e03081748 | 519 | *reinterpret_cast<R (**)(T*, A1)>(_function) = function; |
Christopher Haster |
14:4af7fef9cf08 | 520 | _thunk = &FuncPtr::boundthunk<T>; |
Christopher Haster |
11:f08e03081748 | 521 | } |
Christopher Haster |
11:f08e03081748 | 522 | |
Christopher Haster |
11:f08e03081748 | 523 | /** Attach a member function |
Christopher Haster |
11:f08e03081748 | 524 | * |
Christopher Haster |
11:f08e03081748 | 525 | * @param object The object pointer to invoke the member function on (i.e. the this pointer) |
Christopher Haster |
11:f08e03081748 | 526 | * @param function The address of the member function to attach |
Christopher Haster |
11:f08e03081748 | 527 | */ |
Christopher Haster |
11:f08e03081748 | 528 | template<typename T> |
Christopher Haster |
11:f08e03081748 | 529 | void attach(T *object, R (T::*method)(A1)) { |
Christopher Haster |
11:f08e03081748 | 530 | _object = static_cast<void*>(object); |
Christopher Haster |
11:f08e03081748 | 531 | *reinterpret_cast<R (T::**)(A1)>(_function) = method; |
Christopher Haster |
14:4af7fef9cf08 | 532 | _thunk = &FuncPtr::methodthunk<T>; |
Christopher Haster |
11:f08e03081748 | 533 | } |
Christopher Haster |
11:f08e03081748 | 534 | |
Christopher Haster |
14:4af7fef9cf08 | 535 | /** Attach a FuncPtr |
Christopher Haster |
11:f08e03081748 | 536 | * |
Christopher Haster |
11:f08e03081748 | 537 | * @param func The func to attach |
Christopher Haster |
11:f08e03081748 | 538 | */ |
Christopher Haster |
14:4af7fef9cf08 | 539 | void attach(const FuncPtr<R(A1)> &func) { |
Christopher Haster |
11:f08e03081748 | 540 | _object = func._object; |
Christopher Haster |
11:f08e03081748 | 541 | memcpy(_function, func._function, sizeof _function); |
Christopher Haster |
11:f08e03081748 | 542 | _thunk = func._thunk; |
Christopher Haster |
11:f08e03081748 | 543 | } |
Christopher Haster |
11:f08e03081748 | 544 | |
Christopher Haster |
11:f08e03081748 | 545 | /** Call the attached static or member function |
Christopher Haster |
11:f08e03081748 | 546 | */ |
Christopher Haster |
11:f08e03081748 | 547 | R call(A1 a1) { |
Christopher Haster |
11:f08e03081748 | 548 | return _thunk(_object, _function, a1); |
Christopher Haster |
11:f08e03081748 | 549 | } |
Christopher Haster |
11:f08e03081748 | 550 | |
Christopher Haster |
11:f08e03081748 | 551 | /** Get registered static function |
Christopher Haster |
11:f08e03081748 | 552 | */ |
Christopher Haster |
11:f08e03081748 | 553 | R (*get_function(A1))() { |
Christopher Haster |
11:f08e03081748 | 554 | return reinterpret_cast<R (*)(A1)>(_object ? 0 : _function); |
Christopher Haster |
11:f08e03081748 | 555 | } |
Christopher Haster |
11:f08e03081748 | 556 | |
Christopher Haster |
11:f08e03081748 | 557 | #ifdef MBED_OPERATORS |
Christopher Haster |
11:f08e03081748 | 558 | R operator ()(A1 a1) { |
Christopher Haster |
11:f08e03081748 | 559 | return call(a1); |
Christopher Haster |
11:f08e03081748 | 560 | } |
Christopher Haster |
11:f08e03081748 | 561 | operator bool(void) const { |
Christopher Haster |
11:f08e03081748 | 562 | return static_cast<bool>(_function); |
Christopher Haster |
11:f08e03081748 | 563 | } |
Christopher Haster |
11:f08e03081748 | 564 | #endif |
Christopher Haster |
11:f08e03081748 | 565 | private: |
Christopher Haster |
11:f08e03081748 | 566 | // Static thunks for various function types |
Christopher Haster |
15:1ce23ed6859a | 567 | static R staticthunk(void*, void *func, A1 a1) { |
Christopher Haster |
11:f08e03081748 | 568 | R (*f)(A1) = *reinterpret_cast<R (**)(A1)>(func); |
Christopher Haster |
11:f08e03081748 | 569 | return f(a1); |
Christopher Haster |
11:f08e03081748 | 570 | } |
Christopher Haster |
11:f08e03081748 | 571 | |
Christopher Haster |
11:f08e03081748 | 572 | template<typename T> |
Christopher Haster |
11:f08e03081748 | 573 | static R boundthunk(void *object, void *func, A1 a1) { |
Christopher Haster |
11:f08e03081748 | 574 | T *o = static_cast<T*>(object); |
Christopher Haster |
11:f08e03081748 | 575 | R (*f)(T*, A1) = *reinterpret_cast<R (**)(T*, A1)>(func); |
Christopher Haster |
11:f08e03081748 | 576 | return f(o, a1); |
Christopher Haster |
11:f08e03081748 | 577 | } |
Christopher Haster |
11:f08e03081748 | 578 | |
Christopher Haster |
11:f08e03081748 | 579 | template<typename T> |
Christopher Haster |
11:f08e03081748 | 580 | static R methodthunk(void *object, void *member, A1 a1) { |
Christopher Haster |
11:f08e03081748 | 581 | T* o = static_cast<T*>(object); |
Christopher Haster |
11:f08e03081748 | 582 | R (T::*m)(A1) = *reinterpret_cast<R (T::**)(A1)>(member); |
Christopher Haster |
11:f08e03081748 | 583 | return (o->*m)(a1); |
Christopher Haster |
11:f08e03081748 | 584 | } |
Christopher Haster |
11:f08e03081748 | 585 | |
Christopher Haster |
11:f08e03081748 | 586 | // Forward declaration of an unknown class |
Christopher Haster |
11:f08e03081748 | 587 | // this kind of declaration is authorized by the standard (see 8.3.3/2 of C++ 03 standard). |
Christopher Haster |
11:f08e03081748 | 588 | // As a result, the compiler will allocate for UnknownFunctionMember_t the biggest size |
Christopher Haster |
11:f08e03081748 | 589 | // and biggest alignment possible for member function. |
Christopher Haster |
11:f08e03081748 | 590 | // This type can be used inside unions, it will help to provide the storage |
Christopher Haster |
11:f08e03081748 | 591 | // with the proper size and alignment guarantees |
Christopher Haster |
11:f08e03081748 | 592 | class UnknownClass; |
Christopher Haster |
11:f08e03081748 | 593 | |
Christopher Haster |
11:f08e03081748 | 594 | // object this pointer |
Christopher Haster |
11:f08e03081748 | 595 | void *_object; |
Christopher Haster |
11:f08e03081748 | 596 | |
Christopher Haster |
11:f08e03081748 | 597 | // aligned raw member function pointer storage - converted back by registered thunk |
Christopher Haster |
11:f08e03081748 | 598 | char _function[sizeof(void (UnknownClass::*)())]; |
Christopher Haster |
11:f08e03081748 | 599 | |
Christopher Haster |
11:f08e03081748 | 600 | // registered function to convert back and call _m.member on _object |
Christopher Haster |
11:f08e03081748 | 601 | R (*_thunk)(void*, void*, A1); |
Christopher Haster |
11:f08e03081748 | 602 | }; |
Christopher Haster |
11:f08e03081748 | 603 | |
Christopher Haster |
11:f08e03081748 | 604 | /** A class for storing and calling a pointer to a static or member function |
Christopher Haster |
11:f08e03081748 | 605 | */ |
Christopher Haster |
11:f08e03081748 | 606 | template <typename R> |
Christopher Haster |
14:4af7fef9cf08 | 607 | class FuncPtr<R()> { |
Christopher Haster |
11:f08e03081748 | 608 | public: |
Christopher Haster |
14:4af7fef9cf08 | 609 | /** Create a FuncPtr, attaching a static function |
Christopher Haster |
11:f08e03081748 | 610 | * |
Christopher Haster |
11:f08e03081748 | 611 | * @param function The static function to attach (default is none) |
Christopher Haster |
11:f08e03081748 | 612 | */ |
Christopher Haster |
14:4af7fef9cf08 | 613 | FuncPtr(R (*function)() = 0) { |
Christopher Haster |
11:f08e03081748 | 614 | attach(function); |
Christopher Haster |
11:f08e03081748 | 615 | } |
Christopher Haster |
11:f08e03081748 | 616 | |
Christopher Haster |
14:4af7fef9cf08 | 617 | /** Create a FuncPtr, attaching a static function with bound pointer |
Christopher Haster |
11:f08e03081748 | 618 | * |
Christopher Haster |
11:f08e03081748 | 619 | * @param object Pointer to object to bind to function |
Christopher Haster |
11:f08e03081748 | 620 | * @param function The static function to attach |
Christopher Haster |
11:f08e03081748 | 621 | */ |
Christopher Haster |
11:f08e03081748 | 622 | template<typename T> |
Christopher Haster |
14:4af7fef9cf08 | 623 | FuncPtr(T *object, R (*function)(T*)) { |
Christopher Haster |
11:f08e03081748 | 624 | attach(object, function); |
Christopher Haster |
11:f08e03081748 | 625 | } |
Christopher Haster |
11:f08e03081748 | 626 | |
Christopher Haster |
14:4af7fef9cf08 | 627 | /** Create a FuncPtr, attaching a member function |
Christopher Haster |
11:f08e03081748 | 628 | * |
Christopher Haster |
11:f08e03081748 | 629 | * @param object The object pointer to invoke the member function on (i.e. the this pointer) |
Christopher Haster |
11:f08e03081748 | 630 | * @param function The address of the member function to attach |
Christopher Haster |
11:f08e03081748 | 631 | */ |
Christopher Haster |
11:f08e03081748 | 632 | template<typename T> |
Christopher Haster |
14:4af7fef9cf08 | 633 | FuncPtr(T *object, R (T::*member)()) { |
Christopher Haster |
11:f08e03081748 | 634 | attach(object, member); |
Christopher Haster |
11:f08e03081748 | 635 | } |
Christopher Haster |
11:f08e03081748 | 636 | |
Christopher Haster |
14:4af7fef9cf08 | 637 | /** Create a FuncPtr from another FuncPtr |
Christopher Haster |
11:f08e03081748 | 638 | * |
Christopher Haster |
11:f08e03081748 | 639 | * @param func The func to attach |
Christopher Haster |
11:f08e03081748 | 640 | */ |
Christopher Haster |
14:4af7fef9cf08 | 641 | FuncPtr(const FuncPtr<R()> &func) { |
Christopher Haster |
11:f08e03081748 | 642 | attach(func); |
Christopher Haster |
11:f08e03081748 | 643 | } |
Christopher Haster |
11:f08e03081748 | 644 | |
Christopher Haster |
11:f08e03081748 | 645 | /** Attach a static function |
Christopher Haster |
11:f08e03081748 | 646 | * |
Christopher Haster |
11:f08e03081748 | 647 | * @param function The static function to attach (default is none) |
Christopher Haster |
11:f08e03081748 | 648 | */ |
Christopher Haster |
11:f08e03081748 | 649 | void attach(R (*function)()) { |
Christopher Haster |
11:f08e03081748 | 650 | _object = 0; |
Christopher Haster |
11:f08e03081748 | 651 | *reinterpret_cast<R (**)()>(_function) = function; |
Christopher Haster |
14:4af7fef9cf08 | 652 | _thunk = &FuncPtr::staticthunk; |
Christopher Haster |
11:f08e03081748 | 653 | } |
Christopher Haster |
11:f08e03081748 | 654 | |
Christopher Haster |
11:f08e03081748 | 655 | /** Attach a static function with bound pointer |
Christopher Haster |
11:f08e03081748 | 656 | * |
Christopher Haster |
11:f08e03081748 | 657 | * @param object Pointer to object to bind to function |
Christopher Haster |
11:f08e03081748 | 658 | * @param function The static function to attach |
Christopher Haster |
11:f08e03081748 | 659 | */ |
Christopher Haster |
11:f08e03081748 | 660 | template <typename T> |
Christopher Haster |
15:1ce23ed6859a | 661 | void attach(T *object, R (*function)(T*)) { |
Christopher Haster |
11:f08e03081748 | 662 | _object = static_cast<void*>(object); |
Christopher Haster |
11:f08e03081748 | 663 | *reinterpret_cast<R (**)(T*)>(_function) = function; |
Christopher Haster |
14:4af7fef9cf08 | 664 | _thunk = &FuncPtr::boundthunk<T>; |
Christopher Haster |
11:f08e03081748 | 665 | } |
Christopher Haster |
11:f08e03081748 | 666 | |
Christopher Haster |
11:f08e03081748 | 667 | /** Attach a member function |
Christopher Haster |
11:f08e03081748 | 668 | * |
Christopher Haster |
11:f08e03081748 | 669 | * @param object The object pointer to invoke the member function on (i.e. the this pointer) |
Christopher Haster |
11:f08e03081748 | 670 | * @param function The address of the member function to attach |
Christopher Haster |
11:f08e03081748 | 671 | */ |
Christopher Haster |
11:f08e03081748 | 672 | template<typename T> |
Christopher Haster |
11:f08e03081748 | 673 | void attach(T *object, R (T::*method)()) { |
Christopher Haster |
11:f08e03081748 | 674 | _object = static_cast<void*>(object); |
Christopher Haster |
11:f08e03081748 | 675 | *reinterpret_cast<R (T::**)()>(_function) = method; |
Christopher Haster |
14:4af7fef9cf08 | 676 | _thunk = &FuncPtr::methodthunk<T>; |
Christopher Haster |
11:f08e03081748 | 677 | } |
Christopher Haster |
11:f08e03081748 | 678 | |
Christopher Haster |
14:4af7fef9cf08 | 679 | /** Attach a FuncPtr |
Christopher Haster |
11:f08e03081748 | 680 | * |
Christopher Haster |
11:f08e03081748 | 681 | * @param func The func to attach |
Christopher Haster |
11:f08e03081748 | 682 | */ |
Christopher Haster |
14:4af7fef9cf08 | 683 | void attach(const FuncPtr<R()> &func) { |
Christopher Haster |
11:f08e03081748 | 684 | _object = func._object; |
Christopher Haster |
11:f08e03081748 | 685 | memcpy(_function, func._function, sizeof _function); |
Christopher Haster |
11:f08e03081748 | 686 | _thunk = func._thunk; |
Christopher Haster |
11:f08e03081748 | 687 | } |
Christopher Haster |
11:f08e03081748 | 688 | |
Christopher Haster |
11:f08e03081748 | 689 | /** Call the attached static or member function |
Christopher Haster |
11:f08e03081748 | 690 | */ |
Christopher Haster |
11:f08e03081748 | 691 | R call() { |
Christopher Haster |
11:f08e03081748 | 692 | return _thunk(_object, _function); |
Christopher Haster |
11:f08e03081748 | 693 | } |
Christopher Haster |
11:f08e03081748 | 694 | |
Christopher Haster |
11:f08e03081748 | 695 | /** Get registered static function |
Christopher Haster |
11:f08e03081748 | 696 | */ |
Christopher Haster |
11:f08e03081748 | 697 | R (*get_function())() { |
Christopher Haster |
11:f08e03081748 | 698 | return reinterpret_cast<R (*)()>(_object ? 0 : _function); |
Christopher Haster |
11:f08e03081748 | 699 | } |
Christopher Haster |
11:f08e03081748 | 700 | |
Christopher Haster |
11:f08e03081748 | 701 | #ifdef MBED_OPERATORS |
Christopher Haster |
11:f08e03081748 | 702 | R operator ()() { |
Christopher Haster |
11:f08e03081748 | 703 | return call(); |
Christopher Haster |
11:f08e03081748 | 704 | } |
Christopher Haster |
11:f08e03081748 | 705 | operator bool(void) const { |
Christopher Haster |
11:f08e03081748 | 706 | return static_cast<bool>(_function); |
Christopher Haster |
11:f08e03081748 | 707 | } |
Christopher Haster |
11:f08e03081748 | 708 | #endif |
Christopher Haster |
11:f08e03081748 | 709 | private: |
Christopher Haster |
11:f08e03081748 | 710 | // Static thunks for various function types |
Christopher Haster |
15:1ce23ed6859a | 711 | static R staticthunk(void*, void *func) { |
Christopher Haster |
11:f08e03081748 | 712 | R (*f)() = *reinterpret_cast<R (**)()>(func); |
Christopher Haster |
11:f08e03081748 | 713 | return f(); |
Christopher Haster |
11:f08e03081748 | 714 | } |
Christopher Haster |
11:f08e03081748 | 715 | |
Christopher Haster |
11:f08e03081748 | 716 | template<typename T> |
Christopher Haster |
11:f08e03081748 | 717 | static R boundthunk(void *object, void *func) { |
Christopher Haster |
11:f08e03081748 | 718 | T *o = static_cast<T*>(object); |
Christopher Haster |
11:f08e03081748 | 719 | R (*f)(T*) = *reinterpret_cast<R (**)(T*)>(func); |
Christopher Haster |
11:f08e03081748 | 720 | return f(o); |
Christopher Haster |
11:f08e03081748 | 721 | } |
Christopher Haster |
11:f08e03081748 | 722 | |
Christopher Haster |
11:f08e03081748 | 723 | template<typename T> |
Christopher Haster |
11:f08e03081748 | 724 | static R methodthunk(void *object, void *member) { |
Christopher Haster |
11:f08e03081748 | 725 | T* o = static_cast<T*>(object); |
Christopher Haster |
11:f08e03081748 | 726 | R (T::*m)() = *reinterpret_cast<R (T::**)()>(member); |
Christopher Haster |
11:f08e03081748 | 727 | return (o->*m)(); |
Christopher Haster |
11:f08e03081748 | 728 | } |
Christopher Haster |
11:f08e03081748 | 729 | |
Christopher Haster |
11:f08e03081748 | 730 | // Forward declaration of an unknown class |
Christopher Haster |
11:f08e03081748 | 731 | // this kind of declaration is authorized by the standard (see 8.3.3/2 of C++ 03 standard). |
Christopher Haster |
11:f08e03081748 | 732 | // As a result, the compiler will allocate for UnknownFunctionMember_t the biggest size |
Christopher Haster |
11:f08e03081748 | 733 | // and biggest alignment possible for member function. |
Christopher Haster |
11:f08e03081748 | 734 | // This type can be used inside unions, it will help to provide the storage |
Christopher Haster |
11:f08e03081748 | 735 | // with the proper size and alignment guarantees |
Christopher Haster |
11:f08e03081748 | 736 | class UnknownClass; |
Christopher Haster |
11:f08e03081748 | 737 | |
Christopher Haster |
11:f08e03081748 | 738 | // object this pointer |
Christopher Haster |
11:f08e03081748 | 739 | void *_object; |
Christopher Haster |
11:f08e03081748 | 740 | |
Christopher Haster |
11:f08e03081748 | 741 | // aligned raw member function pointer storage - converted back by registered thunk |
Christopher Haster |
11:f08e03081748 | 742 | union { |
Christopher Haster |
11:f08e03081748 | 743 | char _function[sizeof(void (UnknownClass::*)())]; |
Christopher Haster |
11:f08e03081748 | 744 | void (UnknownClass::*_unknownMethod)(); |
Christopher Haster |
11:f08e03081748 | 745 | }; |
Christopher Haster |
11:f08e03081748 | 746 | |
Christopher Haster |
11:f08e03081748 | 747 | // registered function to convert back and call _m.member on _object |
Christopher Haster |
11:f08e03081748 | 748 | R (*_thunk)(void*, void*); |
Christopher Haster |
11:f08e03081748 | 749 | }; |
Christopher Haster |
11:f08e03081748 | 750 | |
Christopher Haster |
6:c2a3aa792960 | 751 | // Overloads for backwards compatibility |
Christopher Haster |
6:c2a3aa792960 | 752 | template <typename R, typename A1> |
Christopher Haster |
14:4af7fef9cf08 | 753 | class FunctionPointerArg1 : public FuncPtr<R(A1)> {}; |
Christopher Haster |
6:c2a3aa792960 | 754 | |
Christopher Haster |
6:c2a3aa792960 | 755 | template <typename R> |
Christopher Haster |
14:4af7fef9cf08 | 756 | class FunctionPointerArg1<R, void> : public FuncPtr<R()> {}; |
Christopher Haster |
6:c2a3aa792960 | 757 | |
Christopher Haster |
14:4af7fef9cf08 | 758 | typedef FuncPtr<void()> FunctionPointer; |
Christopher Haster |
14:4af7fef9cf08 | 759 | typedef FuncPtr<void(int)> event_callback_t; |
screamer | 0:9c59db1fbc9e | 760 | |
screamer | 0:9c59db1fbc9e | 761 | } // namespace mbed |
screamer | 0:9c59db1fbc9e | 762 | |
screamer | 0:9c59db1fbc9e | 763 | #endif |