Btk
function.hpp
1 #if !defined(_BTKSIGNAL_FUNCTION_HPP_)
2 #define _BTKSIGNAL_FUNCTION_HPP_
3 #include <cstddef>
4 #include <utility>
5 #include <type_traits>
6 namespace Btk{
7  //Impl
8  namespace Impl{
9  //Function manager
10  struct ManagerBase{
11  int refcount;
12  };
13  template<class T,class RetT,class ...Args>
14  struct Manager:public ManagerBase{
15  //target fn
16  Manager(T f):
17  ManagerBase({1}),
18  fn(std::forward<T>(f)){}
19  T fn;
20  //CallFunction
21  static RetT Invoke(void *__self,Args ...args){
22  Manager *self = static_cast<Manager*>(__self);
23  return self->fn(std::forward<Args>(args)...);
24  };
25  static void Delete(void *__self){
26  delete static_cast<Manager*>(__self);
27  };
28  };
29  };
30  //throw BadFunctionCall
31  [[noreturn]] void throwBadFunctionCall();
32  //Function Base
33  struct FunctionBase{
34  FunctionBase():
35  manager_ptr(nullptr),
36  delete_ptr(nullptr){};
37  //Copy function base
38  FunctionBase(const FunctionBase &fn){
39  manager_ptr = fn.manager_ptr;
40  delete_ptr = fn.delete_ptr;
41  if(delete_ptr != nullptr){
42  //has refcount
43  auto base = static_cast<Impl::ManagerBase*>(manager_ptr);
44  base->refcount += 1;
45  }
46  }
48  manager_ptr = fn.manager_ptr;
49  delete_ptr = fn.delete_ptr;
50 
51  fn.manager_ptr = nullptr;
52  fn.delete_ptr = nullptr;
53  }
54  //Delete Manager
55  ~FunctionBase(){
56  reset();
57  }
58  //reset manager
59  void reset(){
60  if(delete_ptr != nullptr){
61  //is Impl::ManagerBase
62  auto base = static_cast<Impl::ManagerBase*>(manager_ptr);
63  base->refcount -= 1;
64  if(base->refcount == 0){
65  delete_ptr(manager_ptr);
66  }
67  }
68  manager_ptr = nullptr;
69  delete_ptr = nullptr;
70  }
71  //swap manager
72  void swap(FunctionBase &fn){
73  auto m = fn.manager_ptr;
74  auto dptr = fn.delete_ptr;
75 
76  fn.manager_ptr = manager_ptr;
77  fn.delete_ptr = delete_ptr;
78 
79  manager_ptr = m;
80  delete_ptr = dptr;
81  }
82  //copy manager
83  void *manager_ptr;
84  void (*delete_ptr)(void *manager);
85  };
86 
87 
88  template<class RetT>
89  class Function;
90  //Function
91  template<class RetT,class ...Args>
92  class Function<RetT(Args...)>:public FunctionBase{
93  public:
94  //empty function
95  Function():
96  FunctionBase(),
97  invoke_ptr(nullptr)
98  {};
99  //create function
100  template<class Fn>
101  Function(Fn fn){
102  assign_impl(std::forward<Fn>(fn));
103  };
104  //Copy function
105  Function(const Function &fn):FunctionBase(fn){
106  invoke_ptr = fn.invoke_ptr;
107  }
108  //move function
109  Function(Function &&fn):FunctionBase(fn){
110  invoke_ptr = fn.invoke_ptr;
111  fn.invoke_ptr = nullptr;
112  }
113  //assign
114  template<class Fn>
115  void assign_impl(Fn &&fn){
116  //typedef typename std::remove_reference<Fn>::type T;
117  if constexpr(std::is_pointer<Fn>::value){
118  //C function pointer
119  delete_ptr = nullptr;
120  manager_ptr = reinterpret_cast<void*>(fn);
121  invoke_ptr = InvokeCFunction<Fn>;
122  }
123  else{
124  //other any callable
125  typedef Impl::Manager<Fn,RetT,Args...> Manager;
126  manager_ptr = new Manager(std::forward<Fn>(fn));
127  delete_ptr = Manager::Delete;
128  invoke_ptr = Manager::Invoke;
129  }
130  };
131  //assign other callable
132  template<class Fn>
133  void assign(Fn &&fn){
134  //reset function
135  reset();
136  //assign
137  assign_impl(std::forward<Fn>(fn));
138  };
139  void assign(Function &&fn){
140  if(this != &fn){
141  swap(fn);
142  }
143  };
144  void assign(Function &fn){
145  if(this != &fn){
146  //clear it
147  reset();
148  manager_ptr = fn.manager_ptr;
149  delete_ptr = fn.delete_ptr;
150  if(delete_ptr != nullptr){
151  //has refcount
152  auto base = static_cast<Impl::ManagerBase*>(manager_ptr);
153  base->refcount += 1;
154  }
155  }
156  };
157  //reset function
158  void reset(){
159  FunctionBase::reset();
160  invoke_ptr = nullptr;
161  };
162  //swap function
163  void swap(Function &fn){
164  FunctionBase::swap(fn);
165  auto invp = fn.invoke_ptr;
166  fn.invoke_ptr = invoke_ptr;
167  invoke_ptr = invp;
168  };
169  //assign operator
170  template<class T>
171  Function &operator =(T &&dat){
172  assign<T>(std::forward<T>(dat));
173  return *this;
174  }
175  //result_type
176  typedef RetT result_type;
177  //invoke function pointer
178  typedef RetT (*InvokeFn)(void*,Args...);
179  result_type call(Args ...args) const{
180  if(invoke_ptr == nullptr){
181  //handle err...
182  throwBadFunctionCall();
183  }
184  else{
185  return invoke_ptr(manager_ptr,std::forward<Args>(args)...);
186  }
187  };
188  //is safe to call
189  bool empty() const noexcept{
190  return invoke_ptr == nullptr;
191  };
192  result_type operator()(Args ...args) const{
193  return call(std::forward<Args>(args)...);
194  };
195  bool operator ==(std::nullptr_t) const noexcept{
196  return invoke_ptr == nullptr;
197  };
198  operator bool() const noexcept{
199  return empty();
200  };
201  //Invoke C Function
202  template<class Fn = RetT(*)(Args...)>
203  static RetT InvokeCFunction(void *fn,Args ...args){
204  return reinterpret_cast<Fn>(fn)(
205  std::forward<Args>(args)...
206  );
207  };
208  private:
209  InvokeFn invoke_ptr;
210  };
211 };
212 #endif // _BTKSIGNAL_FUNCTION_HPP_
Definition: function.hpp:10
This header include many useful containers.
Definition: async.hpp:7
Definition: function.hpp:14
Definition: function.hpp:89
Definition: function.hpp:33