libcamera v0.7.1+1-5701eb5f-nvm
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 template<typename... Ts>
37 BoundMethodPack(Ts &&...args)
38 : args_(std::forward<Ts>(args)...)
39 {
40 }
41
42 std::tuple<std::remove_cv_t<std::remove_reference_t<Args>>...> args_;
43 R ret_;
44};
45
46template<typename... Args>
47class BoundMethodPack<void, Args...> : public BoundMethodPackBase
48{
49public:
50 template<typename... Ts>
51 BoundMethodPack(Ts &&...args)
52 : args_(std::forward<Ts>(args)...)
53 {
54 }
55
56 std::tuple<std::remove_cv_t<std::remove_reference_t<Args>>...> args_;
57};
58
59class BoundMethodBase
60{
61public:
62 BoundMethodBase(void *obj, Object *object, ConnectionType type)
63 : obj_(obj), object_(object), connectionType_(type)
64 {
65 }
66 virtual ~BoundMethodBase() = default;
67
68 template<typename T, std::enable_if_t<!std::is_same<Object, T>::value> * = nullptr>
69 bool match(T *obj) { return obj == obj_; }
70 bool match(Object *object) { return object == object_; }
71
72 Object *object() const { return object_; }
73
74 virtual void invokePack(BoundMethodPackBase *pack) = 0;
75
76protected:
77 bool activatePack(std::shared_ptr<BoundMethodPackBase> pack,
78 bool deleteMethod);
79
80 void *obj_;
81 Object *object_;
82
83private:
84 ConnectionType connectionType_;
85};
86
87template<typename R, typename... Args>
88class BoundMethodArgs : public BoundMethodBase
89{
90public:
91 using PackType = BoundMethodPack<R, Args...>;
92
93 BoundMethodArgs(void *obj, Object *object, ConnectionType type)
94 : BoundMethodBase(obj, object, type) {}
95
96 void invokePack(BoundMethodPackBase *pack) override
97 {
98 auto *argsPack = static_cast<PackType *>(pack);
99
100 std::apply([&](Args &&...args) {
101 if constexpr (!std::is_void_v<R>)
102 argsPack->ret_ = invoke(std::forward<decltype(args)>(args)...);
103 else
104 invoke(std::forward<decltype(args)>(args)...);
105 }, std::move(argsPack->args_));
106 }
107
108 virtual R activate(Args... args, bool deleteMethod = false) = 0;
109 virtual R invoke(Args... args) = 0;
110};
111
112template<typename T, typename R, typename Func, typename... Args>
113class BoundMethodFunctor : public BoundMethodArgs<R, Args...>
114{
115public:
116 using PackType = typename BoundMethodArgs<R, Args...>::PackType;
117
118 BoundMethodFunctor(T *obj, Object *object, Func func,
120 : BoundMethodArgs<R, Args...>(obj, object, type), func_(std::move(func))
121 {
122 }
123
124 R activate(Args... args, bool deleteMethod = false) override
125 {
126 if (!this->object_)
127 return func_(std::forward<Args>(args)...);
128
129 auto pack = std::make_shared<PackType>(std::forward<Args>(args)...);
130 [[maybe_unused]] bool sync = BoundMethodBase::activatePack(pack, deleteMethod);
131
132 if constexpr (!std::is_void_v<R>)
133 return sync ? std::move(pack->ret_) : R();
134 }
135
136 R invoke(Args... args) override
137 {
138 return func_(std::forward<Args>(args)...);
139 }
140
141private:
142 Func func_;
143};
144
145template<typename T, typename R, typename... Args>
146class BoundMethodMember : public BoundMethodArgs<R, Args...>
147{
148public:
149 using PackType = typename BoundMethodArgs<R, Args...>::PackType;
150
151 BoundMethodMember(T *obj, Object *object, R (T::*func)(Args...),
153 : BoundMethodArgs<R, Args...>(obj, object, type), func_(func)
154 {
155 }
156
157 bool match(R (T::*func)(Args...)) const { return func == func_; }
158
159 R activate(Args... args, bool deleteMethod = false) override
160 {
161 if (!this->object_) {
162 T *obj = static_cast<T *>(this->obj_);
163 return (obj->*func_)(std::forward<Args>(args)...);
164 }
165
166 auto pack = std::make_shared<PackType>(std::forward<Args>(args)...);
167 [[maybe_unused]] bool sync = BoundMethodBase::activatePack(pack, deleteMethod);
168
169 if constexpr (!std::is_void_v<R>)
170 return sync ? std::move(pack->ret_) : R();
171 }
172
173 R invoke(Args... args) override
174 {
175 T *obj = static_cast<T *>(this->obj_);
176 return (obj->*func_)(std::forward<Args>(args)...);
177 }
178
179private:
180 R (T::*func_)(Args...);
181};
182
183template<typename R, typename... Args>
184class BoundMethodStatic : public BoundMethodArgs<R, Args...>
185{
186public:
187 BoundMethodStatic(R (*func)(Args...))
188 : BoundMethodArgs<R, Args...>(nullptr, nullptr, ConnectionTypeAuto),
189 func_(func)
190 {
191 }
192
193 bool match(R (*func)(Args...)) const { return func == func_; }
194
195 R activate(Args... args, [[maybe_unused]] bool deleteMethod = false) override
196 {
197 return (*func_)(std::forward<Args>(args)...);
198 }
199
200 R invoke(Args...) override
201 {
202 return R();
203 }
204
205private:
206 R (*func_)(Args...);
207};
208
209} /* namespace libcamera */
Top-level libcamera namespace.
Definition bound_method.h:15
ConnectionType
Connection type for asynchronous communication.
Definition bound_method.h:19
@ ConnectionTypeQueued
The receiver is invoked asynchronously.
Definition bound_method.h:22
@ ConnectionTypeDirect
The receiver is invoked immediately and synchronously in the sender's thread.
Definition bound_method.h:21
@ ConnectionTypeAuto
If the sender and the receiver live in the same thread, ConnectionTypeDirect is used....
Definition bound_method.h:20
@ ConnectionTypeBlocking
The receiver is invoked synchronously.
Definition bound_method.h:23