From patchwork Sat Jan 4 05:09:34 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 2497 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 4C3B560466 for ; Sat, 4 Jan 2020 06:10:03 +0100 (CET) Received: from pendragon.bb.dnainternet.fi (81-175-216-236.bb.dnainternet.fi [81.175.216.236]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id E005EA49 for ; Sat, 4 Jan 2020 06:10:02 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1578114603; bh=XDmoyez+9Q+gmb7aXgFlcw9C5/2YsoVpKGpYI1Y08Y0=; h=From:To:Subject:Date:In-Reply-To:References:From; b=nXXx/sKlVXfWAUYIA7AuCm3JUjGomr8+u8AUVShEYcE+X1wjgTjAa/s6KBk4Hqoti BlTB4jdXI5l2ZZKA+AKFiYS9kCNGl0CmaYOhMbfMuiIdxFqtxJfZlnDQ6Af49VyUqb r/5CCNbuNznlEKzTYLtHxLCihHAOyIRvtmBtSruc= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Sat, 4 Jan 2020 07:09:34 +0200 Message-Id: <20200104050947.7673-2-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.24.1 In-Reply-To: <20200104050947.7673-1-laurent.pinchart@ideasonboard.com> References: <20200104050947.7673-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 01/14] test: object-invoke: Test direct invocation X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 04 Jan 2020 05:10:03 -0000 Test the ConnectionTypeDirect type when the object lives in a different thread. This test passes but generates a memory leak. Signed-off-by: Laurent Pinchart Reviewed-by: Niklas Söderlund --- test/object-invoke.cpp | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/test/object-invoke.cpp b/test/object-invoke.cpp index f9a8bea9dce2..ed16de99ef5e 100644 --- a/test/object-invoke.cpp +++ b/test/object-invoke.cpp @@ -123,6 +123,27 @@ protected: return TestFail; } + /* Test that direct method invocation bypasses threads. */ + object_.reset(); + object_.invokeMethod(&InvokedObject::method, + ConnectionTypeDirect, 42); + + switch (object_.status()) { + case InvokedObject::NoCall: + cout << "Method not invoked for custom thread" << endl; + return TestFail; + case InvokedObject::CallReceived: + cout << "Method invoked in incorrect thread for direct call" << endl; + return TestFail; + default: + break; + } + + if (object_.value() != 42) { + cout << "Method invoked with incorrect value for direct call" << endl; + return TestFail; + } + /* * Test invoking a method that takes reference arguments. This * targets compilation, there's no need to check runtime From patchwork Sat Jan 4 05:09:35 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 2498 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 9482B60466 for ; Sat, 4 Jan 2020 06:10:03 +0100 (CET) Received: from pendragon.bb.dnainternet.fi (81-175-216-236.bb.dnainternet.fi [81.175.216.236]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 3A79F30F for ; Sat, 4 Jan 2020 06:10:03 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1578114603; bh=v6EUKuas02m+ruXKnuLeIxHV2wUXG5+a5yQQjjjkQDI=; h=From:To:Subject:Date:In-Reply-To:References:From; b=r3OMg6wxrLHvrTuAn2tYBG7j6DCHg5OJa6GPRB4xFXri6OwRUD8MVE2E/p6yFkryl u7G6rDY68HVhnmUgIO+JTsnsWkk2+vQO1ye435WPznvZzYUuTo0XXNl+c7L1ztlPww iGQ5+/eSVpK1oQXxhzDdbrpydQsHr8fRQ7visJ3c= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Sat, 4 Jan 2020 07:09:35 +0200 Message-Id: <20200104050947.7673-3-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.24.1 In-Reply-To: <20200104050947.7673-1-laurent.pinchart@ideasonboard.com> References: <20200104050947.7673-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 02/14] libcamera: object: Use activate() in invokeMethod() X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 04 Jan 2020 05:10:03 -0000 The Object::invokeMethod() implementation duplicates pack creation code from BoundMemberMethod::activate(). Call activate() instead of activatePack() to share code. Signed-off-by: Laurent Pinchart Reviewed-by: Niklas Söderlund --- include/libcamera/bound_method.h | 15 ++++++++++----- include/libcamera/object.h | 7 ++----- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/include/libcamera/bound_method.h b/include/libcamera/bound_method.h index b841a2aed147..5743cacf5388 100644 --- a/include/libcamera/bound_method.h +++ b/include/libcamera/bound_method.h @@ -37,10 +37,11 @@ public: Object *object() const { return object_; } ConnectionType connectionType() const { return connectionType_; } - void activatePack(void *pack, bool deleteMethod); virtual void invokePack(void *pack) = 0; protected: + void activatePack(void *pack, bool deleteMethod); + void *obj_; Object *object_; ConnectionType connectionType_; @@ -88,7 +89,7 @@ public: invokePack(pack, typename generator::type()); } - virtual void activate(Args... args) = 0; + virtual void activate(Args... args, bool deleteMethod = false) = 0; virtual void invoke(Args... args) = 0; }; @@ -106,10 +107,10 @@ public: bool match(void (T::*func)(Args...)) const { return func == func_; } - void activate(Args... args) + void activate(Args... args, bool deleteMethod = false) { if (this->object_) - BoundMethodBase::activatePack(new PackType{ args... }, false); + BoundMethodBase::activatePack(new PackType{ args... }, deleteMethod); else (static_cast(this->obj_)->*func_)(args...); } @@ -135,7 +136,11 @@ public: bool match(void (*func)(Args...)) const { return func == func_; } - void activate(Args... args) { (*func_)(args...); } + void activate(Args... args, bool deleteMethod = false) + { + (*func_)(args...); + } + void invoke(Args...) {} private: diff --git a/include/libcamera/object.h b/include/libcamera/object.h index 21b70460b516..c45165dec8ef 100644 --- a/include/libcamera/object.h +++ b/include/libcamera/object.h @@ -35,11 +35,8 @@ public: Args... args) { T *obj = static_cast(this); - BoundMethodBase *method = - new BoundMemberMethod(obj, this, func, type); - void *pack = new typename BoundMemberMethod::PackType{ args... }; - - method->activatePack(pack, true); + auto *method = new BoundMemberMethod(obj, this, func, type); + method->activate(args..., true); } Thread *thread() const { return thread_; } From patchwork Sat Jan 4 05:09:36 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 2499 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id EDED960466 for ; Sat, 4 Jan 2020 06:10:03 +0100 (CET) Received: from pendragon.bb.dnainternet.fi (81-175-216-236.bb.dnainternet.fi [81.175.216.236]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 8A906A49 for ; Sat, 4 Jan 2020 06:10:03 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1578114603; bh=iuKvvqBOOmGKweNTex1vbZX9NzTjfQrevg48E95VhDM=; h=From:To:Subject:Date:In-Reply-To:References:From; b=X7ghZHeXl6j+5w6TCeIJYu5QP08KfBcxT9uSGo2gAU9OFah6StJopQdon6XD16NZr CO7sJHiqy4k82mjpyEnjfp7orSHs4E0l0PAu3KOwbAuP9z/oCS/neDtpjLV7LPtcF/ 22/0jeN3YLJyLe+1d+PRvUFTLgNA2384tYEPhhk0= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Sat, 4 Jan 2020 07:09:36 +0200 Message-Id: <20200104050947.7673-4-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.24.1 In-Reply-To: <20200104050947.7673-1-laurent.pinchart@ideasonboard.com> References: <20200104050947.7673-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 03/14] libcamera: bound_method: Fix memory leak with direct connections X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 04 Jan 2020 05:10:04 -0000 When BoundMethodBase::activatePack() is called with the connection type set to ConnectionTypeDirect, the method isn't deleted even if deleteMethod is true, as is the case when called from Object::invokeMethod(). This causes a memory leak. Fix it. Signed-off-by: Laurent Pinchart Reviewed-by: Niklas Söderlund --- src/libcamera/bound_method.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libcamera/bound_method.cpp b/src/libcamera/bound_method.cpp index 4c0cd415a3f1..45c765774801 100644 --- a/src/libcamera/bound_method.cpp +++ b/src/libcamera/bound_method.cpp @@ -62,6 +62,8 @@ void BoundMethodBase::activatePack(void *pack, bool deleteMethod) case ConnectionTypeDirect: default: invokePack(pack); + if (deleteMethod) + delete this; break; case ConnectionTypeQueued: { From patchwork Sat Jan 4 05:09:37 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 2500 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 3CA3160466 for ; Sat, 4 Jan 2020 06:10:04 +0100 (CET) Received: from pendragon.bb.dnainternet.fi (81-175-216-236.bb.dnainternet.fi [81.175.216.236]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id D9AB830F for ; Sat, 4 Jan 2020 06:10:03 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1578114604; bh=Q31aLLJP61ph/JvgeiUo+dtOidufq2NNa6OwPbOIvOU=; h=From:To:Subject:Date:In-Reply-To:References:From; b=GYvSShe4/vC5KbxjgX7AlXVjpXMP2Qn8GgJMHFxE1lK8dli8Se7r1ti3xaaIgu7KI QJRyhOSJyCH0g15IOSKkCQ5Z0gC9NGU3tGEoechyRDqrMhd62ayaUxw+rHWK7gDV6s qGzpXYpqUKu/Jjo0tTsSUhynjpo7RV0KoNYtyllI= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Sat, 4 Jan 2020 07:09:37 +0200 Message-Id: <20200104050947.7673-5-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.24.1 In-Reply-To: <20200104050947.7673-1-laurent.pinchart@ideasonboard.com> References: <20200104050947.7673-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 04/14] libcamera: bound_method: Mark overriden methods with override X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 04 Jan 2020 05:10:04 -0000 Mark the activate() and invoke() methods with the override keyword where appropriate. Signed-off-by: Laurent Pinchart Reviewed-by: Niklas Söderlund --- include/libcamera/bound_method.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/libcamera/bound_method.h b/include/libcamera/bound_method.h index 5743cacf5388..f23b17c7dd98 100644 --- a/include/libcamera/bound_method.h +++ b/include/libcamera/bound_method.h @@ -107,7 +107,7 @@ public: bool match(void (T::*func)(Args...)) const { return func == func_; } - void activate(Args... args, bool deleteMethod = false) + void activate(Args... args, bool deleteMethod = false) override { if (this->object_) BoundMethodBase::activatePack(new PackType{ args... }, deleteMethod); @@ -115,7 +115,7 @@ public: (static_cast(this->obj_)->*func_)(args...); } - void invoke(Args... args) + void invoke(Args... args) override { (static_cast(this->obj_)->*func_)(args...); } @@ -136,12 +136,12 @@ public: bool match(void (*func)(Args...)) const { return func == func_; } - void activate(Args... args, bool deleteMethod = false) + void activate(Args... args, bool deleteMethod = false) override { (*func_)(args...); } - void invoke(Args...) {} + void invoke(Args...) override {} private: void (*func_)(Args...); From patchwork Sat Jan 4 05:09:38 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 2501 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 98C5060466 for ; Sat, 4 Jan 2020 06:10:04 +0100 (CET) Received: from pendragon.bb.dnainternet.fi (81-175-216-236.bb.dnainternet.fi [81.175.216.236]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 32245A49 for ; Sat, 4 Jan 2020 06:10:04 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1578114604; bh=x364z7FBmwdlMhCMITkp8M8WEN2FwwItMd5D6b6058w=; h=From:To:Subject:Date:In-Reply-To:References:From; b=ofraQdrCGnkX0gQAisRVgLyvHP76cGUe18VdH8jJq7My/ByE2HcdEZj3UVdzSgSgL TW2u8h0BGNUfo1xIIPUzfWjtKy02eM3+Fqmrc4ULOj0L66O7YWrRiw9D0SkGJm+B3K w9J13ABFTSaB2PMhipYBVHpQLAJ4RX0fhi5EXw9M= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Sat, 4 Jan 2020 07:09:38 +0200 Message-Id: <20200104050947.7673-6-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.24.1 In-Reply-To: <20200104050947.7673-1-laurent.pinchart@ideasonboard.com> References: <20200104050947.7673-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 05/14] libcamera: bound_method: Drop unused BoundMethodBase::connectionType() X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 04 Jan 2020 05:10:04 -0000 The BoundMethodBase::connectionType() method isn't used, drop it. While it at make the connectionType_ member private as it is only used by the class. Signed-off-by: Laurent Pinchart Reviewed-by: Niklas Söderlund --- include/libcamera/bound_method.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/libcamera/bound_method.h b/include/libcamera/bound_method.h index f23b17c7dd98..a1541212ff3d 100644 --- a/include/libcamera/bound_method.h +++ b/include/libcamera/bound_method.h @@ -35,7 +35,6 @@ public: bool match(Object *object) { return object == object_; } Object *object() const { return object_; } - ConnectionType connectionType() const { return connectionType_; } virtual void invokePack(void *pack) = 0; @@ -44,6 +43,8 @@ protected: void *obj_; Object *object_; + +private: ConnectionType connectionType_; }; From patchwork Sat Jan 4 05:09:39 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 2502 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id E6BDE60466 for ; Sat, 4 Jan 2020 06:10:04 +0100 (CET) Received: from pendragon.bb.dnainternet.fi (81-175-216-236.bb.dnainternet.fi [81.175.216.236]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 843C930F for ; Sat, 4 Jan 2020 06:10:04 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1578114604; bh=Gw7AjzkQmim4HYDBhzJyjHUFX8b21zk9VkxOsgqCxOc=; h=From:To:Subject:Date:In-Reply-To:References:From; b=fm7N/CvRMUVVbm0DChrzRRWMSxL973D84mwuUZGiShR5u+m6GtMx5UUm4sE/K3daQ sg72bVyA/R3ZJx6ViJ/GZ3PWifYf7qW1s7SL7m30PaUTo1BOHWTBuRRU8IRp5zo8/E E67pKSvOEKaJSiyRMv55GPfHgL3rx7mZpLBp6PbA= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Sat, 4 Jan 2020 07:09:39 +0200 Message-Id: <20200104050947.7673-7-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.24.1 In-Reply-To: <20200104050947.7673-1-laurent.pinchart@ideasonboard.com> References: <20200104050947.7673-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 06/14] libcamera: bound_method: Move sequence and generator to BoundMethodBase X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 04 Jan 2020 05:10:06 -0000 The sequence and generator member types of BoundMethodArgs are not dependent on the template arguments of BoundMethodArgs. To prepare for template specialization of BoundMethodArgs and avoid code duplication, move them to the BoundMethodBase class. Signed-off-by: Laurent Pinchart Reviewed-by: Niklas Söderlund --- include/libcamera/bound_method.h | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/include/libcamera/bound_method.h b/include/libcamera/bound_method.h index a1541212ff3d..9fd58c69a0e9 100644 --- a/include/libcamera/bound_method.h +++ b/include/libcamera/bound_method.h @@ -39,19 +39,6 @@ public: virtual void invokePack(void *pack) = 0; protected: - void activatePack(void *pack, bool deleteMethod); - - void *obj_; - Object *object_; - -private: - ConnectionType connectionType_; -}; - -template -class BoundMethodArgs : public BoundMethodBase -{ -private: #ifndef __DOXYGEN__ /* * This is a cheap partial implementation of std::integer_sequence<> @@ -71,10 +58,23 @@ private: }; #endif + void activatePack(void *pack, bool deleteMethod); + + void *obj_; + Object *object_; + +private: + ConnectionType connectionType_; +}; + +template +class BoundMethodArgs : public BoundMethodBase +{ +private: using PackType = std::tuple::type...>; template - void invokePack(void *pack, sequence) + void invokePack(void *pack, BoundMethodBase::sequence) { PackType *args = static_cast(pack); invoke(std::get(*args)...); @@ -87,7 +87,7 @@ public: void invokePack(void *pack) override { - invokePack(pack, typename generator::type()); + invokePack(pack, typename BoundMethodBase::generator::type()); } virtual void activate(Args... args, bool deleteMethod = false) = 0; From patchwork Sat Jan 4 05:09:40 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 2503 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 54ED060611 for ; Sat, 4 Jan 2020 06:10:05 +0100 (CET) Received: from pendragon.bb.dnainternet.fi (81-175-216-236.bb.dnainternet.fi [81.175.216.236]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id DD165A49 for ; Sat, 4 Jan 2020 06:10:04 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1578114605; bh=GvbqXLdTNKKtZYcODnXfBEUFpkLPY3uJAlu3ak0e4NU=; h=From:To:Subject:Date:In-Reply-To:References:From; b=SXfSVyY7I6VtCu20luHhuCrvoIkNDgUelmWMac2W2hvaZ78gsCp1++OG9XqsLaNSD HEgxjQaEUJDgDb3CvHl+5T38zVOp08XDLWXUo7UAebL+4zUQYjpAcpxdYKm+39txV8 mYSDuPtRTYrSnuBIzls2sl9R2vcJ6YLchcOUmfXw= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Sat, 4 Jan 2020 07:09:40 +0200 Message-Id: <20200104050947.7673-8-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.24.1 In-Reply-To: <20200104050947.7673-1-laurent.pinchart@ideasonboard.com> References: <20200104050947.7673-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 07/14] libcamera: bound_method: Store method arguments in a class X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 04 Jan 2020 05:10:06 -0000 Create a new BoundMethodPack class to replace the PackType type alias. This will allow adding additional fields to the arguments pack, when adding support for propagation of bound method return values. Signed-off-by: Laurent Pinchart Reviewed-by: Niklas Söderlund --- Documentation/Doxyfile.in | 1 + include/libcamera/bound_method.h | 21 +++++++++++++++++---- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/Documentation/Doxyfile.in b/Documentation/Doxyfile.in index 840c1b4c76c5..9e5efae33919 100644 --- a/Documentation/Doxyfile.in +++ b/Documentation/Doxyfile.in @@ -873,6 +873,7 @@ EXCLUDE_PATTERNS = EXCLUDE_SYMBOLS = libcamera::BoundMemberMethod \ libcamera::BoundMethodArgs \ libcamera::BoundMethodBase \ + libcamera::BoundMethodPack \ libcamera::BoundStaticMethod \ libcamera::SignalBase \ std::* diff --git a/include/libcamera/bound_method.h b/include/libcamera/bound_method.h index 9fd58c69a0e9..d194cd4133bb 100644 --- a/include/libcamera/bound_method.h +++ b/include/libcamera/bound_method.h @@ -67,17 +67,30 @@ private: ConnectionType connectionType_; }; +template +class BoundMethodPack +{ +public: + BoundMethodPack(const Args &... args) + : args_(args...) + { + } + + std::tuple::type...> args_; +}; + template class BoundMethodArgs : public BoundMethodBase { -private: - using PackType = std::tuple::type...>; +public: + using PackType = BoundMethodPack; +private: template void invokePack(void *pack, BoundMethodBase::sequence) { PackType *args = static_cast(pack); - invoke(std::get(*args)...); + invoke(std::get(args->args_)...); delete args; } @@ -98,7 +111,7 @@ template class BoundMemberMethod : public BoundMethodArgs { public: - using PackType = std::tuple::type...>; + using PackType = typename BoundMethodArgs::PackType; BoundMemberMethod(T *obj, Object *object, void (T::*func)(Args...), ConnectionType type = ConnectionTypeAuto) From patchwork Sat Jan 4 05:09:41 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 2504 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 9404060605 for ; Sat, 4 Jan 2020 06:10:05 +0100 (CET) Received: from pendragon.bb.dnainternet.fi (81-175-216-236.bb.dnainternet.fi [81.175.216.236]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 3982630F for ; Sat, 4 Jan 2020 06:10:05 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1578114605; bh=WsJUHEKFZpMwIW/SZ2KfP9yBOqYhlIcjE1nKxAa3TBk=; h=From:To:Subject:Date:In-Reply-To:References:From; b=jTjG/eMdnaLUaxTeSc5yqkH//C06u7qxafgF6fYKGDYTK6WteBLqSkCMUBRAPnIYU Ry/JlZsRHHTs0V0s1MO0WLDjT0ockfIqwIF//2VYvTrteJohYkve3p8pVGF8wBTKMD eWPZebzBuisuvICBdyo/GCEGMVJSxajBkd7aZUkU= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Sat, 4 Jan 2020 07:09:41 +0200 Message-Id: <20200104050947.7673-9-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.24.1 In-Reply-To: <20200104050947.7673-1-laurent.pinchart@ideasonboard.com> References: <20200104050947.7673-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 08/14] libcamera: bound_method: Support bindings to non-void methods X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 04 Jan 2020 05:10:07 -0000 The bound method implementation is restricted to binding to void methods as return values are not supported. This complicates usage of bound methods, as non-void methods used a slots or Object::invokeMethod() targets need to be wrapped in a void method. Simplify this by supporting arbitrary return types and ignoring the return value. Signed-off-by: Laurent Pinchart Reviewed-by: Niklas Söderlund --- include/libcamera/bound_method.h | 28 ++++++++++++------------ include/libcamera/object.h | 6 +++--- include/libcamera/signal.h | 37 +++++++++++++++++--------------- src/libcamera/signal.cpp | 8 +++---- 4 files changed, 41 insertions(+), 38 deletions(-) diff --git a/include/libcamera/bound_method.h b/include/libcamera/bound_method.h index d194cd4133bb..b50072ffc098 100644 --- a/include/libcamera/bound_method.h +++ b/include/libcamera/bound_method.h @@ -79,7 +79,7 @@ public: std::tuple::type...> args_; }; -template +template class BoundMethodArgs : public BoundMethodBase { public: @@ -107,19 +107,19 @@ public: virtual void invoke(Args... args) = 0; }; -template -class BoundMemberMethod : public BoundMethodArgs +template +class BoundMemberMethod : public BoundMethodArgs { public: - using PackType = typename BoundMethodArgs::PackType; + using PackType = typename BoundMethodArgs::PackType; - BoundMemberMethod(T *obj, Object *object, void (T::*func)(Args...), + BoundMemberMethod(T *obj, Object *object, R (T::*func)(Args...), ConnectionType type = ConnectionTypeAuto) - : BoundMethodArgs(obj, object, type), func_(func) + : BoundMethodArgs(obj, object, type), func_(func) { } - bool match(void (T::*func)(Args...)) const { return func == func_; } + bool match(R (T::*func)(Args...)) const { return func == func_; } void activate(Args... args, bool deleteMethod = false) override { @@ -135,20 +135,20 @@ public: } private: - void (T::*func_)(Args...); + R (T::*func_)(Args...); }; -template -class BoundStaticMethod : public BoundMethodArgs +template +class BoundStaticMethod : public BoundMethodArgs { public: - BoundStaticMethod(void (*func)(Args...)) - : BoundMethodArgs(nullptr, nullptr, ConnectionTypeAuto), + BoundStaticMethod(R (*func)(Args...)) + : BoundMethodArgs(nullptr, nullptr, ConnectionTypeAuto), func_(func) { } - bool match(void (*func)(Args...)) const { return func == func_; } + bool match(R (*func)(Args...)) const { return func == func_; } void activate(Args... args, bool deleteMethod = false) override { @@ -158,7 +158,7 @@ public: void invoke(Args...) override {} private: - void (*func_)(Args...); + R (*func_)(Args...); }; } /* namespace libcamera */ diff --git a/include/libcamera/object.h b/include/libcamera/object.h index c45165dec8ef..586c2cf6fc70 100644 --- a/include/libcamera/object.h +++ b/include/libcamera/object.h @@ -29,13 +29,13 @@ public: void postMessage(std::unique_ptr msg); - template::value>::type * = nullptr> - void invokeMethod(void (T::*func)(FuncArgs...), ConnectionType type, + void invokeMethod(R (T::*func)(FuncArgs...), ConnectionType type, Args... args) { T *obj = static_cast(this); - auto *method = new BoundMemberMethod(obj, this, func, type); + auto *method = new BoundMemberMethod(obj, this, func, type); method->activate(args..., true); } diff --git a/include/libcamera/signal.h b/include/libcamera/signal.h index 57598335932c..7fbe5a2c528f 100644 --- a/include/libcamera/signal.h +++ b/include/libcamera/signal.h @@ -54,27 +54,28 @@ public: } #ifndef __DOXYGEN__ - template::value>::type * = nullptr> - void connect(T *obj, void (T::*func)(Args...), + template::value>::type * = nullptr> + void connect(T *obj, R (T::*func)(Args...), ConnectionType type = ConnectionTypeAuto) { Object *object = static_cast(obj); object->connect(this); - slots_.push_back(new BoundMemberMethod(obj, object, func, type)); + slots_.push_back(new BoundMemberMethod(obj, object, func, type)); } - template::value>::type * = nullptr> + template::value>::type * = nullptr> #else - template + template #endif - void connect(T *obj, void (T::*func)(Args...)) + void connect(T *obj, R (T::*func)(Args...)) { - slots_.push_back(new BoundMemberMethod(obj, nullptr, func)); + slots_.push_back(new BoundMemberMethod(obj, nullptr, func)); } - void connect(void (*func)(Args...)) + template + void connect(R (*func)(Args...)) { - slots_.push_back(new BoundStaticMethod(func)); + slots_.push_back(new BoundStaticMethod(func)); } void disconnect() @@ -90,11 +91,12 @@ public: SignalBase::disconnect(obj); } - template - void disconnect(T *obj, void (T::*func)(Args...)) + template + void disconnect(T *obj, R (T::*func)(Args...)) { for (auto iter = slots_.begin(); iter != slots_.end(); ) { - BoundMethodArgs *slot = static_cast *>(*iter); + BoundMethodArgs *slot = + static_cast *>(*iter); /* * If the object matches the slot, the slot is * guaranteed to be a member slot, so we can safely @@ -102,7 +104,7 @@ public: * func. */ if (slot->match(obj) && - static_cast *>(slot)->match(func)) { + static_cast *>(slot)->match(func)) { iter = slots_.erase(iter); delete slot; } else { @@ -111,12 +113,13 @@ public: } } - void disconnect(void (*func)(Args...)) + template + void disconnect(R (*func)(Args...)) { for (auto iter = slots_.begin(); iter != slots_.end(); ) { - BoundMethodArgs *slot = *iter; + BoundMethodArgs *slot = *iter; if (slot->match(nullptr) && - static_cast *>(slot)->match(func)) { + static_cast *>(slot)->match(func)) { iter = slots_.erase(iter); delete slot; } else { @@ -133,7 +136,7 @@ public: */ std::vector slots{ slots_.begin(), slots_.end() }; for (BoundMethodBase *slot : slots) - static_cast *>(slot)->activate(args...); + static_cast *>(slot)->activate(args...); } }; diff --git a/src/libcamera/signal.cpp b/src/libcamera/signal.cpp index 6ee348acc8d4..190033317c72 100644 --- a/src/libcamera/signal.cpp +++ b/src/libcamera/signal.cpp @@ -54,7 +54,7 @@ namespace libcamera { */ /** - * \fn Signal::connect(T *object, void(T::*func)(Args...)) + * \fn Signal::connect(T *object, R (T::*func)(Args...)) * \brief Connect the signal to a member function slot * \param[in] object The slot object pointer * \param[in] func The slot member function @@ -66,7 +66,7 @@ namespace libcamera { */ /** - * \fn Signal::connect(void(*func)(Args...)) + * \fn Signal::connect(R (*func)(Args...)) * \brief Connect the signal to a static function slot * \param[in] func The slot static function */ @@ -83,14 +83,14 @@ namespace libcamera { */ /** - * \fn Signal::disconnect(T *object, void(T::*func)(Args...)) + * \fn Signal::disconnect(T *object, R (T::*func)(Args...)) * \brief Disconnect the signal from the \a object slot member function \a func * \param[in] object The object pointer whose slots to disconnect * \param[in] func The slot member function to disconnect */ /** - * \fn Signal::disconnect(void(*func)(Args...)) + * \fn Signal::disconnect(R (*func)(Args...)) * \brief Disconnect the signal from the slot static function \a func * \param[in] func The slot static function to disconnect */ From patchwork Sat Jan 4 05:09:42 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 2505 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id E600960461 for ; Sat, 4 Jan 2020 06:10:05 +0100 (CET) Received: from pendragon.bb.dnainternet.fi (81-175-216-236.bb.dnainternet.fi [81.175.216.236]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 85B30A49 for ; Sat, 4 Jan 2020 06:10:05 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1578114605; bh=K6K82HbM2NYoN+Iwsuyf+Rhna/oKWFyF6tyy8l9R1cs=; h=From:To:Subject:Date:In-Reply-To:References:From; b=b9h8g+Fa1PY9+UuPdj1oM4gJhM9onplvndeHj2N4f312sVAfhhGW3ygabn/P2KdDV vJXixB+SIm2/dXuHeJBEs+MuFUoZYC2ar0aJgQiVWdER0yoLF9um/fDtByLria03b5 /+beCpKQfgwyDx3Z1oNreRU5BGSlZVIZyoLHORRE= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Sat, 4 Jan 2020 07:09:42 +0200 Message-Id: <20200104050947.7673-10-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.24.1 In-Reply-To: <20200104050947.7673-1-laurent.pinchart@ideasonboard.com> References: <20200104050947.7673-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 09/14] libcamera: bound_method: Manage BoundMethodPack through std::shared_ptr X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 04 Jan 2020 05:10:08 -0000 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 9e5efae33919..5ae8773bd3ad 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 b50072ffc098..a74d2c503cdb 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 45c765774801..82339b7e9c95 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 311755cc60fe..8e8b013dcd18 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 c35bb33dfeda..77f2bdd5fbac 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()); } /** From patchwork Sat Jan 4 05:09:43 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 2506 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 5393760607 for ; Sat, 4 Jan 2020 06:10:06 +0100 (CET) Received: from pendragon.bb.dnainternet.fi (81-175-216-236.bb.dnainternet.fi [81.175.216.236]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id D8CD1A58 for ; Sat, 4 Jan 2020 06:10:05 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1578114606; bh=LHL/mAZ8wgV9cylqoYiZojUEgXcwoSor7hup2mIBjUE=; h=From:To:Subject:Date:In-Reply-To:References:From; b=caa2XxcPYZxh32QatAOnJsrFePN5SXZr7/dJ0/Ke0V1WnpTugrrMPfKwOXilEbH7Q 9I7ui8XIzWIUk6CDznEh0BStEx8J273rubAl0mog8uDLa1bfhAx2ezjoWkBtwQE8k5 t6NCYSikGRZT4lw3ZNCIKCoXpIt1YjoHt8aYQeBk= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Sat, 4 Jan 2020 07:09:43 +0200 Message-Id: <20200104050947.7673-11-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.24.1 In-Reply-To: <20200104050947.7673-1-laurent.pinchart@ideasonboard.com> References: <20200104050947.7673-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 10/14] libcamera: bound_method: Propagate method return value X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 04 Jan 2020 05:10:08 -0000 Propagate the return value of the bound method all the way to the caller of activate(). The value is stored in the arguments pack for indirect invocation. As C++ doesn't allow instantiating a variable of type void, we need to specialize the template class BoundMethodPack for methods returning void. This in turn requires template specialization for the BoundMethodArgs class in order to store the return value in the pack, and for the BoundMemberMethod class to extract the return value from the pack. Signed-off-by: Laurent Pinchart Reviewed-by: Niklas Söderlund --- include/libcamera/bound_method.h | 99 +++++++++++++++++++++++++++----- include/libcamera/object.h | 6 +- src/libcamera/bound_method.cpp | 23 ++++++-- src/libcamera/object.cpp | 6 +- 4 files changed, 113 insertions(+), 21 deletions(-) diff --git a/include/libcamera/bound_method.h b/include/libcamera/bound_method.h index a74d2c503cdb..0a91f44a2054 100644 --- a/include/libcamera/bound_method.h +++ b/include/libcamera/bound_method.h @@ -28,7 +28,7 @@ public: virtual ~BoundMethodPackBase() {} }; -template +template class BoundMethodPack : public BoundMethodPackBase { public: @@ -37,6 +37,19 @@ public: { } + std::tuple::type...> args_; + R ret_; +}; + +template +class BoundMethodPack : public BoundMethodPackBase +{ +public: + BoundMethodPack(const Args &... args) + : args_(args...) + { + } + std::tuple::type...> args_; }; @@ -77,7 +90,7 @@ protected: }; #endif - void activatePack(std::shared_ptr pack, + bool activatePack(std::shared_ptr pack, bool deleteMethod); void *obj_; @@ -91,7 +104,34 @@ template class BoundMethodArgs : public BoundMethodBase { public: - using PackType = BoundMethodPack; + using PackType = BoundMethodPack; + +private: + template + void invokePack(BoundMethodPackBase *pack, BoundMethodBase::sequence) + { + PackType *args = static_cast(pack); + args->ret_ = invoke(std::get(args->args_)...); + } + +public: + BoundMethodArgs(void *obj, Object *object, ConnectionType type) + : BoundMethodBase(obj, object, type) {} + + void invokePack(BoundMethodPackBase *pack) override + { + invokePack(pack, typename BoundMethodBase::generator::type()); + } + + virtual R activate(Args... args, bool deleteMethod = false) = 0; + virtual R invoke(Args... args) = 0; +}; + +template +class BoundMethodArgs : public BoundMethodBase +{ +public: + using PackType = BoundMethodPack; private: template @@ -129,15 +169,45 @@ public: bool match(R (T::*func)(Args...)) const { return func == func_; } + R activate(Args... args, bool deleteMethod = false) override + { + if (!this->object_) + return (static_cast(this->obj_)->*func_)(args...); + + auto pack = std::make_shared(args...); + bool sync = BoundMethodBase::activatePack(pack, deleteMethod); + return sync ? pack->ret_ : R(); + } + + R invoke(Args... args) override + { + return (static_cast(this->obj_)->*func_)(args...); + } + +private: + R (T::*func_)(Args...); +}; + +template +class BoundMemberMethod : public BoundMethodArgs +{ +public: + using PackType = typename BoundMethodArgs::PackType; + + BoundMemberMethod(T *obj, Object *object, void (T::*func)(Args...), + ConnectionType type = ConnectionTypeAuto) + : BoundMethodArgs(obj, object, type), func_(func) + { + } + + bool match(void (T::*func)(Args...)) const { return func == func_; } + void activate(Args... args, bool deleteMethod = false) override { - if (!this->object_) { - (static_cast(this->obj_)->*func_)(args...); - return; - } + if (!this->object_) + return (static_cast(this->obj_)->*func_)(args...); - std::shared_ptr pack = - std::make_shared::PackType>(args...); + auto pack = std::make_shared(args...); BoundMethodBase::activatePack(pack, deleteMethod); } @@ -147,7 +217,7 @@ public: } private: - R (T::*func_)(Args...); + void (T::*func_)(Args...); }; template @@ -162,12 +232,15 @@ public: bool match(R (*func)(Args...)) const { return func == func_; } - void activate(Args... args, bool deleteMethod = false) override + R activate(Args... args, bool deleteMethod = false) override { - (*func_)(args...); + return (*func_)(args...); } - void invoke(Args...) override {} + R invoke(Args...) override + { + return R(); + } private: R (*func_)(Args...); diff --git a/include/libcamera/object.h b/include/libcamera/object.h index 586c2cf6fc70..04aa18394d55 100644 --- a/include/libcamera/object.h +++ b/include/libcamera/object.h @@ -31,12 +31,12 @@ public: template::value>::type * = nullptr> - void invokeMethod(R (T::*func)(FuncArgs...), ConnectionType type, - Args... args) + R invokeMethod(R (T::*func)(FuncArgs...), ConnectionType type, + Args... args) { T *obj = static_cast(this); auto *method = new BoundMemberMethod(obj, this, func, type); - method->activate(args..., true); + return method->activate(args..., true); } Thread *thread() const { return thread_; } diff --git a/src/libcamera/bound_method.cpp b/src/libcamera/bound_method.cpp index 82339b7e9c95..8e95c7eec92c 100644 --- a/src/libcamera/bound_method.cpp +++ b/src/libcamera/bound_method.cpp @@ -48,7 +48,22 @@ namespace libcamera { * deadlock will occur. */ -void BoundMethodBase::activatePack(std::shared_ptr pack, +/** + * \brief Invoke the bound method with packed arguments + * \param[in] pack Packed arguments + * \param[in] deleteMethod True to delete \a this bound method instance when + * method invocation completes + * + * The bound method stores its return value, if any, in the arguments \a pack. + * For direct and blocking invocations, this is performed synchronously, and + * the return value contained in the pack may be used. For queued invocations, + * the return value is stored at an undefined point of time and shall thus not + * be used by the caller. + * + * \return True if the return value contained in the \a pack may be used by the + * caller, false otherwise + */ +bool BoundMethodBase::activatePack(std::shared_ptr pack, bool deleteMethod) { ConnectionType type = connectionType_; @@ -65,13 +80,13 @@ void BoundMethodBase::activatePack(std::shared_ptr pack, invokePack(pack.get()); if (deleteMethod) delete this; - break; + return true; case ConnectionTypeQueued: { std::unique_ptr msg = utils::make_unique(this, pack, nullptr, deleteMethod); object_->postMessage(std::move(msg)); - break; + return false; } case ConnectionTypeBlocking: { @@ -82,7 +97,7 @@ void BoundMethodBase::activatePack(std::shared_ptr pack, object_->postMessage(std::move(msg)); semaphore.acquire(); - break; + return true; } } } diff --git a/src/libcamera/object.cpp b/src/libcamera/object.cpp index e76faf48b8ed..21aad5652b38 100644 --- a/src/libcamera/object.cpp +++ b/src/libcamera/object.cpp @@ -143,7 +143,7 @@ void Object::message(Message *msg) } /** - * \fn void Object::invokeMethod() + * \fn R Object::invokeMethod() * \brief Invoke a method asynchronously on an Object instance * \param[in] func The object method to invoke * \param[in] type Connection type for method invocation @@ -156,6 +156,10 @@ void Object::message(Message *msg) * 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. + * + * \return For connection types ConnectionTypeDirect and + * ConnectionTypeBlocking, return the return value of the invoked method. For + * connection type ConnectionTypeQueued, return a default-constructed R value. */ /** From patchwork Sat Jan 4 05:09:44 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 2507 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 9736D6061C for ; Sat, 4 Jan 2020 06:10:06 +0100 (CET) Received: from pendragon.bb.dnainternet.fi (81-175-216-236.bb.dnainternet.fi [81.175.216.236]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 40566A49 for ; Sat, 4 Jan 2020 06:10:06 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1578114606; bh=WQ8oKGiEHxLEe6inw2XBqzTx7rvBSKWenfsUDa1pBQk=; h=From:To:Subject:Date:In-Reply-To:References:From; b=TJlZGPlVJxch2nMrJGFSGRGhlvHOdwbqf6IKqfnWKf5cqiD4/M1d6PYriUJyjaQnk isdpCWAvRAeV7Kjh59+42+9K9ozPG1btblb+7SRnG1wnSxCWNzzRsxIzYPK5Gr4McI 5aLKct8NmcSaCBbjJ8DDCyWlUY+iXiK/2N8tNkfo= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Sat, 4 Jan 2020 07:09:44 +0200 Message-Id: <20200104050947.7673-12-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.24.1 In-Reply-To: <20200104050947.7673-1-laurent.pinchart@ideasonboard.com> References: <20200104050947.7673-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 11/14] libcamera: bound_method: Rename Bound*Method to BoundMethod* X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 04 Jan 2020 05:10:08 -0000 Most of the bound method classes are named with a BoundMethod prefix, except for BoundMemberMethod and BoundStaticMethod. Rename them to BoundMethodMember and BoundMethodStatic respectively to make the code more coherent. Signed-off-by: Laurent Pinchart Reviewed-by: Niklas Söderlund --- Documentation/Doxyfile.in | 6 +++--- include/libcamera/bound_method.h | 12 ++++++------ include/libcamera/object.h | 2 +- include/libcamera/signal.h | 12 ++++++------ 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/Documentation/Doxyfile.in b/Documentation/Doxyfile.in index 5ae8773bd3ad..8e6fbdbb92b6 100644 --- a/Documentation/Doxyfile.in +++ b/Documentation/Doxyfile.in @@ -870,12 +870,12 @@ EXCLUDE_PATTERNS = # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories use the pattern */test/* -EXCLUDE_SYMBOLS = libcamera::BoundMemberMethod \ - libcamera::BoundMethodArgs \ +EXCLUDE_SYMBOLS = libcamera::BoundMethodArgs \ libcamera::BoundMethodBase \ + libcamera::BoundMethodMember \ libcamera::BoundMethodPack \ libcamera::BoundMethodPackBase \ - libcamera::BoundStaticMethod \ + libcamera::BoundMethodStatic \ libcamera::SignalBase \ std::* diff --git a/include/libcamera/bound_method.h b/include/libcamera/bound_method.h index 0a91f44a2054..ca501493bce2 100644 --- a/include/libcamera/bound_method.h +++ b/include/libcamera/bound_method.h @@ -156,12 +156,12 @@ public: }; template -class BoundMemberMethod : public BoundMethodArgs +class BoundMethodMember : public BoundMethodArgs { public: using PackType = typename BoundMethodArgs::PackType; - BoundMemberMethod(T *obj, Object *object, R (T::*func)(Args...), + BoundMethodMember(T *obj, Object *object, R (T::*func)(Args...), ConnectionType type = ConnectionTypeAuto) : BoundMethodArgs(obj, object, type), func_(func) { @@ -189,12 +189,12 @@ private: }; template -class BoundMemberMethod : public BoundMethodArgs +class BoundMethodMember : public BoundMethodArgs { public: using PackType = typename BoundMethodArgs::PackType; - BoundMemberMethod(T *obj, Object *object, void (T::*func)(Args...), + BoundMethodMember(T *obj, Object *object, void (T::*func)(Args...), ConnectionType type = ConnectionTypeAuto) : BoundMethodArgs(obj, object, type), func_(func) { @@ -221,10 +221,10 @@ private: }; template -class BoundStaticMethod : public BoundMethodArgs +class BoundMethodStatic : public BoundMethodArgs { public: - BoundStaticMethod(R (*func)(Args...)) + BoundMethodStatic(R (*func)(Args...)) : BoundMethodArgs(nullptr, nullptr, ConnectionTypeAuto), func_(func) { diff --git a/include/libcamera/object.h b/include/libcamera/object.h index 04aa18394d55..9344af30bc79 100644 --- a/include/libcamera/object.h +++ b/include/libcamera/object.h @@ -35,7 +35,7 @@ public: Args... args) { T *obj = static_cast(this); - auto *method = new BoundMemberMethod(obj, this, func, type); + auto *method = new BoundMethodMember(obj, this, func, type); return method->activate(args..., true); } diff --git a/include/libcamera/signal.h b/include/libcamera/signal.h index 7fbe5a2c528f..432d95d0ed1c 100644 --- a/include/libcamera/signal.h +++ b/include/libcamera/signal.h @@ -60,7 +60,7 @@ public: { Object *object = static_cast(obj); object->connect(this); - slots_.push_back(new BoundMemberMethod(obj, object, func, type)); + slots_.push_back(new BoundMethodMember(obj, object, func, type)); } template::value>::type * = nullptr> @@ -69,13 +69,13 @@ public: #endif void connect(T *obj, R (T::*func)(Args...)) { - slots_.push_back(new BoundMemberMethod(obj, nullptr, func)); + slots_.push_back(new BoundMethodMember(obj, nullptr, func)); } template void connect(R (*func)(Args...)) { - slots_.push_back(new BoundStaticMethod(func)); + slots_.push_back(new BoundMethodStatic(func)); } void disconnect() @@ -100,11 +100,11 @@ public: /* * If the object matches the slot, the slot is * guaranteed to be a member slot, so we can safely - * cast it to BoundMemberMethod to match + * cast it to BoundMethodMember to match * func. */ if (slot->match(obj) && - static_cast *>(slot)->match(func)) { + static_cast *>(slot)->match(func)) { iter = slots_.erase(iter); delete slot; } else { @@ -119,7 +119,7 @@ public: for (auto iter = slots_.begin(); iter != slots_.end(); ) { BoundMethodArgs *slot = *iter; if (slot->match(nullptr) && - static_cast *>(slot)->match(func)) { + static_cast *>(slot)->match(func)) { iter = slots_.erase(iter); delete slot; } else { From patchwork Sat Jan 4 05:09:45 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 2508 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id ECFE960623 for ; Sat, 4 Jan 2020 06:10:06 +0100 (CET) Received: from pendragon.bb.dnainternet.fi (81-175-216-236.bb.dnainternet.fi [81.175.216.236]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 8D7CEFA0 for ; Sat, 4 Jan 2020 06:10:06 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1578114606; bh=w7GKfXnNZ4PbZ7dIcabStmNoViqiYYpWD7OMX60WpJc=; h=From:To:Subject:Date:In-Reply-To:References:From; b=d3fNiK/OW65JX4oWgWkBpUGYMdqpVuoaW+aeTLnefwqdUvROm1ibQ7PzVpWRuhoFs gVk56CSms1KPpsS1AlWmh4OgTNvakpLFR3oh6KpWGZNMCb4uF5ISJdN3fVyr7hsMjF 845pYJ+Nrx3vnueZO0P2zC9kBPsY6psyaeU6GYtA= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Sat, 4 Jan 2020 07:09:45 +0200 Message-Id: <20200104050947.7673-13-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.24.1 In-Reply-To: <20200104050947.7673-1-laurent.pinchart@ideasonboard.com> References: <20200104050947.7673-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 12/14] test: object-invoke: Test invoking a non-void method X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 04 Jan 2020 05:10:08 -0000 Test that Object::invokeMethod() can be used to invoke a non-void method. Verify that the return value is correctly propagated to the caller. Signed-off-by: Laurent Pinchart Reviewed-by: Niklas Söderlund --- test/object-invoke.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/test/object-invoke.cpp b/test/object-invoke.cpp index ed16de99ef5e..8e2055ca620f 100644 --- a/test/object-invoke.cpp +++ b/test/object-invoke.cpp @@ -53,6 +53,11 @@ public: { } + int methodWithReturn() + { + return 42; + } + private: Status status_; int value_; @@ -152,6 +157,15 @@ protected: object_.invokeMethod(&InvokedObject::methodWithReference, ConnectionTypeBlocking, 42); + /* Test invoking a method that returns a value. */ + int ret = object_.invokeMethod(&InvokedObject::methodWithReturn, + ConnectionTypeBlocking); + if (ret != 42) { + cout << "Method invoked return incorrect value (" << ret + << ")" << endl; + return TestFail; + } + return TestPass; } From patchwork Sat Jan 4 05:09:46 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 2509 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 4448460608 for ; Sat, 4 Jan 2020 06:10:07 +0100 (CET) Received: from pendragon.bb.dnainternet.fi (81-175-216-236.bb.dnainternet.fi [81.175.216.236]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id D9964A49 for ; Sat, 4 Jan 2020 06:10:06 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1578114607; bh=Fzd4jZSgzcaD4adAa9bjYFqCaUVOdLkOoPsYlANy21A=; h=From:To:Subject:Date:In-Reply-To:References:From; b=C70anl/Sa8O2lTyLlOZOp7DjP4awfqg3zBvSYqyArDq018b4sAwHqAdzi0cjom4Kr xL884avRWeMB+ZSiO5e3psj7Cqc4rM5PUtoETHeuOJqQosgVqzjdf95RXfghc/iPaa RKjgdGghrMFylkTa7g1P8DCI6YfYIt37C/f4s88E= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Sat, 4 Jan 2020 07:09:46 +0200 Message-Id: <20200104050947.7673-14-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.24.1 In-Reply-To: <20200104050947.7673-1-laurent.pinchart@ideasonboard.com> References: <20200104050947.7673-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 13/14] test: signal: Test connecting to non-void slots X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 04 Jan 2020 05:10:08 -0000 Test that a signal can be connected to non-void static and member slots. Signed-off-by: Laurent Pinchart Reviewed-by: Niklas Söderlund --- test/signal.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/test/signal.cpp b/test/signal.cpp index 9d8f985d15e5..0054ed5a380d 100644 --- a/test/signal.cpp +++ b/test/signal.cpp @@ -23,6 +23,11 @@ static void slotStatic(int value) valueStatic_ = value; } +static int slotStaticReturn() +{ + return 0; +} + class SlotObject : public Object { public: @@ -85,6 +90,11 @@ protected: name_ = name; } + int slotReturn() + { + return 0; + } + int init() { return 0; @@ -174,6 +184,13 @@ protected: return TestFail; } + /* + * Test connecting to slots that return a value. This targets + * compilation, there's no need to check runtime results. + */ + signalVoid_.connect(slotStaticReturn); + signalVoid_.connect(this, &SignalTest::slotReturn); + /* ----------------- Signal -> Object tests ----------------- */ /* From patchwork Sat Jan 4 05:09:47 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 2510 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id C858B60606 for ; Sat, 4 Jan 2020 06:10:07 +0100 (CET) Received: from pendragon.bb.dnainternet.fi (81-175-216-236.bb.dnainternet.fi [81.175.216.236]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 3889AFA0 for ; Sat, 4 Jan 2020 06:10:07 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1578114607; bh=TGHhZ1p1kO44vtGIQS1hQjXWoTpvjmdnu6PNPf7AOTw=; h=From:To:Subject:Date:In-Reply-To:References:From; b=B2ex/BLbf53RWDKfX0mi6Pc4AcoRX+pyphVCJg2nyoyaHhpcgMgI9QjHIqQeTfX4a wpq6CvfstV5XNK/20XwzclR06PBL67+tsoee3KuJI/t6u6cdUTaM5YddnrgBXVbwDp etVB1c5Oey89Gbx4LK0chZmHw8Uaj94rxmpNh+Fk= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Sat, 4 Jan 2020 07:09:47 +0200 Message-Id: <20200104050947.7673-15-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.24.1 In-Reply-To: <20200104050947.7673-1-laurent.pinchart@ideasonboard.com> References: <20200104050947.7673-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 14/14] libcamera: v4l2: Use Object::invokeMethod() return value X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 04 Jan 2020 05:10:08 -0000 Now that Object::invokeMethod() supports returning a value, use it and drop the return value method argument. Signed-off-by: Laurent Pinchart Reviewed-by: Niklas Söderlund --- src/v4l2/v4l2_camera.cpp | 109 +++++++++++++++------------------ src/v4l2/v4l2_camera.h | 18 +++--- src/v4l2/v4l2_camera_proxy.cpp | 51 ++++++++------- 3 files changed, 82 insertions(+), 96 deletions(-) diff --git a/src/v4l2/v4l2_camera.cpp b/src/v4l2/v4l2_camera.cpp index 3590730fde08..4545483cf1c7 100644 --- a/src/v4l2/v4l2_camera.cpp +++ b/src/v4l2/v4l2_camera.cpp @@ -34,23 +34,21 @@ V4L2Camera::~V4L2Camera() camera_->release(); } -void V4L2Camera::open(int *ret) +int V4L2Camera::open() { /* \todo Support multiple open. */ if (camera_->acquire() < 0) { LOG(V4L2Compat, Error) << "Failed to acquire camera"; - *ret = -EINVAL; - return; + return -EINVAL; } config_ = camera_->generateConfiguration({ StreamRole::Viewfinder }); if (!config_) { camera_->release(); - *ret = -EINVAL; - return; + return -EINVAL; } - *ret = 0; + return 0; } void V4L2Camera::close() @@ -92,9 +90,9 @@ void V4L2Camera::requestComplete(Request *request) bufferSema_.release(); } -void V4L2Camera::configure(int *ret, StreamConfiguration *streamConfigOut, - const Size &size, PixelFormat pixelformat, - unsigned int bufferCount) +int V4L2Camera::configure(StreamConfiguration *streamConfigOut, + const Size &size, PixelFormat pixelformat, + unsigned int bufferCount) { StreamConfiguration &streamConfig = config_->at(0); streamConfig.size.width = size.width; @@ -106,8 +104,7 @@ void V4L2Camera::configure(int *ret, StreamConfiguration *streamConfigOut, CameraConfiguration::Status validation = config_->validate(); if (validation == CameraConfiguration::Invalid) { LOG(V4L2Compat, Debug) << "Configuration invalid"; - *ret = -EINVAL; - return; + return -EINVAL; } if (validation == CameraConfiguration::Adjusted) LOG(V4L2Compat, Debug) << "Configuration adjusted"; @@ -115,24 +112,25 @@ void V4L2Camera::configure(int *ret, StreamConfiguration *streamConfigOut, LOG(V4L2Compat, Debug) << "Validated configuration is: " << streamConfig.toString(); - *ret = camera_->configure(config_.get()); - if (*ret < 0) - return; + int ret = camera_->configure(config_.get()); + if (ret < 0) + return ret; *streamConfigOut = config_->at(0); + + return 0; } -void V4L2Camera::mmap(void **ret, unsigned int index) +void *V4L2Camera::mmap(unsigned int index) { Stream *stream = *camera_->streams().begin(); - *ret = stream->buffers()[index].planes()[0].mem(); + return stream->buffers()[index].planes()[0].mem(); } -void V4L2Camera::allocBuffers(int *ret, unsigned int count) +int V4L2Camera::allocBuffers(unsigned int count) { - *ret = camera_->allocateBuffers(); - if (*ret == -EACCES) - *ret = -EBUSY; + int ret = camera_->allocateBuffers(); + return ret == -EACCES ? -EBUSY : ret; } void V4L2Camera::freeBuffers() @@ -140,85 +138,76 @@ void V4L2Camera::freeBuffers() camera_->freeBuffers(); } -void V4L2Camera::streamOn(int *ret) +int V4L2Camera::streamOn() { - *ret = 0; - if (isRunning_) - return; + return 0; + + int ret = camera_->start(); + if (ret < 0) + return ret == -EACCES ? -EBUSY : ret; - *ret = camera_->start(); - if (*ret < 0) { - if (*ret == -EACCES) - *ret = -EBUSY; - return; - } isRunning_ = true; for (std::unique_ptr &req : pendingRequests_) { /* \todo What should we do if this returns -EINVAL? */ - *ret = camera_->queueRequest(req.release()); - if (*ret < 0) { - if (*ret == -EACCES) - *ret = -EBUSY; - return; - } + ret = camera_->queueRequest(req.release()); + if (ret < 0) + return ret == -EACCES ? -EBUSY : ret; } pendingRequests_.clear(); + + return 0; } -void V4L2Camera::streamOff(int *ret) +int V4L2Camera::streamOff() { - *ret = 0; - /* \todo Restore buffers to reqbufs state? */ if (!isRunning_) - return; + return 0; + + int ret = camera_->stop(); + if (ret < 0) + return ret == -EACCES ? -EBUSY : ret; - *ret = camera_->stop(); - if (*ret < 0) { - if (*ret == -EACCES) - *ret = -EBUSY; - return; - } isRunning_ = false; + + return 0; } -void V4L2Camera::qbuf(int *ret, unsigned int index) +int V4L2Camera::qbuf(unsigned int index) { Stream *stream = config_->at(0).stream(); std::unique_ptr buffer = stream->createBuffer(index); if (!buffer) { LOG(V4L2Compat, Error) << "Can't create buffer"; - *ret = -ENOMEM; - return; + return -ENOMEM; } std::unique_ptr request = std::unique_ptr(camera_->createRequest()); if (!request) { LOG(V4L2Compat, Error) << "Can't create request"; - *ret = -ENOMEM; - return; + return -ENOMEM; } - *ret = request->addBuffer(std::move(buffer)); - if (*ret < 0) { + int ret = request->addBuffer(std::move(buffer)); + if (ret < 0) { LOG(V4L2Compat, Error) << "Can't set buffer for request"; - *ret = -ENOMEM; - return; + return -ENOMEM; } if (!isRunning_) { pendingRequests_.push_back(std::move(request)); - return; + return 0; } - *ret = camera_->queueRequest(request.release()); - if (*ret < 0) { + ret = camera_->queueRequest(request.release()); + if (ret < 0) { LOG(V4L2Compat, Error) << "Can't queue request"; - if (*ret == -EACCES) - *ret = -EBUSY; + return ret == -EACCES ? -EBUSY : ret; } + + return 0; } diff --git a/src/v4l2/v4l2_camera.h b/src/v4l2/v4l2_camera.h index d24dbca6aaf4..5a889efdb4a2 100644 --- a/src/v4l2/v4l2_camera.h +++ b/src/v4l2/v4l2_camera.h @@ -48,23 +48,23 @@ public: V4L2Camera(std::shared_ptr camera); ~V4L2Camera(); - void open(int *ret); + int open(); void close(); void getStreamConfig(StreamConfiguration *streamConfig); std::vector completedBuffers(); - void mmap(void **ret, unsigned int index); + void *mmap(unsigned int index); - void configure(int *ret, StreamConfiguration *streamConfigOut, - const Size &size, PixelFormat pixelformat, - unsigned int bufferCount); + int configure(StreamConfiguration *streamConfigOut, + const Size &size, PixelFormat pixelformat, + unsigned int bufferCount); - void allocBuffers(int *ret, unsigned int count); + int allocBuffers(unsigned int count); void freeBuffers(); - void streamOn(int *ret); - void streamOff(int *ret); + int streamOn(); + int streamOff(); - void qbuf(int *ret, unsigned int index); + int qbuf(unsigned int index); Semaphore bufferSema_; diff --git a/src/v4l2/v4l2_camera_proxy.cpp b/src/v4l2/v4l2_camera_proxy.cpp index 559caba69270..2eeb12396d90 100644 --- a/src/v4l2/v4l2_camera_proxy.cpp +++ b/src/v4l2/v4l2_camera_proxy.cpp @@ -40,9 +40,8 @@ int V4L2CameraProxy::open(bool nonBlocking) { LOG(V4L2Compat, Debug) << "Servicing open"; - int ret; - vcam_->invokeMethod(&V4L2Camera::open, ConnectionTypeBlocking, - &ret); + int ret = vcam_->invokeMethod(&V4L2Camera::open, + ConnectionTypeBlocking); if (ret < 0) { errno = -ret; return -1; @@ -91,9 +90,8 @@ void *V4L2CameraProxy::mmap(size_t length, int prot, int flags, off_t offset) return MAP_FAILED; } - void *val; - vcam_->invokeMethod(&V4L2Camera::mmap, ConnectionTypeBlocking, - &val, index); + void *val = vcam_->invokeMethod(&V4L2Camera::mmap, + ConnectionTypeBlocking, index); buffers_[index].flags |= V4L2_BUF_FLAG_MAPPED; mmaps_[val] = index; @@ -245,9 +243,11 @@ int V4L2CameraProxy::vidioc_s_fmt(struct v4l2_format *arg) return ret; Size size(arg->fmt.pix.width, arg->fmt.pix.height); - vcam_->invokeMethod(&V4L2Camera::configure, ConnectionTypeBlocking, - &ret, &streamConfig_, size, - v4l2ToDrm(arg->fmt.pix.pixelformat), bufferCount_); + ret = vcam_->invokeMethod(&V4L2Camera::configure, + ConnectionTypeBlocking, + &streamConfig_, size, + v4l2ToDrm(arg->fmt.pix.pixelformat), + bufferCount_); if (ret < 0) return -EINVAL; @@ -297,9 +297,8 @@ int V4L2CameraProxy::freeBuffers() { LOG(V4L2Compat, Debug) << "Freeing libcamera bufs"; - int ret; - vcam_->invokeMethod(&V4L2Camera::streamOff, - ConnectionTypeBlocking, &ret); + int ret = vcam_->invokeMethod(&V4L2Camera::streamOff, + ConnectionTypeBlocking); if (ret < 0) { LOG(V4L2Compat, Error) << "Failed to stop stream"; return ret; @@ -327,10 +326,11 @@ int V4L2CameraProxy::vidioc_reqbufs(struct v4l2_requestbuffers *arg) return freeBuffers(); Size size(curV4L2Format_.fmt.pix.width, curV4L2Format_.fmt.pix.height); - vcam_->invokeMethod(&V4L2Camera::configure, ConnectionTypeBlocking, - &ret, &streamConfig_, size, - v4l2ToDrm(curV4L2Format_.fmt.pix.pixelformat), - arg->count); + ret = vcam_->invokeMethod(&V4L2Camera::configure, + ConnectionTypeBlocking, + &streamConfig_, size, + v4l2ToDrm(curV4L2Format_.fmt.pix.pixelformat), + arg->count); if (ret < 0) return -EINVAL; @@ -343,8 +343,8 @@ int V4L2CameraProxy::vidioc_reqbufs(struct v4l2_requestbuffers *arg) arg->count = streamConfig_.bufferCount; bufferCount_ = arg->count; - vcam_->invokeMethod(&V4L2Camera::allocBuffers, - ConnectionTypeBlocking, &ret, arg->count); + ret = vcam_->invokeMethod(&V4L2Camera::allocBuffers, + ConnectionTypeBlocking, arg->count); if (ret < 0) { arg->count = 0; return ret; @@ -392,9 +392,8 @@ int V4L2CameraProxy::vidioc_qbuf(struct v4l2_buffer *arg) arg->index >= bufferCount_) return -EINVAL; - int ret; - vcam_->invokeMethod(&V4L2Camera::qbuf, ConnectionTypeBlocking, - &ret, arg->index); + int ret = vcam_->invokeMethod(&V4L2Camera::qbuf, ConnectionTypeBlocking, + arg->index); if (ret < 0) return ret; @@ -437,9 +436,8 @@ int V4L2CameraProxy::vidioc_streamon(int *arg) if (!validateBufferType(*arg)) return -EINVAL; - int ret; - vcam_->invokeMethod(&V4L2Camera::streamOn, - ConnectionTypeBlocking, &ret); + int ret = vcam_->invokeMethod(&V4L2Camera::streamOn, + ConnectionTypeBlocking); return ret; } @@ -451,9 +449,8 @@ int V4L2CameraProxy::vidioc_streamoff(int *arg) if (!validateBufferType(*arg)) return -EINVAL; - int ret; - vcam_->invokeMethod(&V4L2Camera::streamOff, - ConnectionTypeBlocking, &ret); + int ret = vcam_->invokeMethod(&V4L2Camera::streamOff, + ConnectionTypeBlocking); for (struct v4l2_buffer &buf : buffers_) buf.flags &= ~(V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE);