libcamera  v0.5.0+30-92ed6140
Supporting cameras in Linux since 2019
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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  * Method bind and invocation
6  */
7 
8 #pragma once
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  R returnValue()
42  {
43  return ret_;
44  }
45 
46  std::tuple<typename std::remove_reference_t<Args>...> args_;
47  R ret_;
48 };
49 
50 template<typename... Args>
51 class BoundMethodPack<void, Args...> : public BoundMethodPackBase
52 {
53 public:
54  BoundMethodPack(const Args &... args)
55  : args_(args...)
56  {
57  }
58 
59  void returnValue()
60  {
61  }
62 
63  std::tuple<typename std::remove_reference_t<Args>...> args_;
64 };
65 
66 class BoundMethodBase
67 {
68 public:
69  BoundMethodBase(void *obj, Object *object, ConnectionType type)
70  : obj_(obj), object_(object), connectionType_(type)
71  {
72  }
73  virtual ~BoundMethodBase() = default;
74 
75  template<typename T, std::enable_if_t<!std::is_same<Object, T>::value> * = nullptr>
76  bool match(T *obj) { return obj == obj_; }
77  bool match(Object *object) { return object == object_; }
78 
79  Object *object() const { return object_; }
80 
81  virtual void invokePack(BoundMethodPackBase *pack) = 0;
82 
83 protected:
84  bool activatePack(std::shared_ptr<BoundMethodPackBase> pack,
85  bool deleteMethod);
86 
87  void *obj_;
88  Object *object_;
89 
90 private:
91  ConnectionType connectionType_;
92 };
93 
94 template<typename R, typename... Args>
95 class BoundMethodArgs : public BoundMethodBase
96 {
97 public:
98  using PackType = BoundMethodPack<R, Args...>;
99 
100 private:
101  template<std::size_t... I>
102  void invokePack(BoundMethodPackBase *pack, std::index_sequence<I...>)
103  {
104  [[maybe_unused]] auto *args = static_cast<PackType *>(pack);
105 
106  if constexpr (!std::is_void_v<R>)
107  args->ret_ = invoke(std::get<I>(args->args_)...);
108  else
109  invoke(std::get<I>(args->args_)...);
110  }
111 
112 public:
113  BoundMethodArgs(void *obj, Object *object, ConnectionType type)
114  : BoundMethodBase(obj, object, type) {}
115 
116  void invokePack(BoundMethodPackBase *pack) override
117  {
118  invokePack(pack, std::make_index_sequence<sizeof...(Args)>{});
119  }
120 
121  virtual R activate(Args... args, bool deleteMethod = false) = 0;
122  virtual R invoke(Args... args) = 0;
123 };
124 
125 template<typename T, typename R, typename Func, typename... Args>
126 class BoundMethodFunctor : public BoundMethodArgs<R, Args...>
127 {
128 public:
129  using PackType = typename BoundMethodArgs<R, Args...>::PackType;
130 
131  BoundMethodFunctor(T *obj, Object *object, Func func,
133  : BoundMethodArgs<R, Args...>(obj, object, type), func_(func)
134  {
135  }
136 
137  R activate(Args... args, bool deleteMethod = false) override
138  {
139  if (!this->object_)
140  return func_(args...);
141 
142  auto pack = std::make_shared<PackType>(args...);
143  bool sync = BoundMethodBase::activatePack(pack, deleteMethod);
144  return sync ? pack->returnValue() : R();
145  }
146 
147  R invoke(Args... args) override
148  {
149  return func_(args...);
150  }
151 
152 private:
153  Func func_;
154 };
155 
156 template<typename T, typename R, typename... Args>
157 class BoundMethodMember : public BoundMethodArgs<R, Args...>
158 {
159 public:
160  using PackType = typename BoundMethodArgs<R, Args...>::PackType;
161 
162  BoundMethodMember(T *obj, Object *object, R (T::*func)(Args...),
164  : BoundMethodArgs<R, Args...>(obj, object, type), func_(func)
165  {
166  }
167 
168  bool match(R (T::*func)(Args...)) const { return func == func_; }
169 
170  R activate(Args... args, bool deleteMethod = false) override
171  {
172  if (!this->object_) {
173  T *obj = static_cast<T *>(this->obj_);
174  return (obj->*func_)(args...);
175  }
176 
177  auto pack = std::make_shared<PackType>(args...);
178  bool sync = BoundMethodBase::activatePack(pack, deleteMethod);
179  return sync ? pack->returnValue() : R();
180  }
181 
182  R invoke(Args... args) override
183  {
184  T *obj = static_cast<T *>(this->obj_);
185  return (obj->*func_)(args...);
186  }
187 
188 private:
189  R (T::*func_)(Args...);
190 };
191 
192 template<typename R, typename... Args>
193 class BoundMethodStatic : public BoundMethodArgs<R, Args...>
194 {
195 public:
196  BoundMethodStatic(R (*func)(Args...))
197  : BoundMethodArgs<R, Args...>(nullptr, nullptr, ConnectionTypeAuto),
198  func_(func)
199  {
200  }
201 
202  bool match(R (*func)(Args...)) const { return func == func_; }
203 
204  R activate(Args... args, [[maybe_unused]] bool deleteMethod = false) override
205  {
206  return (*func_)(args...);
207  }
208 
209  R invoke(Args...) override
210  {
211  return R();
212  }
213 
214 private:
215  R (*func_)(Args...);
216 };
217 
218 } /* namespace libcamera */
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
If the sender and the receiver live in the same thread, ConnectionTypeDirect is used. Otherwise ConnectionTypeQueued is used.
Definition: bound_method.h:20