Christopher Haster / mbed-hal

Dependencies:   target-freescale

Fork of mbed-hal by Morpheus

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?

UserRevisionLine numberNew contents of line
screamer 0:9c59db1fbc9e 1 /* mbed Microcontroller Library
screamer 0:9c59db1fbc9e 2 * Copyright (c) 2006-2015 ARM Limited
screamer 0:9c59db1fbc9e 3 *
screamer 0:9c59db1fbc9e 4 * Licensed under the Apache License, Version 2.0 (the "License");
screamer 0:9c59db1fbc9e 5 * you may not use this file except in compliance with the License.
screamer 0:9c59db1fbc9e 6 * You may obtain a copy of the License at
screamer 0:9c59db1fbc9e 7 *
screamer 0:9c59db1fbc9e 8 * http://www.apache.org/licenses/LICENSE-2.0
screamer 0:9c59db1fbc9e 9 *
screamer 0:9c59db1fbc9e 10 * Unless required by applicable law or agreed to in writing, software
screamer 0:9c59db1fbc9e 11 * distributed under the License is distributed on an "AS IS" BASIS,
screamer 0:9c59db1fbc9e 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
screamer 0:9c59db1fbc9e 13 * See the License for the specific language governing permissions and
screamer 0:9c59db1fbc9e 14 * limitations under the License.
screamer 0:9c59db1fbc9e 15 */
Christopher Haster 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