diff options
author | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2021-08-27 04:05:33 +0300 |
---|---|---|
committer | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2021-09-02 01:16:45 +0300 |
commit | 58720e1dc98186e79ef4e758a851b58df562f7b4 (patch) | |
tree | 00c8b9701e937dd1d7a47937bf1792cd623ef834 /include | |
parent | c4e2b00d51f150632b203f81866604168d2ac1ff (diff) |
libcamera: base: signal: Support connecting signals to functors
It can be useful to connect a signal to a functor, and in particular a
lambda function, while still operating in the context of a receiver
object (to support both object-based disconnection and queued
connections to Object instances).
Add a BoundMethodFunctor class to bind a functor, and a corresponding
Signal::connect() function. There is no corresponding disconnect()
function, as a lambda passed to connect() can't be later passed to
disconnect(). Disconnection typically uses disconnect(T *object), which
will cover the vast majority of use cases.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Umang Jain <umang.jain@ideasonboard.com>
Diffstat (limited to 'include')
-rw-r--r-- | include/libcamera/base/bound_method.h | 31 | ||||
-rw-r--r-- | include/libcamera/base/signal.h | 19 |
2 files changed, 50 insertions, 0 deletions
diff --git a/include/libcamera/base/bound_method.h b/include/libcamera/base/bound_method.h index 76ce8017..ebd297ab 100644 --- a/include/libcamera/base/bound_method.h +++ b/include/libcamera/base/bound_method.h @@ -128,6 +128,37 @@ public: virtual R invoke(Args... args) = 0; }; +template<typename T, typename R, typename Func, typename... Args> +class BoundMethodFunctor : public BoundMethodArgs<R, Args...> +{ +public: + using PackType = typename BoundMethodArgs<R, Args...>::PackType; + + BoundMethodFunctor(T *obj, Object *object, Func func, + ConnectionType type = ConnectionTypeAuto) + : BoundMethodArgs<R, Args...>(obj, object, type), func_(func) + { + } + + R activate(Args... args, bool deleteMethod = false) override + { + if (!this->object_) + return func_(args...); + + auto pack = std::make_shared<PackType>(args...); + bool sync = BoundMethodBase::activatePack(pack, deleteMethod); + return sync ? pack->returnValue() : R(); + } + + R invoke(Args... args) override + { + return func_(args...); + } + +private: + Func func_; +}; + template<typename T, typename R, typename... Args> class BoundMethodMember : public BoundMethodArgs<R, Args...> { diff --git a/include/libcamera/base/signal.h b/include/libcamera/base/signal.h index c2521769..8d9f82f6 100644 --- a/include/libcamera/base/signal.h +++ b/include/libcamera/base/signal.h @@ -61,6 +61,25 @@ public: SignalBase::connect(new BoundMethodMember<T, R, Args...>(obj, nullptr, func)); } +#ifndef __DOXYGEN__ + template<typename T, typename Func, + typename std::enable_if_t<std::is_base_of<Object, T>::value> * = nullptr> + void connect(T *obj, Func func, ConnectionType type = ConnectionTypeAuto) + { + Object *object = static_cast<Object *>(obj); + SignalBase::connect(new BoundMethodFunctor<T, void, Func, Args...>(obj, object, func, type)); + } + + template<typename T, typename Func, + typename std::enable_if_t<!std::is_base_of<Object, T>::value> * = nullptr> +#else + template<typename T, typename Func> +#endif + void connect(T *obj, Func func) + { + SignalBase::connect(new BoundMethodFunctor<T, void, Func, Args...>(obj, nullptr, func)); + } + template<typename R> void connect(R (*func)(Args...)) { |