Mistake on this page? Email us
functionpointer.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 ARM Limited. All rights reserved.
3  * SPDX-License-Identifier: Apache-2.0
4  * Licensed under the Apache License, Version 2.0 (the License); you may
5  * not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS, WITHOUT
12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #ifndef FUNCTIONPOINTER_H
17 #define FUNCTIONPOINTER_H
18 
19 #include <string.h>
20 #include <stdint.h>
21 
26 template <typename R>
27 class FP0{
28 public:
33  FP0(R (*function)(void) = 0) {
34  memset(_member,0,sizeof(_member));
35  attach(function);
36  }
37 
43  template<typename T>
44  FP0(T *object, R (T::*member)(void)) {
45  attach(object, member);
46  }
47 
52  void attach(R (*function)(void)) {
53  _p.function = function;
54  _membercaller = 0;
55  }
56 
62  template<typename T>
63  void attach(T *object, R (T::*member)(void)) {
64  _p.object = static_cast<void*>(object);
65  *reinterpret_cast<R (T::**)(void)>(_member) = member;
66  _membercaller = &FP0::membercaller<T>;
67  }
68 
71  R call(){
72  if (_membercaller == 0 && _p.function) {
73  return _p.function();
74  } else if (_membercaller && _p.object) {
75  return _membercaller(_p.object, _member);
76  }
77  return (R)0;
78  }
79 
80  typedef R (*static_fp)();
81  static_fp get_function() const {
82  return (R(*)())_p.function;
83  }
84 
85  R operator ()(void) {
86  return call();
87  }
88  operator bool(void) {
89  void *q = &_p.function;
90  return (_membercaller != NULL) && _p.object != NULL && (*static_cast<void **>(q) != NULL);
91  }
92 
93 private:
94  template<typename T>
95  static void membercaller(void *object, uintptr_t *member) {
96  T* o = static_cast<T*>(object);
97  R (T::**m)(void) = reinterpret_cast<R (T::**)(void)>(member);
98  (o->**m)();
99  }
100 
101  union {
102  R (*function)(void); // static function pointer - 0 if none attached
103  void *object; // object this pointer - 0 if none attached
104  } _p;
105  uintptr_t _member[2]; // aligned raw member function pointer storage - converted back by registered _membercaller
106  R (*_membercaller)(void*, uintptr_t*); // registered membercaller function to convert back and call _m.member on _object
107 };
108 
109 /* If we had variadic templates, this wouldn't be a problem, but until C++11 is enabled, we are stuck with multiple classes... */
110 
112 template <typename R, typename A1>
113 class FP1{
114 public:
119  FP1(R (*function)(A1) = 0) {
120  memset(_member,0,sizeof(_member));
121  attach(function);
122  }
123 
129  template<typename T>
130  FP1(T *object, R (T::*member)(A1)) {
131  attach(object, member);
132  }
133 
138  void attach(R (*function)(A1)) {
139  _p.function = function;
140  _membercaller = 0;
141  }
142 
148  template<typename T>
149  void attach(T *object, R (T::*member)(A1)) {
150  _p.object = static_cast<void*>(object);
151  *reinterpret_cast<R (T::**)(A1)>(_member) = member;
152  _membercaller = &FP1::membercaller<T>;
153  }
154 
157  R call(A1 a){
158  if (_membercaller == 0 && _p.function) {
159  return _p.function(a);
160  } else if (_membercaller && _p.object) {
161  return _membercaller(_p.object, _member, a);
162  }
163  return (R)0;
164  }
165 
166  typedef R (*static_fp)();
167  static_fp get_function() const {
168  return (R(*)())_p.function;
169  }
170 
171  R operator ()(A1 a) {
172  return call(a);
173  }
174  operator bool(void)
175  {
176  void *q = &_p.function;
177  return (_membercaller != NULL) && _p.object != NULL && (*static_cast<void **>(q) != NULL);
178  }
179 private:
180  template<typename T>
181  static void membercaller(void *object, uintptr_t *member, A1 a) {
182  T* o = static_cast<T*>(object);
183  R (T::**m)(A1) = reinterpret_cast<R (T::**)(A1)>(member);
184  (o->**m)(a);
185  }
186 
187  union {
188  R (*function)(A1); // static function pointer - 0 if none attached
189  void *object; // object this pointer - 0 if none attached
190  } _p;
191  uintptr_t _member[2]; // aligned raw member function pointer storage - converted back by registered _membercaller
192  R (*_membercaller)(void*, uintptr_t*, A1); // registered membercaller function to convert back and call _m.member on _object
193 };
194 
196 template <typename R, typename A1, typename A2>
197 class FP2{
198 public:
203  FP2(R (*function)(A1, A2) = 0) {
204  memset(_member,0,sizeof(_member));
205  attach(function);
206  }
207 
213  template<typename T>
214  FP2(T *object, R (T::*member)(A1, A2)) {
215  attach(object, member);
216  }
217 
222  void attach(R (*function)(A1, A2)) {
223  _p.function = function;
224  _membercaller = 0;
225  }
226 
232  template<typename T>
233  void attach(T *object, R (T::*member)(A1, A2)) {
234  _p.object = static_cast<void*>(object);
235  *reinterpret_cast<R (T::**)(A1, A2)>(_member) = member;
236  _membercaller = &FP2::membercaller<T>;
237  }
238 
241  R call(A1 a1, A2 a2){
242  if (_membercaller == 0 && _p.function) {
243  return _p.function(a1, a2);
244  } else if (_membercaller && _p.object) {
245  return _membercaller(_p.object, _member, a1, a2);
246  }
247  return (R)0;
248  }
249 
250  typedef R (*static_fp)();
251  static_fp get_function() const {
252  return (R(*)())_p.function;
253  }
254 
255  R operator ()(A1 a1, A2 a2) {
256  return call(a1, a2);
257  }
258  operator bool(void)
259  {
260  void *q = &_p.function;
261  return (_membercaller != NULL) && _p.object != NULL && (*static_cast<void **>(q) != NULL);
262  }
263 private:
264  template<typename T>
265  static void membercaller(void *object, uintptr_t *member, A1 a1, A2 a2) {
266  T* o = static_cast<T*>(object);
267  R (T::**m)(A1, A2) = reinterpret_cast<R (T::**)(A1, A2)>(member);
268  (o->**m)(a1, a2);
269  }
270 
271  union {
272  R (*function)(A1, A2); // static function pointer - 0 if none attached
273  void *object; // object this pointer - 0 if none attached
274  } _p;
275  uintptr_t _member[2]; // aligned raw member function pointer storage - converted back by registered _membercaller
276  R (*_membercaller)(void*, uintptr_t*, A1, A2); // registered membercaller function to convert back and call _m.member on _object
277 };
278 
280 template <typename R, typename A1, typename A2, typename A3>
281 class FP3{
282 public:
287  FP3(R (*function)(A1, A2, A3) = 0) {
288  memset(_member,0,sizeof(_member));
289  attach(function);
290  }
291 
297  template<typename T>
298  FP3(T *object, R (T::*member)(A1, A2, A3)) {
299  attach(object, member);
300  }
301 
306  void attach(R (*function)(A1, A2, A3)) {
307  _p.function = function;
308  _membercaller = 0;
309  }
310 
316  template<typename T>
317  void attach(T *object, R (T::*member)(A1, A2, A3)) {
318  _p.object = static_cast<void*>(object);
319  *reinterpret_cast<R (T::**)(A1, A2, A3)>(_member) = member;
320  _membercaller = &FP3::membercaller<T>;
321  }
322 
325  R call(A1 a1, A2 a2, A3 a3){
326  if (_membercaller == 0 && _p.function) {
327  return _p.function(a1, a2, a3);
328  } else if (_membercaller && _p.object) {
329  return _membercaller(_p.object, _member, a1, a2, a3);
330  }
331  return (R)0;
332  }
333 
334  typedef R (*static_fp)();
335  static_fp get_function() const {
336  return (R(*)())_p.function;
337  }
338 
339  R operator ()(A1 a1, A2 a2, A3 a3) {
340  return call(a1, a2, a3);
341  }
342  operator bool(void)
343  {
344  void *q = &_p.function;
345  return (_membercaller != NULL) && _p.object != NULL && (*static_cast<void **>(q) != NULL);
346  }
347 private:
348  template<typename T>
349  static void membercaller(void *object, uintptr_t *member, A1 a1, A2 a2, A3 a3) {
350  T* o = static_cast<T*>(object);
351  R (T::**m)(A1, A2, A3) = reinterpret_cast<R (T::**)(A1, A2, A3)>(member);
352  (o->**m)(a1, a2, a3);
353  }
354 
355  union {
356  R (*function)(A1, A2, A3); // static function pointer - 0 if none attached
357  void *object; // object this pointer - 0 if none attached
358  } _p;
359  uintptr_t _member[2]; // aligned raw member function pointer storage - converted back by registered _membercaller
360  R (*_membercaller)(void*, uintptr_t*, A1, A2, A3); // registered membercaller function to convert back and call _m.member on _object
361 };
362 
363 typedef FP0<void> FP;
364 
365 #endif
FP1(T *object, R(T::*member)(A1))
Definition: functionpointer.h:130
FP3(T *object, R(T::*member)(A1, A2, A3))
Definition: functionpointer.h:298
void attach(T *object, R(T::*member)(A1))
Definition: functionpointer.h:149
Definition: functionpointer.h:281
FP2(R(*function)(A1, A2)=0)
Definition: functionpointer.h:203
void attach(R(*function)(A1, A2))
Definition: functionpointer.h:222
Definition: functionpointer.h:27
void attach(R(*function)(A1, A2, A3))
Definition: functionpointer.h:306
void attach(R(*function)(A1))
Definition: functionpointer.h:138
FP2(T *object, R(T::*member)(A1, A2))
Definition: functionpointer.h:214
FP0(T *object, R(T::*member)(void))
Definition: functionpointer.h:44
FP1(R(*function)(A1)=0)
Definition: functionpointer.h:119
void attach(R(*function)(void))
Definition: functionpointer.h:52
FP3(R(*function)(A1, A2, A3)=0)
Definition: functionpointer.h:287
void attach(T *object, R(T::*member)(A1, A2))
Definition: functionpointer.h:233
R call()
Definition: functionpointer.h:71
Definition: functionpointer.h:197
R call(A1 a1, A2 a2)
Definition: functionpointer.h:241
R call(A1 a)
Definition: functionpointer.h:157
FP0(R(*function)(void)=0)
Definition: functionpointer.h:33
void attach(T *object, R(T::*member)(void))
Definition: functionpointer.h:63
R call(A1 a1, A2 a2, A3 a3)
Definition: functionpointer.h:325
void attach(T *object, R(T::*member)(A1, A2, A3))
Definition: functionpointer.h:317
Definition: functionpointer.h:113