libcamera  v0.0.0+100-debian/0_git20200629+e7aa92a-8-9-g77f5237c-dirty (2021-05-05T16:20:29+01:00)
Supporting cameras in Linux since 2019
bound_method.h
Go to the documentation of this file.
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 /*
3  * Copyright (C) 2019, Google Inc.
4  *
5  * bound_method.h - Method bind and invocation
6  */
7 #ifndef __LIBCAMERA_BOUND_METHOD_H__
8 #define __LIBCAMERA_BOUND_METHOD_H__
9 
10 #include <memory>
11 #include <tuple>
12 #include <type_traits>
13 #include <utility>
14 
15 namespace libcamera {
16 
17 class Object;
18 
24 };
25 
26 class BoundMethodPackBase
27 {
28 public:
29  virtual ~BoundMethodPackBase() = default;
30 };
31 
32 template<typename R, typename... Args>
33 class BoundMethodPack : public BoundMethodPackBase
34 {
35 public:
36  BoundMethodPack(const Args &... args)
37  : args_(args...)
38  {
39  }
40 
41  std::tuple<typename std::remove_reference_t<Args>...> args_;
42  R ret_;
43 };
44 
45 template<typename... Args>
46 class BoundMethodPack<void, Args...> : public BoundMethodPackBase
47 {
48 public:
49  BoundMethodPack(const Args &... args)
50  : args_(args...)
51  {
52  }
53 
54  std::tuple<typename std::remove_reference_t<Args>...> args_;
55 };
56 
57 class BoundMethodBase
58 {
59 public:
60  BoundMethodBase(void *obj, Object *object, ConnectionType type)
61  : obj_(obj), object_(object), connectionType_(type)
62  {
63  }
64  virtual ~BoundMethodBase() = default;
65 
66  template<typename T, typename std::enable_if_t<!std::is_same<Object, T>::value> * = nullptr>
67  bool match(T *obj) { return obj == obj_; }
68  bool match(Object *object) { return object == object_; }
69 
70  Object *object() const { return object_; }
71 
72  virtual void invokePack(BoundMethodPackBase *pack) = 0;
73 
74 protected:
75  bool activatePack(std::shared_ptr<BoundMethodPackBase> pack,
76  bool deleteMethod);
77 
78  void *obj_;
79  Object *object_;
80 
81 private:
82  ConnectionType connectionType_;
83 };
84 
85 template<typename R, typename... Args>
86 class BoundMethodArgs : public BoundMethodBase
87 {
88 public:
89  using PackType = BoundMethodPack<R, Args...>;
90 
91 private:
92  template<std::size_t... I>
93  void invokePack(BoundMethodPackBase *pack, std::index_sequence<I...>)
94  {
95  PackType *args = static_cast<PackType *>(pack);
96  args->ret_ = invoke(std::get<I>(args->args_)...);
97  }
98 
99 public:
100  BoundMethodArgs(void *obj, Object *object, ConnectionType type)
101  : BoundMethodBase(obj, object, type) {}
102 
103  void invokePack(BoundMethodPackBase *pack) override
104  {
105  invokePack(pack, std::make_index_sequence<sizeof...(Args)>{});
106  }
107 
108  virtual R activate(Args... args, bool deleteMethod = false) = 0;
109  virtual R invoke(Args... args) = 0;
110 };
111 
112 template<typename... Args>
113 class BoundMethodArgs<void, Args...> : public BoundMethodBase
114 {
115 public:
116  using PackType = BoundMethodPack<void, Args...>;
117 
118 private:
119  template<std::size_t... I>
120  void invokePack(BoundMethodPackBase *pack, std::index_sequence<I...>)
121  {
122  /* args is effectively unused when the sequence I is empty. */
123  PackType *args [[gnu::unused]] = static_cast<PackType *>(pack);
124  invoke(std::get<I>(args->args_)...);
125  }
126 
127 public:
128  BoundMethodArgs(void *obj, Object *object, ConnectionType type)
129  : BoundMethodBase(obj, object, type) {}
130 
131  void invokePack(BoundMethodPackBase *pack) override
132  {
133  invokePack(pack, std::make_index_sequence<sizeof...(Args)>{});
134  }
135 
136  virtual void activate(Args... args, bool deleteMethod = false) = 0;
137  virtual void invoke(Args... args) = 0;
138 };
139 
140 template<typename T, typename R, typename... Args>
141 class BoundMethodMember : public BoundMethodArgs<R, Args...>
142 {
143 public:
144  using PackType = typename BoundMethodArgs<R, Args...>::PackType;
145 
146  BoundMethodMember(T *obj, Object *object, R (T::*func)(Args...),
148  : BoundMethodArgs<R, Args...>(obj, object, type), func_(func)
149  {
150  }
151 
152  bool match(R (T::*func)(Args...)) const { return func == func_; }
153 
154  R activate(Args... args, bool deleteMethod = false) override
155  {
156  if (!this->object_) {
157  T *obj = static_cast<T *>(this->obj_);
158  return (obj->*func_)(args...);
159  }
160 
161  auto pack = std::make_shared<PackType>(args...);
162  bool sync = BoundMethodBase::activatePack(pack, deleteMethod);
163  return sync ? pack->ret_ : R();
164  }
165 
166  R invoke(Args... args) override
167  {
168  T *obj = static_cast<T *>(this->obj_);
169  return (obj->*func_)(args...);
170  }
171 
172 private:
173  R (T::*func_)(Args...);
174 };
175 
176 template<typename T, typename... Args>
177 class BoundMethodMember<T, void, Args...> : public BoundMethodArgs<void, Args...>
178 {
179 public:
180  using PackType = typename BoundMethodArgs<void, Args...>::PackType;
181 
182  BoundMethodMember(T *obj, Object *object, void (T::*func)(Args...),
184  : BoundMethodArgs<void, Args...>(obj, object, type), func_(func)
185  {
186  }
187 
188  bool match(void (T::*func)(Args...)) const { return func == func_; }
189 
190  void activate(Args... args, bool deleteMethod = false) override
191  {
192  if (!this->object_) {
193  T *obj = static_cast<T *>(this->obj_);
194  return (obj->*func_)(args...);
195  }
196 
197  auto pack = std::make_shared<PackType>(args...);
198  BoundMethodBase::activatePack(pack, deleteMethod);
199  }
200 
201  void invoke(Args... args) override
202  {
203  T *obj = static_cast<T *>(this->obj_);
204  return (obj->*func_)(args...);
205  }
206 
207 private:
208  void (T::*func_)(Args...);
209 };
210 
211 template<typename R, typename... Args>
212 class BoundMethodStatic : public BoundMethodArgs<R, Args...>
213 {
214 public:
215  BoundMethodStatic(R (*func)(Args...))
216  : BoundMethodArgs<R, Args...>(nullptr, nullptr, ConnectionTypeAuto),
217  func_(func)
218  {
219  }
220 
221  bool match(R (*func)(Args...)) const { return func == func_; }
222 
223  R activate(Args... args, [[maybe_unused]] bool deleteMethod = false) override
224  {
225  return (*func_)(args...);
226  }
227 
228  R invoke(Args...) override
229  {
230  return R();
231  }
232 
233 private:
234  R (*func_)(Args...);
235 };
236 
237 } /* namespace libcamera */
238 
239 #endif /* __LIBCAMERA_BOUND_METHOD_H__ */
ConnectionType
Connection type for asynchronous communication.
Definition: bound_method.h:19
Top-level libcamera namespace.
Definition: bound_method.h:15
The receiver is invoked synchronously.
Definition: bound_method.h:23
The receiver is invoked asynchronously.
Definition: bound_method.h:22
The receiver is invoked immediately and synchronously in the sender&#39;s thread.
Definition: bound_method.h:21
Base object to support automatic signal disconnection.
Definition: object.h:24
If the sender and the receiver live in the same thread, ConnectionTypeDirect is used. Otherwise ConnectionTypeQueued is used.
Definition: bound_method.h:20