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