diff options
author | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2020-01-04 04:18:05 +0200 |
---|---|---|
committer | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2020-01-07 22:29:31 +0200 |
commit | b0135a1522ed4217a8deb7929fdb36276e58161b (patch) | |
tree | 2a435222aefe9f9440818626b0add617666270e9 /include | |
parent | 621edb2367e81860f6b6e89243ad7cbe3e0b6b7f (diff) |
libcamera: bound_method: Manage BoundMethodPack through std::shared_ptr
The bound method arguments pack will need to be accessed by the method
invoker in order to retrieve the method return value when using a
blocking connection type. We thus can't delete the pack unconditionally
in the bound method target thread. We also can't delete it
unconditionally in the invoker's thread, as for queued connections the
pack will be used in the target thread after the invoker completes.
This shows that ownership of the arguments pack is shared between two
contexts. As a result, manage it using std::shared_ptr<>.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
Diffstat (limited to 'include')
-rw-r--r-- | include/libcamera/bound_method.h | 54 |
1 files changed, 33 insertions, 21 deletions
diff --git a/include/libcamera/bound_method.h b/include/libcamera/bound_method.h index b50072ff..a74d2c50 100644 --- a/include/libcamera/bound_method.h +++ b/include/libcamera/bound_method.h @@ -7,6 +7,7 @@ #ifndef __LIBCAMERA_BOUND_METHOD_H__ #define __LIBCAMERA_BOUND_METHOD_H__ +#include <memory> #include <tuple> #include <type_traits> @@ -21,6 +22,24 @@ enum ConnectionType { ConnectionTypeBlocking, }; +class BoundMethodPackBase +{ +public: + virtual ~BoundMethodPackBase() {} +}; + +template<typename... Args> +class BoundMethodPack : public BoundMethodPackBase +{ +public: + BoundMethodPack(const Args &... args) + : args_(args...) + { + } + + std::tuple<typename std::remove_reference<Args>::type...> args_; +}; + class BoundMethodBase { public: @@ -36,7 +55,7 @@ public: Object *object() const { return object_; } - virtual void invokePack(void *pack) = 0; + virtual void invokePack(BoundMethodPackBase *pack) = 0; protected: #ifndef __DOXYGEN__ @@ -58,7 +77,8 @@ protected: }; #endif - void activatePack(void *pack, bool deleteMethod); + void activatePack(std::shared_ptr<BoundMethodPackBase> pack, + bool deleteMethod); void *obj_; Object *object_; @@ -67,18 +87,6 @@ private: ConnectionType connectionType_; }; -template<typename... Args> -class BoundMethodPack -{ -public: - BoundMethodPack(const Args &... args) - : args_(args...) - { - } - - std::tuple<typename std::remove_reference<Args>::type...> args_; -}; - template<typename R, typename... Args> class BoundMethodArgs : public BoundMethodBase { @@ -87,18 +95,18 @@ public: private: template<int... S> - void invokePack(void *pack, BoundMethodBase::sequence<S...>) + void invokePack(BoundMethodPackBase *pack, BoundMethodBase::sequence<S...>) { - PackType *args = static_cast<PackType *>(pack); + /* args is effectively unused when the sequence S is empty. */ + PackType *args [[gnu::unused]] = static_cast<PackType *>(pack); invoke(std::get<S>(args->args_)...); - delete args; } public: BoundMethodArgs(void *obj, Object *object, ConnectionType type) : BoundMethodBase(obj, object, type) {} - void invokePack(void *pack) override + void invokePack(BoundMethodPackBase *pack) override { invokePack(pack, typename BoundMethodBase::generator<sizeof...(Args)>::type()); } @@ -123,10 +131,14 @@ public: void activate(Args... args, bool deleteMethod = false) override { - if (this->object_) - BoundMethodBase::activatePack(new PackType{ args... }, deleteMethod); - else + if (!this->object_) { (static_cast<T *>(this->obj_)->*func_)(args...); + return; + } + + std::shared_ptr<BoundMethodPackBase> pack = + std::make_shared<typename BoundMemberMethod<T, R, Args...>::PackType>(args...); + BoundMethodBase::activatePack(pack, deleteMethod); } void invoke(Args... args) override |