From patchwork Sat Aug 17 15:20:52 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 1824 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 321956191D for ; Sat, 17 Aug 2019 17:21:15 +0200 (CEST) Received: from pendragon.bb.dnainternet.fi (dfj612yhrgyx302h3jwwy-3.rev.dnainternet.fi [IPv6:2001:14ba:21f5:5b00:ce28:277f:58d7:3ca4]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id C0DD3556 for ; Sat, 17 Aug 2019 17:21:14 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1566055274; bh=99IHcKULPualFbgtnnuFGfw0K+m4RMi8R4+k7pu0gTg=; h=From:To:Subject:Date:In-Reply-To:References:From; b=IjU6azW8BTu3VXf1mbqVtzQeK8j316S5c2tQwKHk9GezvBgEZaJbnpYNIHY8gCiVn Ha1QDjoczS6CyVoOcHyCGfbmyISHpn7DSrn3RHeYmBeyYrp+CAclo2sm5K7jsvKHCH A//H89Os3DofsAHMbVVuMWwem5Zj6cNfU80TxUAE= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Sat, 17 Aug 2019 18:20:52 +0300 Message-Id: <20190817152104.10834-7-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190817152104.10834-1-laurent.pinchart@ideasonboard.com> References: <20190817152104.10834-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 06/18] libcamera: object: Add an asynchronous method invocation method X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 17 Aug 2019 15:21:16 -0000 Add a helper invokeMethod() to the Object class that allows asynchrnous invocation of any method of an Object instance. Asynchronous invocation occurs when control returns to the event dispatcher of the target object's thread, in the context of that thread. To support this, generalise the SignalMessage implementation to support automatic deletion of the associated BoundMethod, and rename the message to InvokeMessage to reflect the more generic purpose. Signed-off-by: Laurent Pinchart Reviewed-by: Jacopo Mondi Reviewed-by: Niklas Söderlund --- include/libcamera/object.h | 12 +++++++++ src/libcamera/bound_method.cpp | 2 +- src/libcamera/include/message.h | 17 +++++++----- src/libcamera/message.cpp | 48 ++++++++++++++++++++++++--------- src/libcamera/object.cpp | 29 +++++++++++++++++--- 5 files changed, 86 insertions(+), 22 deletions(-) diff --git a/include/libcamera/object.h b/include/libcamera/object.h index e3b39cf547b0..869200a57d8c 100644 --- a/include/libcamera/object.h +++ b/include/libcamera/object.h @@ -28,6 +28,16 @@ public: void postMessage(std::unique_ptr msg); + template::value>::type * = nullptr> + void invokeMethod(void (T::*func)(Args...), Args... args) + { + T *obj = static_cast(this); + BoundMethodBase *method = new BoundMemberMethod(obj, this, func); + void *pack = new typename BoundMemberMethod::PackType{ args... }; + + invokeMethod(method, pack); + } + Thread *thread() const { return thread_; } void moveToThread(Thread *thread); @@ -40,6 +50,8 @@ private: friend class BoundMethodBase; friend class Thread; + void invokeMethod(BoundMethodBase *method, void *pack); + void connect(SignalBase *signal); void disconnect(SignalBase *signal); diff --git a/src/libcamera/bound_method.cpp b/src/libcamera/bound_method.cpp index 23b8f4122283..d89f84c03f4d 100644 --- a/src/libcamera/bound_method.cpp +++ b/src/libcamera/bound_method.cpp @@ -19,7 +19,7 @@ void BoundMethodBase::activatePack(void *pack) invokePack(pack); } else { std::unique_ptr msg = - utils::make_unique(this, pack); + utils::make_unique(this, pack); object_->postMessage(std::move(msg)); } } diff --git a/src/libcamera/include/message.h b/src/libcamera/include/message.h index b4670c0eab76..92717e316cc3 100644 --- a/src/libcamera/include/message.h +++ b/src/libcamera/include/message.h @@ -9,6 +9,8 @@ #include +#include + namespace libcamera { class BoundMethodBase; @@ -20,7 +22,7 @@ class Message public: enum Type { None = 0, - SignalMessage = 1, + InvokeMessage = 1, UserMessage = 1000, }; @@ -41,16 +43,19 @@ private: static std::atomic_uint nextUserType_; }; -class SignalMessage : public Message +class InvokeMessage : public Message { public: - SignalMessage(BoundMethodBase *method, void *pack) - : Message(Message::SignalMessage), method_(method), pack_(pack) - { - } + InvokeMessage(BoundMethodBase *method, void *pack, + bool deleteMethod = false); + ~InvokeMessage(); + void invoke(); + +private: BoundMethodBase *method_; void *pack_; + bool deleteMethod_; }; } /* namespace libcamera */ diff --git a/src/libcamera/message.cpp b/src/libcamera/message.cpp index 8d3376d8a533..f6c39d40fc73 100644 --- a/src/libcamera/message.cpp +++ b/src/libcamera/message.cpp @@ -7,6 +7,8 @@ #include "message.h" +#include + #include "log.h" /** @@ -43,8 +45,8 @@ std::atomic_uint Message::nextUserType_{ Message::UserMessage }; * \brief The message type * \var Message::None * \brief Invalid message type - * \var Message::SignalMessage - * \brief Asynchronous signal delivery across threads + * \var Message::InvokeMessage + * \brief Asynchronous method invocation across threads * \var Message::UserMessage * \brief First value available for user-defined messages */ @@ -107,25 +109,47 @@ Message::Type Message::registerMessageType() } /** - * \class SignalMessage - * \brief A message carrying a Signal across threads + * \class InvokeMessage + * \brief A message carrying a method invocation across threads */ /** - * \fn SignalMessage::SignalMessage() - * \brief Construct a SignalMessage - * \param[in] method The slot that the signal targets - * \param[in] pack The signal arguments + * \brief Construct an InvokeMessage for method invocation on an Object + * \param[in] method The bound method + * \param[in] pack The packed method arguments + * \param[in] deleteMethod True to delete the \a method when the message is + * destroyed */ +InvokeMessage::InvokeMessage(BoundMethodBase *method, void *pack, + bool deleteMethod) + : Message(Message::InvokeMessage), method_(method), pack_(pack), + deleteMethod_(deleteMethod) +{ +} + +InvokeMessage::~InvokeMessage() +{ + if (deleteMethod_) + delete method_; +} + +/** + * \brief Invoke the method bound to InvokeMessage::method_ with arguments + * InvokeMessage::pack_ + */ +void InvokeMessage::invoke() +{ + method_->invokePack(pack_); +} /** - * \var SignalMessage::method_ - * \brief The slot that the signal targets + * \var InvokeMessage::method_ + * \brief The method to be invoked */ /** - * \var SignalMessage::pack_ - * \brief The signal arguments + * \var InvokeMessage::pack_ + * \brief The packed method invocation arguments */ }; /* namespace libcamera */ diff --git a/src/libcamera/object.cpp b/src/libcamera/object.cpp index 0adbc203add8..7d70ce21b5d0 100644 --- a/src/libcamera/object.cpp +++ b/src/libcamera/object.cpp @@ -12,6 +12,7 @@ #include "log.h" #include "message.h" #include "thread.h" +#include "utils.h" /** * \file object.h @@ -88,9 +89,9 @@ void Object::postMessage(std::unique_ptr msg) void Object::message(Message *msg) { switch (msg->type()) { - case Message::SignalMessage: { - SignalMessage *smsg = static_cast(msg); - smsg->method_->invokePack(smsg->pack_); + case Message::InvokeMessage: { + InvokeMessage *iMsg = static_cast(msg); + iMsg->invoke(); break; } @@ -99,6 +100,28 @@ void Object::message(Message *msg) } } +/** + * \fn void Object::invokeMethod(void (T::*func)(Args...), Args... args) + * \brief Invoke a method asynchronously on an Object instance + * \param[in] func The object method to invoke + * \param[in] args The method arguments + * + * This method invokes the member method \a func when control returns to the + * event loop of the object's thread. The method is executed in the object's + * thread with arguments \a args. + * + * Arguments \a args passed by value or reference are copied, while pointers + * are passed untouched. The caller shall ensure that any pointer argument + * remains valid until the method is invoked. + */ + +void Object::invokeMethod(BoundMethodBase *method, void *args) +{ + std::unique_ptr msg = + utils::make_unique(method, args, true); + postMessage(std::move(msg)); +} + /** * \fn Object::thread() * \brief Retrieve the thread the object is bound to