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 
113 template <typename R, typename A1>
114 class FP1{
115 public:
120  FP1(R (*function)(A1) = 0) {
121  memset(_member,0,sizeof(_member));
122  attach(function);
123  }
124 
130  template<typename T>
131  FP1(T *object, R (T::*member)(A1)) {
132  attach(object, member);
133  }
134 
139  void attach(R (*function)(A1)) {
140  _p.function = function;
141  _membercaller = 0;
142  }
143 
149  template<typename T>
150  void attach(T *object, R (T::*member)(A1)) {
151  _p.object = static_cast<void*>(object);
152  *reinterpret_cast<R (T::**)(A1)>(_member) = member;
153  _membercaller = &FP1::membercaller<T>;
154  }
155 
158  R call(A1 a){
159  if (_membercaller == 0 && _p.function) {
160  return _p.function(a);
161  } else if (_membercaller && _p.object) {
162  return _membercaller(_p.object, _member, a);
163  }
164  return (R)0;
165  }
166 
167  typedef R (*static_fp)();
168  static_fp get_function() const {
169  return (R(*)())_p.function;
170  }
171 
172  R operator ()(A1 a) {
173  return call(a);
174  }
175  operator bool(void)
176  {
177  void *q = &_p.function;
178  return (_membercaller != NULL) && _p.object != NULL && (*static_cast<void **>(q) != NULL);
179  }
180 private:
181  template<typename T>
182  static void membercaller(void *object, uintptr_t *member, A1 a) {
183  T* o = static_cast<T*>(object);
184  R (T::**m)(A1) = reinterpret_cast<R (T::**)(A1)>(member);
185  (o->**m)(a);
186  }
187 
188  union {
189  R (*function)(A1); // static function pointer - 0 if none attached
190  void *object; // object this pointer - 0 if none attached
191  } _p;
192  uintptr_t _member[2]; // aligned raw member function pointer storage - converted back by registered _membercaller
193  R (*_membercaller)(void*, uintptr_t*, A1); // registered membercaller function to convert back and call _m.member on _object
194 };
195 
198 template <typename R, typename A1, typename A2>
199 class FP2{
200 public:
205  FP2(R (*function)(A1, A2) = 0) {
206  memset(_member,0,sizeof(_member));
207  attach(function);
208  }
209 
215  template<typename T>
216  FP2(T *object, R (T::*member)(A1, A2)) {
217  attach(object, member);
218  }
219 
224  void attach(R (*function)(A1, A2)) {
225  _p.function = function;
226  _membercaller = 0;
227  }
228 
234  template<typename T>
235  void attach(T *object, R (T::*member)(A1, A2)) {
236  _p.object = static_cast<void*>(object);
237  *reinterpret_cast<R (T::**)(A1, A2)>(_member) = member;
238  _membercaller = &FP2::membercaller<T>;
239  }
240 
243  R call(A1 a1, A2 a2){
244  if (_membercaller == 0 && _p.function) {
245  return _p.function(a1, a2);
246  } else if (_membercaller && _p.object) {
247  return _membercaller(_p.object, _member, a1, a2);
248  }
249  return (R)0;
250  }
251 
252  typedef R (*static_fp)();
253  static_fp get_function() const {
254  return (R(*)())_p.function;
255  }
256 
257  R operator ()(A1 a1, A2 a2) {
258  return call(a1, a2);
259  }
260  operator bool(void)
261  {
262  void *q = &_p.function;
263  return (_membercaller != NULL) && _p.object != NULL && (*static_cast<void **>(q) != NULL);
264  }
265 private:
266  template<typename T>
267  static void membercaller(void *object, uintptr_t *member, A1 a1, A2 a2) {
268  T* o = static_cast<T*>(object);
269  R (T::**m)(A1, A2) = reinterpret_cast<R (T::**)(A1, A2)>(member);
270  (o->**m)(a1, a2);
271  }
272 
273  union {
274  R (*function)(A1, A2); // static function pointer - 0 if none attached
275  void *object; // object this pointer - 0 if none attached
276  } _p;
277  uintptr_t _member[2]; // aligned raw member function pointer storage - converted back by registered _membercaller
278  R (*_membercaller)(void*, uintptr_t*, A1, A2); // registered membercaller function to convert back and call _m.member on _object
279 };
280 
283 template <typename R, typename A1, typename A2, typename A3>
284 class FP3{
285 public:
290  FP3(R (*function)(A1, A2, A3) = 0) {
291  memset(_member,0,sizeof(_member));
292  attach(function);
293  }
294 
300  template<typename T>
301  FP3(T *object, R (T::*member)(A1, A2, A3)) {
302  attach(object, member);
303  }
304 
309  void attach(R (*function)(A1, A2, A3)) {
310  _p.function = function;
311  _membercaller = 0;
312  }
313 
319  template<typename T>
320  void attach(T *object, R (T::*member)(A1, A2, A3)) {
321  _p.object = static_cast<void*>(object);
322  *reinterpret_cast<R (T::**)(A1, A2, A3)>(_member) = member;
323  _membercaller = &FP3::membercaller<T>;
324  }
325 
328  R call(A1 a1, A2 a2, A3 a3){
329  if (_membercaller == 0 && _p.function) {
330  return _p.function(a1, a2, a3);
331  } else if (_membercaller && _p.object) {
332  return _membercaller(_p.object, _member, a1, a2, a3);
333  }
334  return (R)0;
335  }
336 
337  typedef R (*static_fp)();
338  static_fp get_function() const {
339  return (R(*)())_p.function;
340  }
341 
342  R operator ()(A1 a1, A2 a2, A3 a3) {
343  return call(a1, a2, a3);
344  }
345  operator bool(void)
346  {
347  void *q = &_p.function;
348  return (_membercaller != NULL) && _p.object != NULL && (*static_cast<void **>(q) != NULL);
349  }
350 private:
351  template<typename T>
352  static void membercaller(void *object, uintptr_t *member, A1 a1, A2 a2, A3 a3) {
353  T* o = static_cast<T*>(object);
354  R (T::**m)(A1, A2, A3) = reinterpret_cast<R (T::**)(A1, A2, A3)>(member);
355  (o->**m)(a1, a2, a3);
356  }
357 
358  union {
359  R (*function)(A1, A2, A3); // static function pointer - 0 if none attached
360  void *object; // object this pointer - 0 if none attached
361  } _p;
362  uintptr_t _member[2]; // aligned raw member function pointer storage - converted back by registered _membercaller
363  R (*_membercaller)(void*, uintptr_t*, A1, A2, A3); // registered membercaller function to convert back and call _m.member on _object
364 };
365 
366 typedef FP0<void> FP;
367 
368 #endif
FP1(T *object, R(T::*member)(A1))
Definition: functionpointer.h:131
FP3(T *object, R(T::*member)(A1, A2, A3))
Definition: functionpointer.h:301
void attach(T *object, R(T::*member)(A1))
Definition: functionpointer.h:150
Definition: functionpointer.h:284
FP2(R(*function)(A1, A2)=0)
Definition: functionpointer.h:205
void attach(R(*function)(A1, A2))
Definition: functionpointer.h:224
Definition: functionpointer.h:27
void attach(R(*function)(A1, A2, A3))
Definition: functionpointer.h:309
void attach(R(*function)(A1))
Definition: functionpointer.h:139
FP2(T *object, R(T::*member)(A1, A2))
Definition: functionpointer.h:216
FP0(T *object, R(T::*member)(void))
Definition: functionpointer.h:44
FP1(R(*function)(A1)=0)
Definition: functionpointer.h:120
void attach(R(*function)(void))
Definition: functionpointer.h:52
FP3(R(*function)(A1, A2, A3)=0)
Definition: functionpointer.h:290
void attach(T *object, R(T::*member)(A1, A2))
Definition: functionpointer.h:235
R call()
Definition: functionpointer.h:71
Definition: functionpointer.h:199
R call(A1 a1, A2 a2)
Definition: functionpointer.h:243
R call(A1 a)
Definition: functionpointer.h:158
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:328
void attach(T *object, R(T::*member)(A1, A2, A3))
Definition: functionpointer.h:320
Definition: functionpointer.h:114