libcamera v0.5.1
Supporting cameras in Linux since 2019
Loading...
Searching...
No Matches
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
15namespace libcamera {
16
17class Object;
18
25
26class BoundMethodPackBase
27{
28public:
29 virtual ~BoundMethodPackBase() = default;
30};
31
32template<typename R, typename... Args>
33class BoundMethodPack : public BoundMethodPackBase
34{
35public:
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
50template<typename... Args>
51class BoundMethodPack<void, Args...> : public BoundMethodPackBase
52{
53public:
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
66class BoundMethodBase
67{
68public:
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
83protected:
84 bool activatePack(std::shared_ptr<BoundMethodPackBase> pack,
85 bool deleteMethod);
86
87 void *obj_;
88 Object *object_;
89
90private:
91 ConnectionType connectionType_;
92};
93
94template<typename R, typename... Args>
95class BoundMethodArgs : public BoundMethodBase
96{
97public:
98 using PackType = BoundMethodPack<R, Args...>;
99
100private:
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
112public:
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
125template<typename T, typename R, typename Func, typename... Args>
126class BoundMethodFunctor : public BoundMethodArgs<R, Args...>
127{
128public:
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
152private:
153 Func func_;
154};
155
156template<typename T, typename R, typename... Args>
157class BoundMethodMember : public BoundMethodArgs<R, Args...>
158{
159public:
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
188private:
189 R (T::*func_)(Args...);
190};
191
192template<typename R, typename... Args>
193class BoundMethodStatic : public BoundMethodArgs<R, Args...>
194{
195public:
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
214private:
215 R (*func_)(Args...);
216};
217
218} /* namespace libcamera */
Base object to support automatic signal disconnection.
Definition object.h:27
Top-level libcamera namespace.
Definition backtrace.h:17
ConnectionType
Connection type for asynchronous communication.
Definition bound_method.h:19
@ ConnectionTypeDirect
The receiver is invoked immediately and synchronously in the sender's thread.
Definition bound_method.h:21
@ ConnectionTypeBlocking
The receiver is invoked synchronously.
Definition bound_method.h:23
@ ConnectionTypeQueued
The receiver is invoked asynchronously.
Definition bound_method.h:22
@ ConnectionTypeAuto
If the sender and the receiver live in the same thread, ConnectionTypeDirect is used....
Definition bound_method.h:20