[libcamera-devel] [PATCH 06/18] libcamera: object: Add an asynchronous method invocation method
Niklas Söderlund
niklas.soderlund at ragnatech.se
Sat Aug 17 16:33:07 CEST 2019
Hi Laurent,
Thanks for your work.
On 2019-08-12 15:46:30 +0300, Laurent Pinchart wrote:
> 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 <laurent.pinchart at ideasonboard.com>
I think this patch looks OK but there seems to be some code that should
be moved here from a later patch and I would like to review the final
result before I add my tag. This is tricky enough as it is then copy
pasting code in local meat memory ;-)
> ---
> 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<Message> msg);
>
> + template<typename T, typename... Args, typename std::enable_if<std::is_base_of<Object, T>::value>::type * = nullptr>
> + void invokeMethod(void (T::*func)(Args...), Args... args)
> + {
> + T *obj = static_cast<T *>(this);
> + BoundMethodBase *method = new BoundMemberMethod<T, Args...>(obj, this, func);
> + void *pack = new typename BoundMemberMethod<T, Args...>::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<Message> msg =
> - utils::make_unique<SignalMessage>(this, pack);
> + utils::make_unique<InvokeMessage>(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 <atomic>
>
> +#include <libcamera/bound_method.h>
> +
> 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 <libcamera/signal.h>
> +
> #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<Message> msg)
> void Object::message(Message *msg)
> {
> switch (msg->type()) {
> - case Message::SignalMessage: {
> - SignalMessage *smsg = static_cast<SignalMessage *>(msg);
> - smsg->method_->invokePack(smsg->pack_);
> + case Message::InvokeMessage: {
> + InvokeMessage *iMsg = static_cast<InvokeMessage *>(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<Message> msg =
> + utils::make_unique<InvokeMessage>(method, args, true);
> + postMessage(std::move(msg));
> +}
> +
> /**
> * \fn Object::thread()
> * \brief Retrieve the thread the object is bound to
> --
> Regards,
>
> Laurent Pinchart
>
> _______________________________________________
> libcamera-devel mailing list
> libcamera-devel at lists.libcamera.org
> https://lists.libcamera.org/listinfo/libcamera-devel
--
Regards,
Niklas Söderlund
More information about the libcamera-devel
mailing list