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