From b0135a1522ed4217a8deb7929fdb36276e58161b Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sat, 4 Jan 2020 04:18:05 +0200 Subject: libcamera: bound_method: Manage BoundMethodPack through std::shared_ptr MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Reviewed-by: Niklas Söderlund --- Documentation/Doxyfile.in | 1 + include/libcamera/bound_method.h | 54 ++++++++++++++++++++++++---------------- src/libcamera/bound_method.cpp | 5 ++-- src/libcamera/include/message.h | 5 ++-- src/libcamera/message.cpp | 5 ++-- 5 files changed, 43 insertions(+), 27 deletions(-) diff --git a/Documentation/Doxyfile.in b/Documentation/Doxyfile.in index 9e5efae3..5ae8773b 100644 --- a/Documentation/Doxyfile.in +++ b/Documentation/Doxyfile.in @@ -874,6 +874,7 @@ EXCLUDE_SYMBOLS = libcamera::BoundMemberMethod \ libcamera::BoundMethodArgs \ libcamera::BoundMethodBase \ libcamera::BoundMethodPack \ + libcamera::BoundMethodPackBase \ libcamera::BoundStaticMethod \ libcamera::SignalBase \ std::* 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 #include #include @@ -21,6 +22,24 @@ enum ConnectionType { ConnectionTypeBlocking, }; +class BoundMethodPackBase +{ +public: + virtual ~BoundMethodPackBase() {} +}; + +template +class BoundMethodPack : public BoundMethodPackBase +{ +public: + BoundMethodPack(const Args &... args) + : args_(args...) + { + } + + std::tuple::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 pack, + bool deleteMethod); void *obj_; Object *object_; @@ -67,18 +87,6 @@ private: ConnectionType connectionType_; }; -template -class BoundMethodPack -{ -public: - BoundMethodPack(const Args &... args) - : args_(args...) - { - } - - std::tuple::type...> args_; -}; - template class BoundMethodArgs : public BoundMethodBase { @@ -87,18 +95,18 @@ public: private: template - void invokePack(void *pack, BoundMethodBase::sequence) + void invokePack(BoundMethodPackBase *pack, BoundMethodBase::sequence) { - PackType *args = static_cast(pack); + /* args is effectively unused when the sequence S is empty. */ + PackType *args [[gnu::unused]] = static_cast(pack); invoke(std::get(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::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(this->obj_)->*func_)(args...); + return; + } + + std::shared_ptr pack = + std::make_shared::PackType>(args...); + BoundMethodBase::activatePack(pack, deleteMethod); } void invoke(Args... args) override diff --git a/src/libcamera/bound_method.cpp b/src/libcamera/bound_method.cpp index 45c76577..82339b7e 100644 --- a/src/libcamera/bound_method.cpp +++ b/src/libcamera/bound_method.cpp @@ -48,7 +48,8 @@ namespace libcamera { * deadlock will occur. */ -void BoundMethodBase::activatePack(void *pack, bool deleteMethod) +void BoundMethodBase::activatePack(std::shared_ptr pack, + bool deleteMethod) { ConnectionType type = connectionType_; if (type == ConnectionTypeAuto) { @@ -61,7 +62,7 @@ void BoundMethodBase::activatePack(void *pack, bool deleteMethod) switch (type) { case ConnectionTypeDirect: default: - invokePack(pack); + invokePack(pack.get()); if (deleteMethod) delete this; break; diff --git a/src/libcamera/include/message.h b/src/libcamera/include/message.h index 311755cc..8e8b013d 100644 --- a/src/libcamera/include/message.h +++ b/src/libcamera/include/message.h @@ -48,7 +48,8 @@ private: class InvokeMessage : public Message { public: - InvokeMessage(BoundMethodBase *method, void *pack, + InvokeMessage(BoundMethodBase *method, + std::shared_ptr pack, Semaphore *semaphore = nullptr, bool deleteMethod = false); ~InvokeMessage(); @@ -59,7 +60,7 @@ public: private: BoundMethodBase *method_; - void *pack_; + std::shared_ptr pack_; Semaphore *semaphore_; bool deleteMethod_; }; diff --git a/src/libcamera/message.cpp b/src/libcamera/message.cpp index c35bb33d..77f2bdd5 100644 --- a/src/libcamera/message.cpp +++ b/src/libcamera/message.cpp @@ -123,7 +123,8 @@ Message::Type Message::registerMessageType() * \param[in] deleteMethod True to delete the \a method when the message is * destroyed */ -InvokeMessage::InvokeMessage(BoundMethodBase *method, void *pack, +InvokeMessage::InvokeMessage(BoundMethodBase *method, + std::shared_ptr pack, Semaphore *semaphore, bool deleteMethod) : Message(Message::InvokeMessage), method_(method), pack_(pack), semaphore_(semaphore), deleteMethod_(deleteMethod) @@ -148,7 +149,7 @@ InvokeMessage::~InvokeMessage() */ void InvokeMessage::invoke() { - method_->invokePack(pack_); + method_->invokePack(pack_.get()); } /** -- cgit v1.2.1