[{"id":2432,"web_url":"https://patchwork.libcamera.org/comment/2432/","msgid":"<20190817143307.GJ16603@wyvern>","date":"2019-08-17T14:33:07","subject":"Re: [libcamera-devel] [PATCH 06/18] libcamera: object: Add an\n\tasynchronous method invocation method","submitter":{"id":5,"url":"https://patchwork.libcamera.org/api/people/5/","name":"Niklas Söderlund","email":"niklas.soderlund@ragnatech.se"},"content":"Hi Laurent,\n\nThanks for your work.\n\nOn 2019-08-12 15:46:30 +0300, Laurent Pinchart wrote:\n> Add a helper invokeMethod() to the Object class that allows asynchrnous\n> invocation of any method of an Object instance. Asynchronous invocation\n> occurs when control returns to the event dispatcher of the target\n> object's thread, in the context of that thread.\n> \n> To support this, generalise the SignalMessage implementation to support\n> automatic deletion of the associated BoundMethod, and rename the message\n> to InvokeMessage to reflect the more generic purpose.\n> \n> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n\nI think this patch looks OK but there seems to be some code that should \nbe moved here from a later patch and I would like to review the final \nresult before I add my tag. This is tricky enough as it is then copy \npasting code in local meat memory ;-)\n\n> ---\n>  include/libcamera/object.h      | 12 +++++++++\n>  src/libcamera/bound_method.cpp  |  2 +-\n>  src/libcamera/include/message.h | 17 +++++++-----\n>  src/libcamera/message.cpp       | 48 ++++++++++++++++++++++++---------\n>  src/libcamera/object.cpp        | 29 +++++++++++++++++---\n>  5 files changed, 86 insertions(+), 22 deletions(-)\n> \n> diff --git a/include/libcamera/object.h b/include/libcamera/object.h\n> index e3b39cf547b0..869200a57d8c 100644\n> --- a/include/libcamera/object.h\n> +++ b/include/libcamera/object.h\n> @@ -28,6 +28,16 @@ public:\n>  \n>  \tvoid postMessage(std::unique_ptr<Message> msg);\n>  \n> +\ttemplate<typename T, typename... Args, typename std::enable_if<std::is_base_of<Object, T>::value>::type * = nullptr>\n> +\tvoid invokeMethod(void (T::*func)(Args...), Args... args)\n> +\t{\n> +\t\tT *obj = static_cast<T *>(this);\n> +\t\tBoundMethodBase *method = new BoundMemberMethod<T, Args...>(obj, this, func);\n> +\t\tvoid *pack = new typename BoundMemberMethod<T, Args...>::PackType{ args... };\n> +\n> +\t\tinvokeMethod(method, pack);\n> +\t}\n> +\n>  \tThread *thread() const { return thread_; }\n>  \tvoid moveToThread(Thread *thread);\n>  \n> @@ -40,6 +50,8 @@ private:\n>  \tfriend class BoundMethodBase;\n>  \tfriend class Thread;\n>  \n> +\tvoid invokeMethod(BoundMethodBase *method, void *pack);\n> +\n>  \tvoid connect(SignalBase *signal);\n>  \tvoid disconnect(SignalBase *signal);\n>  \n> diff --git a/src/libcamera/bound_method.cpp b/src/libcamera/bound_method.cpp\n> index 23b8f4122283..d89f84c03f4d 100644\n> --- a/src/libcamera/bound_method.cpp\n> +++ b/src/libcamera/bound_method.cpp\n> @@ -19,7 +19,7 @@ void BoundMethodBase::activatePack(void *pack)\n>  \t\tinvokePack(pack);\n>  \t} else {\n>  \t\tstd::unique_ptr<Message> msg =\n> -\t\t\tutils::make_unique<SignalMessage>(this, pack);\n> +\t\t\tutils::make_unique<InvokeMessage>(this, pack);\n>  \t\tobject_->postMessage(std::move(msg));\n>  \t}\n>  }\n> diff --git a/src/libcamera/include/message.h b/src/libcamera/include/message.h\n> index b4670c0eab76..92717e316cc3 100644\n> --- a/src/libcamera/include/message.h\n> +++ b/src/libcamera/include/message.h\n> @@ -9,6 +9,8 @@\n>  \n>  #include <atomic>\n>  \n> +#include <libcamera/bound_method.h>\n> +\n>  namespace libcamera {\n>  \n>  class BoundMethodBase;\n> @@ -20,7 +22,7 @@ class Message\n>  public:\n>  \tenum Type {\n>  \t\tNone = 0,\n> -\t\tSignalMessage = 1,\n> +\t\tInvokeMessage = 1,\n>  \t\tUserMessage = 1000,\n>  \t};\n>  \n> @@ -41,16 +43,19 @@ private:\n>  \tstatic std::atomic_uint nextUserType_;\n>  };\n>  \n> -class SignalMessage : public Message\n> +class InvokeMessage : public Message\n>  {\n>  public:\n> -\tSignalMessage(BoundMethodBase *method, void *pack)\n> -\t\t: Message(Message::SignalMessage), method_(method), pack_(pack)\n> -\t{\n> -\t}\n> +\tInvokeMessage(BoundMethodBase *method, void *pack,\n> +\t\t      bool deleteMethod = false);\n> +\t~InvokeMessage();\n>  \n> +\tvoid invoke();\n> +\n> +private:\n>  \tBoundMethodBase *method_;\n>  \tvoid *pack_;\n> +\tbool deleteMethod_;\n>  };\n>  \n>  } /* namespace libcamera */\n> diff --git a/src/libcamera/message.cpp b/src/libcamera/message.cpp\n> index 8d3376d8a533..f6c39d40fc73 100644\n> --- a/src/libcamera/message.cpp\n> +++ b/src/libcamera/message.cpp\n> @@ -7,6 +7,8 @@\n>  \n>  #include \"message.h\"\n>  \n> +#include <libcamera/signal.h>\n> +\n>  #include \"log.h\"\n>  \n>  /**\n> @@ -43,8 +45,8 @@ std::atomic_uint Message::nextUserType_{ Message::UserMessage };\n>   * \\brief The message type\n>   * \\var Message::None\n>   * \\brief Invalid message type\n> - * \\var Message::SignalMessage\n> - * \\brief Asynchronous signal delivery across threads\n> + * \\var Message::InvokeMessage\n> + * \\brief Asynchronous method invocation across threads\n>   * \\var Message::UserMessage\n>   * \\brief First value available for user-defined messages\n>   */\n> @@ -107,25 +109,47 @@ Message::Type Message::registerMessageType()\n>  }\n>  \n>  /**\n> - * \\class SignalMessage\n> - * \\brief A message carrying a Signal across threads\n> + * \\class InvokeMessage\n> + * \\brief A message carrying a method invocation across threads\n>   */\n>  \n>  /**\n> - * \\fn SignalMessage::SignalMessage()\n> - * \\brief Construct a SignalMessage\n> - * \\param[in] method The slot that the signal targets\n> - * \\param[in] pack The signal arguments\n> + * \\brief Construct an InvokeMessage for method invocation on an Object\n> + * \\param[in] method The bound method\n> + * \\param[in] pack The packed method arguments\n> + * \\param[in] deleteMethod True to delete the \\a method when the message is\n> + * destroyed\n>   */\n> +InvokeMessage::InvokeMessage(BoundMethodBase *method, void *pack,\n> +\t\t\t     bool deleteMethod)\n> +\t: Message(Message::InvokeMessage), method_(method), pack_(pack),\n> +\t  deleteMethod_(deleteMethod)\n> +{\n> +}\n> +\n> +InvokeMessage::~InvokeMessage()\n> +{\n> +\tif (deleteMethod_)\n> +\t\tdelete method_;\n> +}\n> +\n> +/**\n> + * \\brief Invoke the method bound to InvokeMessage::method_ with arguments\n> + * InvokeMessage::pack_\n> + */\n> +void InvokeMessage::invoke()\n> +{\n> +\tmethod_->invokePack(pack_);\n> +}\n>  \n>  /**\n> - * \\var SignalMessage::method_\n> - * \\brief The slot that the signal targets\n> + * \\var InvokeMessage::method_\n> + * \\brief The method to be invoked\n>   */\n>  \n>  /**\n> - * \\var SignalMessage::pack_\n> - * \\brief The signal arguments\n> + * \\var InvokeMessage::pack_\n> + * \\brief The packed method invocation arguments\n>   */\n>  \n>  }; /* namespace libcamera */\n> diff --git a/src/libcamera/object.cpp b/src/libcamera/object.cpp\n> index 0adbc203add8..7d70ce21b5d0 100644\n> --- a/src/libcamera/object.cpp\n> +++ b/src/libcamera/object.cpp\n> @@ -12,6 +12,7 @@\n>  #include \"log.h\"\n>  #include \"message.h\"\n>  #include \"thread.h\"\n> +#include \"utils.h\"\n>  \n>  /**\n>   * \\file object.h\n> @@ -88,9 +89,9 @@ void Object::postMessage(std::unique_ptr<Message> msg)\n>  void Object::message(Message *msg)\n>  {\n>  \tswitch (msg->type()) {\n> -\tcase Message::SignalMessage: {\n> -\t\tSignalMessage *smsg = static_cast<SignalMessage *>(msg);\n> -\t\tsmsg->method_->invokePack(smsg->pack_);\n> +\tcase Message::InvokeMessage: {\n> +\t\tInvokeMessage *iMsg = static_cast<InvokeMessage *>(msg);\n> +\t\tiMsg->invoke();\n>  \t\tbreak;\n>  \t}\n>  \n> @@ -99,6 +100,28 @@ void Object::message(Message *msg)\n>  \t}\n>  }\n>  \n> +/**\n> + * \\fn void Object::invokeMethod(void (T::*func)(Args...), Args... args)\n> + * \\brief Invoke a method asynchronously on an Object instance\n> + * \\param[in] func The object method to invoke\n> + * \\param[in] args The method arguments\n> + *\n> + * This method invokes the member method \\a func when control returns to the\n> + * event loop of the object's thread. The method is executed in the object's\n> + * thread with arguments \\a args.\n> + *\n> + * Arguments \\a args passed by value or reference are copied, while pointers\n> + * are passed untouched. The caller shall ensure that any pointer argument\n> + * remains valid until the method is invoked.\n> + */\n> +\n> +void Object::invokeMethod(BoundMethodBase *method, void *args)\n> +{\n> +\tstd::unique_ptr<Message> msg =\n> +\t\tutils::make_unique<InvokeMessage>(method, args, true);\n> +\tpostMessage(std::move(msg));\n> +}\n> +\n>  /**\n>   * \\fn Object::thread()\n>   * \\brief Retrieve the thread the object is bound to\n> -- \n> Regards,\n> \n> Laurent Pinchart\n> \n> _______________________________________________\n> libcamera-devel mailing list\n> libcamera-devel@lists.libcamera.org\n> https://lists.libcamera.org/listinfo/libcamera-devel","headers":{"Return-Path":"<niklas.soderlund@ragnatech.se>","Received":["from mail-ed1-x541.google.com (mail-ed1-x541.google.com\n\t[IPv6:2a00:1450:4864:20::541])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id AF629600F9\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tSat, 17 Aug 2019 16:33:10 +0200 (CEST)","by mail-ed1-x541.google.com with SMTP id s49so7536440edb.1\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tSat, 17 Aug 2019 07:33:10 -0700 (PDT)","from localhost ([185.224.57.161]) by smtp.gmail.com with ESMTPSA id\n\tp5sm1669803edr.72.2019.08.17.07.33.08\n\t(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n\tSat, 17 Aug 2019 07:33:09 -0700 (PDT)"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=ragnatech-se.20150623.gappssmtp.com; s=20150623;\n\th=date:from:to:cc:subject:message-id:references:mime-version\n\t:content-disposition:content-transfer-encoding:in-reply-to\n\t:user-agent; bh=1G1mhDkSllxWCiGsMQJXWohngPt11h+G+ruTb7DSsEE=;\n\tb=h2+9D9Oib8rdmQN4OnI6DGWdz5FsduyNecANAkJs/AtxIrDsx1jDtuGeC3lNt6a4GM\n\tIxf2Vu2gPgTIgG3aSCLFIUpP9I992jw79hqVDblosIbgpJdeOUI8HtWHNvtw7bOEvmOn\n\tIqW61n+lgljRwhoz49FKlKBZwtkERQlpmN5a8VmFOt9DReHCep5maPCi/lrkXoQyd/i1\n\tAFs7jZkuNjJl9QMnhNMZaSmECFjREazbz5omxiHoDd5bY6v0i1RAOIkLKBtgVpy4qtXI\n\tgdLFpVuLEohPAOlHvXZwbGk20JRIBeUsBxk7UMsBZGmbemLWGi0O7MTwyUsA9G7tnXCH\n\t86tQ==","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20161025;\n\th=x-gm-message-state:date:from:to:cc:subject:message-id:references\n\t:mime-version:content-disposition:content-transfer-encoding\n\t:in-reply-to:user-agent;\n\tbh=1G1mhDkSllxWCiGsMQJXWohngPt11h+G+ruTb7DSsEE=;\n\tb=aZWeiaiUJPAE1MrIfY0UXN96R+LVHO0A2pa1vBp766KBvPQsKBamF8gqcVZMvpaiou\n\taUWvA3ON/wqR5BEFQoFGF2a1KW57wGrP6+w5yHtTyPK6N75EjdQMYM9EM5UmcvxaLTQc\n\tg6RELO1oHQHoCCOlo10ucMg/rZfOvymjCKmehfvzHuwkyhwZ7TQQ/KvQ7cM9mVL9hGqP\n\tVxSiB86eHef0E5cgcE6aUSKj0gcGRRyZtE0EHqKaWclXVsAfu6k8/mOppIvf9ayqBJZ8\n\tVmNUvbfUfhRMGN1nJBtxhhMLOMAvF6Fvkq2Ngfj7OQwQ/+CEber2X/DYrJfRtdKzFxQ/\n\t2g7Q==","X-Gm-Message-State":"APjAAAVORahYgTnnnQuWPRrv10Gd3k9R5/BNZZve0kFSDiayfRo8uqnR\n\tSlu7SQSEdpqI+Z3Toiw14JJjbnPGWis=","X-Google-Smtp-Source":"APXvYqxMBQOlMdi+xIHmnzSdJdo5dAC+oHJFDo1H4JicSQuotwa0jDaNP+KKawhfTv1nhz/LATurAg==","X-Received":"by 2002:a17:906:759:: with SMTP id\n\tz25mr13619733ejb.72.1566052390252; \n\tSat, 17 Aug 2019 07:33:10 -0700 (PDT)","Date":"Sat, 17 Aug 2019 16:33:07 +0200","From":"Niklas =?iso-8859-1?q?S=F6derlund?= <niklas.soderlund@ragnatech.se>","To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org","Message-ID":"<20190817143307.GJ16603@wyvern>","References":"<20190812124642.24287-1-laurent.pinchart@ideasonboard.com>\n\t<20190812124642.24287-7-laurent.pinchart@ideasonboard.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=iso-8859-1","Content-Disposition":"inline","Content-Transfer-Encoding":"8bit","In-Reply-To":"<20190812124642.24287-7-laurent.pinchart@ideasonboard.com>","User-Agent":"Mutt/1.12.1 (2019-06-15)","Subject":"Re: [libcamera-devel] [PATCH 06/18] libcamera: object: Add an\n\tasynchronous method invocation method","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.23","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","X-List-Received-Date":"Sat, 17 Aug 2019 14:33:10 -0000"}},{"id":2446,"web_url":"https://patchwork.libcamera.org/comment/2446/","msgid":"<20190817151843.GV16603@wyvern>","date":"2019-08-17T15:18:43","subject":"Re: [libcamera-devel] [PATCH 06/18] libcamera: object: Add an\n\tasynchronous method invocation method","submitter":{"id":5,"url":"https://patchwork.libcamera.org/api/people/5/","name":"Niklas Söderlund","email":"niklas.soderlund@ragnatech.se"},"content":"Hi Laurent,\n\nOn 2019-08-17 16:33:10 +0200, Niklas Söderlund wrote:\n> Hi Laurent,\n> \n> Thanks for your work.\n> \n> On 2019-08-12 15:46:30 +0300, Laurent Pinchart wrote:\n> > Add a helper invokeMethod() to the Object class that allows asynchrnous\n> > invocation of any method of an Object instance. Asynchronous invocation\n> > occurs when control returns to the event dispatcher of the target\n> > object's thread, in the context of that thread.\n> > \n> > To support this, generalise the SignalMessage implementation to support\n> > automatic deletion of the associated BoundMethod, and rename the message\n> > to InvokeMessage to reflect the more generic purpose.\n> > \n> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> \n> I think this patch looks OK but there seems to be some code that should \n> be moved here from a later patch and I would like to review the final \n> result before I add my tag. This is tricky enough as it is then copy \n> pasting code in local meat memory ;-)\n\nAs clarified on IRC, no change is expected in this patch,\n\nReviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>\n\n> \n> > ---\n> >  include/libcamera/object.h      | 12 +++++++++\n> >  src/libcamera/bound_method.cpp  |  2 +-\n> >  src/libcamera/include/message.h | 17 +++++++-----\n> >  src/libcamera/message.cpp       | 48 ++++++++++++++++++++++++---------\n> >  src/libcamera/object.cpp        | 29 +++++++++++++++++---\n> >  5 files changed, 86 insertions(+), 22 deletions(-)\n> > \n> > diff --git a/include/libcamera/object.h b/include/libcamera/object.h\n> > index e3b39cf547b0..869200a57d8c 100644\n> > --- a/include/libcamera/object.h\n> > +++ b/include/libcamera/object.h\n> > @@ -28,6 +28,16 @@ public:\n> >  \n> >  \tvoid postMessage(std::unique_ptr<Message> msg);\n> >  \n> > +\ttemplate<typename T, typename... Args, typename std::enable_if<std::is_base_of<Object, T>::value>::type * = nullptr>\n> > +\tvoid invokeMethod(void (T::*func)(Args...), Args... args)\n> > +\t{\n> > +\t\tT *obj = static_cast<T *>(this);\n> > +\t\tBoundMethodBase *method = new BoundMemberMethod<T, Args...>(obj, this, func);\n> > +\t\tvoid *pack = new typename BoundMemberMethod<T, Args...>::PackType{ args... };\n> > +\n> > +\t\tinvokeMethod(method, pack);\n> > +\t}\n> > +\n> >  \tThread *thread() const { return thread_; }\n> >  \tvoid moveToThread(Thread *thread);\n> >  \n> > @@ -40,6 +50,8 @@ private:\n> >  \tfriend class BoundMethodBase;\n> >  \tfriend class Thread;\n> >  \n> > +\tvoid invokeMethod(BoundMethodBase *method, void *pack);\n> > +\n> >  \tvoid connect(SignalBase *signal);\n> >  \tvoid disconnect(SignalBase *signal);\n> >  \n> > diff --git a/src/libcamera/bound_method.cpp b/src/libcamera/bound_method.cpp\n> > index 23b8f4122283..d89f84c03f4d 100644\n> > --- a/src/libcamera/bound_method.cpp\n> > +++ b/src/libcamera/bound_method.cpp\n> > @@ -19,7 +19,7 @@ void BoundMethodBase::activatePack(void *pack)\n> >  \t\tinvokePack(pack);\n> >  \t} else {\n> >  \t\tstd::unique_ptr<Message> msg =\n> > -\t\t\tutils::make_unique<SignalMessage>(this, pack);\n> > +\t\t\tutils::make_unique<InvokeMessage>(this, pack);\n> >  \t\tobject_->postMessage(std::move(msg));\n> >  \t}\n> >  }\n> > diff --git a/src/libcamera/include/message.h b/src/libcamera/include/message.h\n> > index b4670c0eab76..92717e316cc3 100644\n> > --- a/src/libcamera/include/message.h\n> > +++ b/src/libcamera/include/message.h\n> > @@ -9,6 +9,8 @@\n> >  \n> >  #include <atomic>\n> >  \n> > +#include <libcamera/bound_method.h>\n> > +\n> >  namespace libcamera {\n> >  \n> >  class BoundMethodBase;\n> > @@ -20,7 +22,7 @@ class Message\n> >  public:\n> >  \tenum Type {\n> >  \t\tNone = 0,\n> > -\t\tSignalMessage = 1,\n> > +\t\tInvokeMessage = 1,\n> >  \t\tUserMessage = 1000,\n> >  \t};\n> >  \n> > @@ -41,16 +43,19 @@ private:\n> >  \tstatic std::atomic_uint nextUserType_;\n> >  };\n> >  \n> > -class SignalMessage : public Message\n> > +class InvokeMessage : public Message\n> >  {\n> >  public:\n> > -\tSignalMessage(BoundMethodBase *method, void *pack)\n> > -\t\t: Message(Message::SignalMessage), method_(method), pack_(pack)\n> > -\t{\n> > -\t}\n> > +\tInvokeMessage(BoundMethodBase *method, void *pack,\n> > +\t\t      bool deleteMethod = false);\n> > +\t~InvokeMessage();\n> >  \n> > +\tvoid invoke();\n> > +\n> > +private:\n> >  \tBoundMethodBase *method_;\n> >  \tvoid *pack_;\n> > +\tbool deleteMethod_;\n> >  };\n> >  \n> >  } /* namespace libcamera */\n> > diff --git a/src/libcamera/message.cpp b/src/libcamera/message.cpp\n> > index 8d3376d8a533..f6c39d40fc73 100644\n> > --- a/src/libcamera/message.cpp\n> > +++ b/src/libcamera/message.cpp\n> > @@ -7,6 +7,8 @@\n> >  \n> >  #include \"message.h\"\n> >  \n> > +#include <libcamera/signal.h>\n> > +\n> >  #include \"log.h\"\n> >  \n> >  /**\n> > @@ -43,8 +45,8 @@ std::atomic_uint Message::nextUserType_{ Message::UserMessage };\n> >   * \\brief The message type\n> >   * \\var Message::None\n> >   * \\brief Invalid message type\n> > - * \\var Message::SignalMessage\n> > - * \\brief Asynchronous signal delivery across threads\n> > + * \\var Message::InvokeMessage\n> > + * \\brief Asynchronous method invocation across threads\n> >   * \\var Message::UserMessage\n> >   * \\brief First value available for user-defined messages\n> >   */\n> > @@ -107,25 +109,47 @@ Message::Type Message::registerMessageType()\n> >  }\n> >  \n> >  /**\n> > - * \\class SignalMessage\n> > - * \\brief A message carrying a Signal across threads\n> > + * \\class InvokeMessage\n> > + * \\brief A message carrying a method invocation across threads\n> >   */\n> >  \n> >  /**\n> > - * \\fn SignalMessage::SignalMessage()\n> > - * \\brief Construct a SignalMessage\n> > - * \\param[in] method The slot that the signal targets\n> > - * \\param[in] pack The signal arguments\n> > + * \\brief Construct an InvokeMessage for method invocation on an Object\n> > + * \\param[in] method The bound method\n> > + * \\param[in] pack The packed method arguments\n> > + * \\param[in] deleteMethod True to delete the \\a method when the message is\n> > + * destroyed\n> >   */\n> > +InvokeMessage::InvokeMessage(BoundMethodBase *method, void *pack,\n> > +\t\t\t     bool deleteMethod)\n> > +\t: Message(Message::InvokeMessage), method_(method), pack_(pack),\n> > +\t  deleteMethod_(deleteMethod)\n> > +{\n> > +}\n> > +\n> > +InvokeMessage::~InvokeMessage()\n> > +{\n> > +\tif (deleteMethod_)\n> > +\t\tdelete method_;\n> > +}\n> > +\n> > +/**\n> > + * \\brief Invoke the method bound to InvokeMessage::method_ with arguments\n> > + * InvokeMessage::pack_\n> > + */\n> > +void InvokeMessage::invoke()\n> > +{\n> > +\tmethod_->invokePack(pack_);\n> > +}\n> >  \n> >  /**\n> > - * \\var SignalMessage::method_\n> > - * \\brief The slot that the signal targets\n> > + * \\var InvokeMessage::method_\n> > + * \\brief The method to be invoked\n> >   */\n> >  \n> >  /**\n> > - * \\var SignalMessage::pack_\n> > - * \\brief The signal arguments\n> > + * \\var InvokeMessage::pack_\n> > + * \\brief The packed method invocation arguments\n> >   */\n> >  \n> >  }; /* namespace libcamera */\n> > diff --git a/src/libcamera/object.cpp b/src/libcamera/object.cpp\n> > index 0adbc203add8..7d70ce21b5d0 100644\n> > --- a/src/libcamera/object.cpp\n> > +++ b/src/libcamera/object.cpp\n> > @@ -12,6 +12,7 @@\n> >  #include \"log.h\"\n> >  #include \"message.h\"\n> >  #include \"thread.h\"\n> > +#include \"utils.h\"\n> >  \n> >  /**\n> >   * \\file object.h\n> > @@ -88,9 +89,9 @@ void Object::postMessage(std::unique_ptr<Message> msg)\n> >  void Object::message(Message *msg)\n> >  {\n> >  \tswitch (msg->type()) {\n> > -\tcase Message::SignalMessage: {\n> > -\t\tSignalMessage *smsg = static_cast<SignalMessage *>(msg);\n> > -\t\tsmsg->method_->invokePack(smsg->pack_);\n> > +\tcase Message::InvokeMessage: {\n> > +\t\tInvokeMessage *iMsg = static_cast<InvokeMessage *>(msg);\n> > +\t\tiMsg->invoke();\n> >  \t\tbreak;\n> >  \t}\n> >  \n> > @@ -99,6 +100,28 @@ void Object::message(Message *msg)\n> >  \t}\n> >  }\n> >  \n> > +/**\n> > + * \\fn void Object::invokeMethod(void (T::*func)(Args...), Args... args)\n> > + * \\brief Invoke a method asynchronously on an Object instance\n> > + * \\param[in] func The object method to invoke\n> > + * \\param[in] args The method arguments\n> > + *\n> > + * This method invokes the member method \\a func when control returns to the\n> > + * event loop of the object's thread. The method is executed in the object's\n> > + * thread with arguments \\a args.\n> > + *\n> > + * Arguments \\a args passed by value or reference are copied, while pointers\n> > + * are passed untouched. The caller shall ensure that any pointer argument\n> > + * remains valid until the method is invoked.\n> > + */\n> > +\n> > +void Object::invokeMethod(BoundMethodBase *method, void *args)\n> > +{\n> > +\tstd::unique_ptr<Message> msg =\n> > +\t\tutils::make_unique<InvokeMessage>(method, args, true);\n> > +\tpostMessage(std::move(msg));\n> > +}\n> > +\n> >  /**\n> >   * \\fn Object::thread()\n> >   * \\brief Retrieve the thread the object is bound to\n> > -- \n> > Regards,\n> > \n> > Laurent Pinchart\n> > \n> > _______________________________________________\n> > libcamera-devel mailing list\n> > libcamera-devel@lists.libcamera.org\n> > https://lists.libcamera.org/listinfo/libcamera-devel\n> \n> -- \n> Regards,\n> Niklas Söderlund","headers":{"Return-Path":"<niklas.soderlund@ragnatech.se>","Received":["from mail-ed1-x543.google.com (mail-ed1-x543.google.com\n\t[IPv6:2a00:1450:4864:20::543])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 34AB7600F9\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tSat, 17 Aug 2019 17:18:48 +0200 (CEST)","by mail-ed1-x543.google.com with SMTP id p28so7560837edi.3\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tSat, 17 Aug 2019 08:18:48 -0700 (PDT)","from localhost ([185.224.57.161]) by smtp.gmail.com with ESMTPSA id\n\tp20sm1252639eja.59.2019.08.17.08.18.47\n\t(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n\tSat, 17 Aug 2019 08:18:47 -0700 (PDT)"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=ragnatech-se.20150623.gappssmtp.com; s=20150623;\n\th=date:from:to:cc:subject:message-id:references:mime-version\n\t:content-disposition:content-transfer-encoding:in-reply-to\n\t:user-agent; bh=LwEvn5mKll3amhOjgQa8wjT00KReB7PHmPld8coe344=;\n\tb=x6h2JMWBPcZzLNO1ZgN6094zaAVyQB0e3anYRqxOcvN7bn0iv1FgnsV42oTqqsMS4O\n\t1R6M3U52OJ5a6OwwH3xDp9rYiB0lfcbR5AZQr+JMxXmWw3DRx6YAdJYOn2Ax14mqd+Pu\n\tE7NXyQCLfn2J/iXUgWTfIaZM9gou+hcnLKXSF2htpegz5hPpURqDy5eI0TRArn4QjCBD\n\t05aLVw6hy4XbTlHrBmKLtEOfynSfvn1+VWdeS1w/9bGTt2dO/MMV8cqilxWOq2gsql1v\n\tn9ckMJLfyN8/e8I4Xri00saCGtGtaTrrJxoJNAkAkUfH1+dsHxwFxd0ir5p1DSScxkm8\n\tND+A==","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20161025;\n\th=x-gm-message-state:date:from:to:cc:subject:message-id:references\n\t:mime-version:content-disposition:content-transfer-encoding\n\t:in-reply-to:user-agent;\n\tbh=LwEvn5mKll3amhOjgQa8wjT00KReB7PHmPld8coe344=;\n\tb=R8iIzkXrQHeMexjaSGk+32SF3uaIuxewwXhe8molXHtEjcaNzXiBrtvvyK//MlpRzc\n\tcc+f1ro+DxuAw342AGK6layI0WC1r9EjygL3yumJl3z9NlyGRloLxOG+qpRb7uNk29Ed\n\tPKgTMhX8C5OQScuCYQ7QqtEQI0Gmiw99yn3+hDA2nEHsqZHKZzgQJCgBDqQJ8ut//q/e\n\tWqkwLPKQTk/xDBlSpQjctI1ZggWC1u6elmS42EjyHJ5lyfZh+V9M1jt//F7c+H9GXL3k\n\tAR8ciAkR3594UQX1bWi3wszHqHnk9QJzJgLG4JErakQ8TPijApHDzqYDdrmo0HKuDO12\n\tveSQ==","X-Gm-Message-State":"APjAAAVCKBrZWpVBCOsPiQYO757IizDLsaMX8DhAEFV/HhvFrNrT+JXy\n\tPrNCwAiIHptdasLt1W0o273BHdCjYAw=","X-Google-Smtp-Source":"APXvYqzEloroNZ90GdZomhjyJ8QSl8YRWpHvUe9uwmvcvT3A9kiu3op4C8+T4hZDtW6Rg1KEZ76Zew==","X-Received":"by 2002:a17:906:74da:: with SMTP id\n\tz26mr13865364ejl.283.1566055127833; \n\tSat, 17 Aug 2019 08:18:47 -0700 (PDT)","Date":"Sat, 17 Aug 2019 17:18:43 +0200","From":"Niklas =?iso-8859-1?q?S=F6derlund?= <niklas.soderlund@ragnatech.se>","To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org","Message-ID":"<20190817151843.GV16603@wyvern>","References":"<20190812124642.24287-1-laurent.pinchart@ideasonboard.com>\n\t<20190812124642.24287-7-laurent.pinchart@ideasonboard.com>\n\t<20190817143307.GJ16603@wyvern>","MIME-Version":"1.0","Content-Type":"text/plain; charset=iso-8859-1","Content-Disposition":"inline","Content-Transfer-Encoding":"8bit","In-Reply-To":"<20190817143307.GJ16603@wyvern>","User-Agent":"Mutt/1.12.1 (2019-06-15)","Subject":"Re: [libcamera-devel] [PATCH 06/18] libcamera: object: Add an\n\tasynchronous method invocation method","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.23","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","X-List-Received-Date":"Sat, 17 Aug 2019 15:18:48 -0000"}}]