[{"id":3365,"web_url":"https://patchwork.libcamera.org/comment/3365/","msgid":"<20200107191554.GJ533370@oden.dyn.berto.se>","date":"2020-01-07T19:15:54","subject":"Re: [libcamera-devel] [PATCH 08/14] libcamera: bound_method:\n\tSupport bindings to non-void methods","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 2020-01-04 07:09:41 +0200, Laurent Pinchart wrote:\n> The bound method implementation is restricted to binding to void methods\n> as return values are not supported. This complicates usage of bound\n> methods, as non-void methods used a slots or Object::invokeMethod()\n> targets need to be wrapped in a void method. Simplify this by supporting\n> arbitrary return types and ignoring the return value.\n> \n> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n\nReviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>\n\n> ---\n>  include/libcamera/bound_method.h | 28 ++++++++++++------------\n>  include/libcamera/object.h       |  6 +++---\n>  include/libcamera/signal.h       | 37 +++++++++++++++++---------------\n>  src/libcamera/signal.cpp         |  8 +++----\n>  4 files changed, 41 insertions(+), 38 deletions(-)\n> \n> diff --git a/include/libcamera/bound_method.h b/include/libcamera/bound_method.h\n> index d194cd4133bb..b50072ffc098 100644\n> --- a/include/libcamera/bound_method.h\n> +++ b/include/libcamera/bound_method.h\n> @@ -79,7 +79,7 @@ public:\n>  \tstd::tuple<typename std::remove_reference<Args>::type...> args_;\n>  };\n>  \n> -template<typename... Args>\n> +template<typename R, typename... Args>\n>  class BoundMethodArgs : public BoundMethodBase\n>  {\n>  public:\n> @@ -107,19 +107,19 @@ public:\n>  \tvirtual void invoke(Args... args) = 0;\n>  };\n>  \n> -template<typename T, typename... Args>\n> -class BoundMemberMethod : public BoundMethodArgs<Args...>\n> +template<typename T, typename R, typename... Args>\n> +class BoundMemberMethod : public BoundMethodArgs<R, Args...>\n>  {\n>  public:\n> -\tusing PackType = typename BoundMethodArgs<Args...>::PackType;\n> +\tusing PackType = typename BoundMethodArgs<R, Args...>::PackType;\n>  \n> -\tBoundMemberMethod(T *obj, Object *object, void (T::*func)(Args...),\n> +\tBoundMemberMethod(T *obj, Object *object, R (T::*func)(Args...),\n>  \t\t\t  ConnectionType type = ConnectionTypeAuto)\n> -\t\t: BoundMethodArgs<Args...>(obj, object, type), func_(func)\n> +\t\t: BoundMethodArgs<R, Args...>(obj, object, type), func_(func)\n>  \t{\n>  \t}\n>  \n> -\tbool match(void (T::*func)(Args...)) const { return func == func_; }\n> +\tbool match(R (T::*func)(Args...)) const { return func == func_; }\n>  \n>  \tvoid activate(Args... args, bool deleteMethod = false) override\n>  \t{\n> @@ -135,20 +135,20 @@ public:\n>  \t}\n>  \n>  private:\n> -\tvoid (T::*func_)(Args...);\n> +\tR (T::*func_)(Args...);\n>  };\n>  \n> -template<typename... Args>\n> -class BoundStaticMethod : public BoundMethodArgs<Args...>\n> +template<typename R, typename... Args>\n> +class BoundStaticMethod : public BoundMethodArgs<R, Args...>\n>  {\n>  public:\n> -\tBoundStaticMethod(void (*func)(Args...))\n> -\t\t: BoundMethodArgs<Args...>(nullptr, nullptr, ConnectionTypeAuto),\n> +\tBoundStaticMethod(R (*func)(Args...))\n> +\t\t: BoundMethodArgs<R, Args...>(nullptr, nullptr, ConnectionTypeAuto),\n>  \t\t  func_(func)\n>  \t{\n>  \t}\n>  \n> -\tbool match(void (*func)(Args...)) const { return func == func_; }\n> +\tbool match(R (*func)(Args...)) const { return func == func_; }\n>  \n>  \tvoid activate(Args... args, bool deleteMethod = false) override\n>  \t{\n> @@ -158,7 +158,7 @@ public:\n>  \tvoid invoke(Args...) override {}\n>  \n>  private:\n> -\tvoid (*func_)(Args...);\n> +\tR (*func_)(Args...);\n>  };\n>  \n>  } /* namespace libcamera */\n> diff --git a/include/libcamera/object.h b/include/libcamera/object.h\n> index c45165dec8ef..586c2cf6fc70 100644\n> --- a/include/libcamera/object.h\n> +++ b/include/libcamera/object.h\n> @@ -29,13 +29,13 @@ public:\n>  \n>  \tvoid postMessage(std::unique_ptr<Message> msg);\n>  \n> -\ttemplate<typename T, typename... FuncArgs, typename... Args,\n> +\ttemplate<typename T, typename R, typename... FuncArgs, typename... Args,\n>  \t\t typename std::enable_if<std::is_base_of<Object, T>::value>::type * = nullptr>\n> -\tvoid invokeMethod(void (T::*func)(FuncArgs...), ConnectionType type,\n> +\tvoid invokeMethod(R (T::*func)(FuncArgs...), ConnectionType type,\n>  \t\t\t  Args... args)\n>  \t{\n>  \t\tT *obj = static_cast<T *>(this);\n> -\t\tauto *method = new BoundMemberMethod<T, FuncArgs...>(obj, this, func, type);\n> +\t\tauto *method = new BoundMemberMethod<T, R, FuncArgs...>(obj, this, func, type);\n>  \t\tmethod->activate(args..., true);\n>  \t}\n>  \n> diff --git a/include/libcamera/signal.h b/include/libcamera/signal.h\n> index 57598335932c..7fbe5a2c528f 100644\n> --- a/include/libcamera/signal.h\n> +++ b/include/libcamera/signal.h\n> @@ -54,27 +54,28 @@ public:\n>  \t}\n>  \n>  #ifndef __DOXYGEN__\n> -\ttemplate<typename T, typename std::enable_if<std::is_base_of<Object, T>::value>::type * = nullptr>\n> -\tvoid connect(T *obj, void (T::*func)(Args...),\n> +\ttemplate<typename T, typename R, typename std::enable_if<std::is_base_of<Object, T>::value>::type * = nullptr>\n> +\tvoid connect(T *obj, R (T::*func)(Args...),\n>  \t\t     ConnectionType type = ConnectionTypeAuto)\n>  \t{\n>  \t\tObject *object = static_cast<Object *>(obj);\n>  \t\tobject->connect(this);\n> -\t\tslots_.push_back(new BoundMemberMethod<T, Args...>(obj, object, func, type));\n> +\t\tslots_.push_back(new BoundMemberMethod<T, void, Args...>(obj, object, func, type));\n>  \t}\n>  \n> -\ttemplate<typename T, typename std::enable_if<!std::is_base_of<Object, T>::value>::type * = nullptr>\n> +\ttemplate<typename T, typename R, typename std::enable_if<!std::is_base_of<Object, T>::value>::type * = nullptr>\n>  #else\n> -\ttemplate<typename T>\n> +\ttemplate<typename T, typename R>\n>  #endif\n> -\tvoid connect(T *obj, void (T::*func)(Args...))\n> +\tvoid connect(T *obj, R (T::*func)(Args...))\n>  \t{\n> -\t\tslots_.push_back(new BoundMemberMethod<T, Args...>(obj, nullptr, func));\n> +\t\tslots_.push_back(new BoundMemberMethod<T, R, Args...>(obj, nullptr, func));\n>  \t}\n>  \n> -\tvoid connect(void (*func)(Args...))\n> +\ttemplate<typename R>\n> +\tvoid connect(R (*func)(Args...))\n>  \t{\n> -\t\tslots_.push_back(new BoundStaticMethod<Args...>(func));\n> +\t\tslots_.push_back(new BoundStaticMethod<R, Args...>(func));\n>  \t}\n>  \n>  \tvoid disconnect()\n> @@ -90,11 +91,12 @@ public:\n>  \t\tSignalBase::disconnect(obj);\n>  \t}\n>  \n> -\ttemplate<typename T>\n> -\tvoid disconnect(T *obj, void (T::*func)(Args...))\n> +\ttemplate<typename T, typename R>\n> +\tvoid disconnect(T *obj, R (T::*func)(Args...))\n>  \t{\n>  \t\tfor (auto iter = slots_.begin(); iter != slots_.end(); ) {\n> -\t\t\tBoundMethodArgs<Args...> *slot = static_cast<BoundMethodArgs<Args...> *>(*iter);\n> +\t\t\tBoundMethodArgs<R, Args...> *slot =\n> +\t\t\t\tstatic_cast<BoundMethodArgs<R, Args...> *>(*iter);\n>  \t\t\t/*\n>  \t\t\t * If the object matches the slot, the slot is\n>  \t\t\t * guaranteed to be a member slot, so we can safely\n> @@ -102,7 +104,7 @@ public:\n>  \t\t\t * func.\n>  \t\t\t */\n>  \t\t\tif (slot->match(obj) &&\n> -\t\t\t    static_cast<BoundMemberMethod<T, Args...> *>(slot)->match(func)) {\n> +\t\t\t    static_cast<BoundMemberMethod<T, R, Args...> *>(slot)->match(func)) {\n>  \t\t\t\titer = slots_.erase(iter);\n>  \t\t\t\tdelete slot;\n>  \t\t\t} else {\n> @@ -111,12 +113,13 @@ public:\n>  \t\t}\n>  \t}\n>  \n> -\tvoid disconnect(void (*func)(Args...))\n> +\ttemplate<typename R>\n> +\tvoid disconnect(R (*func)(Args...))\n>  \t{\n>  \t\tfor (auto iter = slots_.begin(); iter != slots_.end(); ) {\n> -\t\t\tBoundMethodArgs<Args...> *slot = *iter;\n> +\t\t\tBoundMethodArgs<R, Args...> *slot = *iter;\n>  \t\t\tif (slot->match(nullptr) &&\n> -\t\t\t    static_cast<BoundStaticMethod<Args...> *>(slot)->match(func)) {\n> +\t\t\t    static_cast<BoundStaticMethod<R, Args...> *>(slot)->match(func)) {\n>  \t\t\t\titer = slots_.erase(iter);\n>  \t\t\t\tdelete slot;\n>  \t\t\t} else {\n> @@ -133,7 +136,7 @@ public:\n>  \t\t */\n>  \t\tstd::vector<BoundMethodBase *> slots{ slots_.begin(), slots_.end() };\n>  \t\tfor (BoundMethodBase *slot : slots)\n> -\t\t\tstatic_cast<BoundMethodArgs<Args...> *>(slot)->activate(args...);\n> +\t\t\tstatic_cast<BoundMethodArgs<void, Args...> *>(slot)->activate(args...);\n>  \t}\n>  };\n>  \n> diff --git a/src/libcamera/signal.cpp b/src/libcamera/signal.cpp\n> index 6ee348acc8d4..190033317c72 100644\n> --- a/src/libcamera/signal.cpp\n> +++ b/src/libcamera/signal.cpp\n> @@ -54,7 +54,7 @@ namespace libcamera {\n>   */\n>  \n>  /**\n> - * \\fn Signal::connect(T *object, void(T::*func)(Args...))\n> + * \\fn Signal::connect(T *object, R (T::*func)(Args...))\n>   * \\brief Connect the signal to a member function slot\n>   * \\param[in] object The slot object pointer\n>   * \\param[in] func The slot member function\n> @@ -66,7 +66,7 @@ namespace libcamera {\n>   */\n>  \n>  /**\n> - * \\fn Signal::connect(void(*func)(Args...))\n> + * \\fn Signal::connect(R (*func)(Args...))\n>   * \\brief Connect the signal to a static function slot\n>   * \\param[in] func The slot static function\n>   */\n> @@ -83,14 +83,14 @@ namespace libcamera {\n>   */\n>  \n>  /**\n> - * \\fn Signal::disconnect(T *object, void(T::*func)(Args...))\n> + * \\fn Signal::disconnect(T *object, R (T::*func)(Args...))\n>   * \\brief Disconnect the signal from the \\a object slot member function \\a func\n>   * \\param[in] object The object pointer whose slots to disconnect\n>   * \\param[in] func The slot member function to disconnect\n>   */\n>  \n>  /**\n> - * \\fn Signal::disconnect(void(*func)(Args...))\n> + * \\fn Signal::disconnect(R (*func)(Args...))\n>   * \\brief Disconnect the signal from the slot static function \\a func\n>   * \\param[in] func The slot static function to disconnect\n>   */\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-lj1-x243.google.com (mail-lj1-x243.google.com\n\t[IPv6:2a00:1450:4864:20::243])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 7E8506063B\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue,  7 Jan 2020 20:15:56 +0100 (CET)","by mail-lj1-x243.google.com with SMTP id z22so761396ljg.1\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue, 07 Jan 2020 11:15:56 -0800 (PST)","from localhost (h-93-159.A463.priv.bahnhof.se. [46.59.93.159])\n\tby smtp.gmail.com with ESMTPSA id\n\ts22sm227436ljm.41.2020.01.07.11.15.54\n\t(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n\tTue, 07 Jan 2020 11:15:55 -0800 (PST)"],"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\tbh=jhhSqFCkHRtQh8UqrrQ3MF3TfL0q1DlxSGSSMORVGBg=;\n\tb=JtqG/uZxqFc5p1ee0X8GOV6jJQEOU2cL+8THAeJBLxkHkbxQ6a7pzIwolX6bDiNWXX\n\tRZzVMiSqQRgdiEWQNGGkvbLcU+xCLbK7S1xtofV2Op9AX+SDAk60u2ziSBgA619+Yi9T\n\tNV5mHjMBzwJLzvTddZMtk6hvP/4vcyIlDweSjuVrl4Nh9BnphjQcsln2KcRd9T5LGeig\n\t7vCwkGDekIvh+eV3RRnTP7eRCjD9r0OLZX43bv0ibbJ7wTUXIyFw8JBrjLByxi4Fv3qq\n\tciEk7Udme47uacKtM99b+YYtWkdD4nhrPLe29GXJl4v/PQPbExeCocJmbtjgy5u0fnsp\n\tqAAQ==","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;\n\tbh=jhhSqFCkHRtQh8UqrrQ3MF3TfL0q1DlxSGSSMORVGBg=;\n\tb=m1DqyeZhU2DTYhQUK42lMsy2PIMktnwqBFSrL8vnSPTLup87y0GA+Bh3coNhHOPNh5\n\tyAmvHkj3rYNpLyc8yq7dBfevTkKkAgZQxP+L/r47HYfYvdevxa7p1YPOaG2oLZ2LVfzX\n\txHSBIEbxt56/BJnzl0oGIKfXvgrCZqDRt6Jpnq1wne0MEHv9RMGdSDQhu+jkXTEBWbCQ\n\tuXh9w5ezp73TFL1lNPcTWgoKo5vzfuojyed/IJiYGgGqtGduCJuqjD6lfUAmOtzK9KAt\n\t95wQGvR1ospzWR0Z9KZMYJyExtdJUZwC/4nAjCB8MgkXe7p0Us7+POzHxgbMgRfvVOos\n\tiRaw==","X-Gm-Message-State":"APjAAAV5v2O82gaMyYYTJblVdIe3jYl/6DuPG9a7QyuQJxI0fdRlpbUE\n\tJ9tG1nD1w0Bo6HHUaMXlMVxfOyPWBUKIXg==","X-Google-Smtp-Source":"APXvYqyF0/S43LLqRKQR5vSHda5a7FFP6TYweBPr/z64eHcJEoVXGWAxMoTRAJ5LrYgg6lqW2QbzYw==","X-Received":"by 2002:a05:651c:204f:: with SMTP id\n\tt15mr602280ljo.240.1578424555787; \n\tTue, 07 Jan 2020 11:15:55 -0800 (PST)","Date":"Tue, 7 Jan 2020 20:15:54 +0100","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":"<20200107191554.GJ533370@oden.dyn.berto.se>","References":"<20200104050947.7673-1-laurent.pinchart@ideasonboard.com>\n\t<20200104050947.7673-9-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":"<20200104050947.7673-9-laurent.pinchart@ideasonboard.com>","Subject":"Re: [libcamera-devel] [PATCH 08/14] libcamera: bound_method:\n\tSupport bindings to non-void methods","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","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":"Tue, 07 Jan 2020 19:15:56 -0000"}}]