summaryrefslogtreecommitdiff
path: root/include/libcamera/bound_method.h
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>2020-01-03 22:53:09 +0200
committerLaurent Pinchart <laurent.pinchart@ideasonboard.com>2020-01-07 22:29:35 +0200
commit3d1d2081714f316483dddf573105682910b026bc (patch)
tree36e88d9acf0e6ed35856ea0a7b9d9a9f617d6f3d /include/libcamera/bound_method.h
parentb0135a1522ed4217a8deb7929fdb36276e58161b (diff)
libcamera: bound_method: Propagate method return value
Propagate the return value of the bound method all the way to the caller of activate(). The value is stored in the arguments pack for indirect invocation. As C++ doesn't allow instantiating a variable of type void, we need to specialize the template class BoundMethodPack for methods returning void. This in turn requires template specialization for the BoundMethodArgs class in order to store the return value in the pack, and for the BoundMemberMethod class to extract the return value from the pack. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
Diffstat (limited to 'include/libcamera/bound_method.h')
-rw-r--r--include/libcamera/bound_method.h99
1 files changed, 86 insertions, 13 deletions
diff --git a/include/libcamera/bound_method.h b/include/libcamera/bound_method.h
index a74d2c50..0a91f44a 100644
--- a/include/libcamera/bound_method.h
+++ b/include/libcamera/bound_method.h
@@ -28,7 +28,7 @@ public:
virtual ~BoundMethodPackBase() {}
};
-template<typename... Args>
+template<typename R, typename... Args>
class BoundMethodPack : public BoundMethodPackBase
{
public:
@@ -38,6 +38,19 @@ public:
}
std::tuple<typename std::remove_reference<Args>::type...> args_;
+ R ret_;
+};
+
+template<typename... Args>
+class BoundMethodPack<void, Args...> : public BoundMethodPackBase
+{
+public:
+ BoundMethodPack(const Args &... args)
+ : args_(args...)
+ {
+ }
+
+ std::tuple<typename std::remove_reference<Args>::type...> args_;
};
class BoundMethodBase
@@ -77,7 +90,7 @@ protected:
};
#endif
- void activatePack(std::shared_ptr<BoundMethodPackBase> pack,
+ bool activatePack(std::shared_ptr<BoundMethodPackBase> pack,
bool deleteMethod);
void *obj_;
@@ -91,7 +104,34 @@ template<typename R, typename... Args>
class BoundMethodArgs : public BoundMethodBase
{
public:
- using PackType = BoundMethodPack<Args...>;
+ using PackType = BoundMethodPack<R, Args...>;
+
+private:
+ template<int... S>
+ void invokePack(BoundMethodPackBase *pack, BoundMethodBase::sequence<S...>)
+ {
+ PackType *args = static_cast<PackType *>(pack);
+ args->ret_ = invoke(std::get<S>(args->args_)...);
+ }
+
+public:
+ BoundMethodArgs(void *obj, Object *object, ConnectionType type)
+ : BoundMethodBase(obj, object, type) {}
+
+ void invokePack(BoundMethodPackBase *pack) override
+ {
+ invokePack(pack, typename BoundMethodBase::generator<sizeof...(Args)>::type());
+ }
+
+ virtual R activate(Args... args, bool deleteMethod = false) = 0;
+ virtual R invoke(Args... args) = 0;
+};
+
+template<typename... Args>
+class BoundMethodArgs<void, Args...> : public BoundMethodBase
+{
+public:
+ using PackType = BoundMethodPack<void, Args...>;
private:
template<int... S>
@@ -129,15 +169,45 @@ public:
bool match(R (T::*func)(Args...)) const { return func == func_; }
+ R activate(Args... args, bool deleteMethod = false) override
+ {
+ if (!this->object_)
+ return (static_cast<T *>(this->obj_)->*func_)(args...);
+
+ auto pack = std::make_shared<PackType>(args...);
+ bool sync = BoundMethodBase::activatePack(pack, deleteMethod);
+ return sync ? pack->ret_ : R();
+ }
+
+ R invoke(Args... args) override
+ {
+ return (static_cast<T *>(this->obj_)->*func_)(args...);
+ }
+
+private:
+ R (T::*func_)(Args...);
+};
+
+template<typename T, typename... Args>
+class BoundMemberMethod<T, void, Args...> : public BoundMethodArgs<void, Args...>
+{
+public:
+ using PackType = typename BoundMethodArgs<void *, Args...>::PackType;
+
+ BoundMemberMethod(T *obj, Object *object, void (T::*func)(Args...),
+ ConnectionType type = ConnectionTypeAuto)
+ : BoundMethodArgs<void, Args...>(obj, object, type), func_(func)
+ {
+ }
+
+ bool match(void (T::*func)(Args...)) const { return func == func_; }
+
void activate(Args... args, bool deleteMethod = false) override
{
- if (!this->object_) {
- (static_cast<T *>(this->obj_)->*func_)(args...);
- return;
- }
+ if (!this->object_)
+ return (static_cast<T *>(this->obj_)->*func_)(args...);
- std::shared_ptr<BoundMethodPackBase> pack =
- std::make_shared<typename BoundMemberMethod<T, R, Args...>::PackType>(args...);
+ auto pack = std::make_shared<PackType>(args...);
BoundMethodBase::activatePack(pack, deleteMethod);
}
@@ -147,7 +217,7 @@ public:
}
private:
- R (T::*func_)(Args...);
+ void (T::*func_)(Args...);
};
template<typename R, typename... Args>
@@ -162,12 +232,15 @@ public:
bool match(R (*func)(Args...)) const { return func == func_; }
- void activate(Args... args, bool deleteMethod = false) override
+ R activate(Args... args, bool deleteMethod = false) override
{
- (*func_)(args...);
+ return (*func_)(args...);
}
- void invoke(Args...) override {}
+ R invoke(Args...) override
+ {
+ return R();
+ }
private:
R (*func_)(Args...);