From patchwork Tue Oct 20 01:40:01 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 10107 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 16A74BDB1F for ; Tue, 20 Oct 2020 01:40:59 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id A5718613BF; Tue, 20 Oct 2020 03:40:57 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="Z4inkzAW"; dkim-atps=neutral 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 9B61E60CE6 for ; Tue, 20 Oct 2020 03:40:56 +0200 (CEST) Received: from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 35A39309 for ; Tue, 20 Oct 2020 03:40:56 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1603158056; bh=Ac66USv+unUkNJVSXkjyKOsX4yhDCvlIGajTFo/mnzk=; h=From:To:Subject:Date:In-Reply-To:References:From; b=Z4inkzAWPAsumfns/Ylpd5bfFeotAi16bAYr/6gDUMj/b6lzdTVbOfZ7ieVeVq8O8 MOoH28nUuGXOOs7d1DhoMWw5leJxvpKRFiAz/HgHNSbmLsK8fFmDMn/du67ahpTy0b 9RqCI+iL7YxTUM1P8FTg+c2e4WUKLfHxwRHadSho= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Tue, 20 Oct 2020 04:40:01 +0300 Message-Id: <20201020014005.12783-2-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20201020014005.12783-1-laurent.pinchart@ideasonboard.com> References: <20201020014005.12783-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 1/5] utils: checkstyle.py: Add d-pointer formatter 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: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Add a formatter to ensure consistent naming of 'd' and 'o' variables related to the d-pointer design pattern, as implemented by the Extensible class. The formatter also ensures that the pointer is always const. const-correctness issues related to the data pointed to will be caught by the compiler, and thus don't need to be checked here. Signed-off-by: Laurent Pinchart Reviewed-by: Niklas Söderlund --- utils/checkstyle.py | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/utils/checkstyle.py b/utils/checkstyle.py index d5dc26c0f666..7225cac47a4e 100755 --- a/utils/checkstyle.py +++ b/utils/checkstyle.py @@ -481,6 +481,38 @@ class DoxygenFormatter(Formatter): return '\n'.join(lines) +class DPointerFormatter(Formatter): + # Ensure consistent naming of variables related to the d-pointer design + # pattern. + patterns = ('*.cpp', '*.h') + + # The clang formatter runs first, we can thus rely on appropriate coding + # style. + declare_regex = re.compile(r'^(\t*)(const )?([a-zA-Z0-9_]+) \*( ?const )?([a-zA-Z0-9_]+) = (LIBCAMERA_[DO]_PTR)\(([a-zA-Z0-9_]+)\);$') + + @classmethod + def format(cls, filename, data): + lines = [] + + for line in data.split('\n'): + match = cls.declare_regex.match(line) + if match: + indent = match.group(1) or '' + const = match.group(2) or '' + macro = match.group(6) + klass = match.group(7) + if macro == 'LIBCAMERA_D_PTR': + var = 'Private *const d' + else: + var = f'{klass} *const o' + + line = f'{indent}{const}{var} = {macro}({klass});' + + lines.append(line) + + return '\n'.join(lines) + + class IncludeOrderFormatter(Formatter): patterns = ('*.cpp', '*.h') From patchwork Tue Oct 20 01:40:02 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 10108 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 9F32ABDB1F for ; Tue, 20 Oct 2020 01:41:00 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 68A1861394; Tue, 20 Oct 2020 03:41:00 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="ivY+SFIO"; dkim-atps=neutral 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 E4FE660CE6 for ; Tue, 20 Oct 2020 03:40:56 +0200 (CEST) Received: from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 8633E52 for ; Tue, 20 Oct 2020 03:40:56 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1603158056; bh=HJn3opyIsMo9C4szyNA7FaeB56wPdvisJKO6yY0yO98=; h=From:To:Subject:Date:In-Reply-To:References:From; b=ivY+SFIOinbX0W8LViQMGuctgBGP+I97QPMcEKG+8uZkQqlZrktwCpUEkOmjZttas 2RvqeLQZ1eXPIuB2XfrUOSYcpWR8tEJjC1ZWmenieaSspv5whkeb8DIR6ZH4M2CpfO k6uGJ4uq3dmPV3yfkjIamHqpbuYMKGpRp0kLhS8g= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Tue, 20 Oct 2020 04:40:02 +0300 Message-Id: <20201020014005.12783-3-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20201020014005.12783-1-laurent.pinchart@ideasonboard.com> References: <20201020014005.12783-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 2/5] libcamera: Add a base class to implement the d-pointer design pattern 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: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" The d-pointer design patterns helps creating public classes that can be extended without breaking their ABI. To facilitate usage of the pattern in libcamera, create a base Extensible class with associated macros. Signed-off-by: Laurent Pinchart Reviewed-by: Niklas Söderlund Reviewed-by: Jacopo Mondi --- Changes since v1: - Don't hide variable declarations in LIBCAMERA_[DO]_PTR macros - Extend documentation - Fix typos --- include/libcamera/extensible.h | 86 +++++++++++++++++++++ include/libcamera/meson.build | 1 + src/libcamera/extensible.cpp | 134 +++++++++++++++++++++++++++++++++ src/libcamera/meson.build | 1 + 4 files changed, 222 insertions(+) create mode 100644 include/libcamera/extensible.h create mode 100644 src/libcamera/extensible.cpp diff --git a/include/libcamera/extensible.h b/include/libcamera/extensible.h new file mode 100644 index 000000000000..ea8808ad3e3c --- /dev/null +++ b/include/libcamera/extensible.h @@ -0,0 +1,86 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2020, Google Inc. + * + * extensible.h - Utilities to create extensible public classes with stable ABIs + */ +#ifndef __LIBCAMERA_EXTENSIBLE_H__ +#define __LIBCAMERA_EXTENSIBLE_H__ + +#include + +namespace libcamera { + +#ifndef __DOXYGEN__ +#define LIBCAMERA_DECLARE_PRIVATE(klass) \ +public: \ + class Private; \ + friend class Private; + +#define LIBCAMERA_DECLARE_PUBLIC(klass) \ + friend class klass; + +#define LIBCAMERA_D_PTR(klass) \ + _d(); + +#define LIBCAMERA_O_PTR(klass) \ + _o(); + +#else +#define LIBCAMERA_DECLARE_PRIVATE(klass) +#define LIBCAMERA_DECLARE_PUBLIC(klass) +#define LIBCAMERA_D_PTR(klass) +#define LIBCAMERA_O_PTR(klass) +#endif + +class Extensible +{ +public: + class Private + { + public: + Private(Extensible *o); + virtual ~Private(); + +#ifndef __DOXYGEN__ + template + const T *_o() const + { + return static_cast(o_); + } + + template + T *_o() + { + return static_cast(o_); + } +#endif + + private: + Extensible * const o_; + }; + + Extensible(Private *d); + +protected: +#ifndef __DOXYGEN__ + template + const T *_d() const + { + return static_cast(d_.get()); + } + + template + T *_d() + { + return static_cast(d_.get()); + } +#endif + +private: + const std::unique_ptr d_; +}; + +} /* namespace libcamera */ + +#endif /* __LIBCAMERA_EXTENSIBLE_H__ */ diff --git a/include/libcamera/meson.build b/include/libcamera/meson.build index 83bc46729314..15e6b43c9585 100644 --- a/include/libcamera/meson.build +++ b/include/libcamera/meson.build @@ -8,6 +8,7 @@ libcamera_public_headers = files([ 'controls.h', 'event_dispatcher.h', 'event_notifier.h', + 'extensible.h', 'file_descriptor.h', 'flags.h', 'framebuffer_allocator.h', diff --git a/src/libcamera/extensible.cpp b/src/libcamera/extensible.cpp new file mode 100644 index 000000000000..1dcb0bf1b12f --- /dev/null +++ b/src/libcamera/extensible.cpp @@ -0,0 +1,134 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2020, Google Inc. + * + * extensible.cpp - Utilities to create extensible public classes with stable ABIs + */ + +#include + +/** + * \file extensible.h + * \brief Utilities to create extensible public classes with stable ABIs + */ + +namespace libcamera { + +/** + * \def LIBCAMERA_DECLARE_PRIVATE + * \brief Declare private data for a public class + * \param klass The public class name + * + * The LIBCAMERA_DECLARE_PRIVATE() macro plumbs the infrastructure necessary to + * make a class manage its private data through a d-pointer. It shall be used at + * the very top of the class definition, with the public class name passed as + * the \a klass parameter. + */ + +/** + * \def LIBCAMERA_DECLARE_PUBLIC + * \brief Declare public data for a private class + * \param klass The public class name + * + * The LIBCAMERA_DECLARE_PUBLIC() macro is the counterpart of + * LIBCAMERA_DECLARE_PRIVATE() to be used in the private data class. It shall be + * used at the very top of the private class definition, with the public class + * name passed as the \a klass parameter. + */ + +/** + * \def LIBCAMERA_D_PTR(klass) + * \brief Retrieve the private data pointer + * \param[in] klass The public class name + * + * This macro can be used in any member function of a class that inherits, + * directly or indirectly, from the Extensible class, to create a local + * variable named 'd' that points to the class' private data instance. + */ + +/** + * \def LIBCAMERA_O_PTR(klass) + * \brief Retrieve the public instance corresponding to the private data + * \param[in] klass The public class name + * + * This macro is the counterpart of LIBCAMERA_D_PTR() for private data classes. + * It can be used in any member function of the private data class to create a + * local variable named 'o' that points to the public class instance + * corresponding to the private data. + */ + +/** + * \class Extensible + * \brief Base class to manage private data through a d-pointer + * + * The Extensible class provides a base class to implement the + * d-pointer design pattern (also + * known as opaque pointer + * or pImpl idiom). + * It helps creating public classes that can be extended without breaking their + * ABI. Such classes store their private data in a separate private data object, + * referenced by a pointer in the public class (hence the name d-pointer). + * + * Classes that follow this design pattern are referred herein as extensible + * classes. To be extensible, a class PublicClass shall: + * + * - inherit from the Extensible class or from another extensible class + * - invoke the LIBCAMERA_DECLARE_PRIVATE() macro at the very top of the class + * definition + * - define a private data class named PublicClass::Private that inherits from + * the Private data class of the base class + * - invoke the LIBCAMERA_DECLARE_PUBLIC() macro at the very top of the Private + * data class definition + * - pass a pointer to a newly allocated Private data object to the constructor + * of the base class + * + * Additionally, if the PublicClass is not final, it shall expose one or more + * constructors that takes a pointer to a Private data instance, to be used by + * derived classes. + * + * The Private class is fully opaque to users of the libcamera public API. + * Internally, it can be kept private to the implementation of PublicClass, or + * be exposed to other classes. In the latter case, the members of the Private + * class need to be qualified with appropriate access specifiers. The + * PublicClass and Private classes always have full access to each other's + * protected and private members. + */ + +/** + * \brief Construct an instance of an Extensible class + * \param[in] d Pointer to the private data instance + */ +Extensible::Extensible(Extensible::Private *d) + : d_(d) +{ +} + +/** + * \var Extensible::d_ + * \brief Pointer to the private data instance + */ + +/** + * \class Extensible::Private + * \brief Base class for private data managed through a d-pointer + */ + +/** + * \brief Construct an instance of an Extensible class private data + * \param[in] o Pointer to the public class object + */ +Extensible::Private::Private(Extensible *o) + : o_(o) +{ +} + +Extensible::Private::~Private() +{ +} + +/** + * \var Extensible::Private::o_ + * \brief Pointer to the public class object + */ + +} /* namespace libcamera */ diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build index 47ddb4014a61..b9f6457433f9 100644 --- a/src/libcamera/meson.build +++ b/src/libcamera/meson.build @@ -17,6 +17,7 @@ libcamera_sources = files([ 'event_dispatcher.cpp', 'event_dispatcher_poll.cpp', 'event_notifier.cpp', + 'extensible.cpp', 'file.cpp', 'file_descriptor.cpp', 'flags.cpp', From patchwork Tue Oct 20 01:40:03 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 10109 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 18C9ABDB1F for ; Tue, 20 Oct 2020 01:41:01 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id D60E96052F; Tue, 20 Oct 2020 03:41:00 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="fcDunE+X"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 3DD2060CE6 for ; Tue, 20 Oct 2020 03:40:57 +0200 (CEST) Received: from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id D5C98309 for ; Tue, 20 Oct 2020 03:40:56 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1603158057; bh=26KzoJx9qWaZkCKCO4gPjO1Iu/nyX45r/CLqOaCLeh0=; h=From:To:Subject:Date:In-Reply-To:References:From; b=fcDunE+XmyeGbROi9B1R/TPiI+1dt0IlfUt+O3kZ0JJxMlLobFROEfixZMNkVaQgY YSDEvTizsj1iopqByAB2e5gNf4jWrXQKQj5LkknsiqrE6teTin9wOm50ZXeLt0wmDx kNOXNjx0elpqqbcANEtDII2tmi8WgLVYh1iZDXmQ= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Tue, 20 Oct 2020 04:40:03 +0300 Message-Id: <20201020014005.12783-4-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20201020014005.12783-1-laurent.pinchart@ideasonboard.com> References: <20201020014005.12783-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 3/5] libcamera: camera_manager: Make CameraManager::Private::mutex_ mutable 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: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" The mutex_ stored in the CameraManager::Private class is used to protect members that may need to be accessed from const functions. Make it mutable to allow this. Signed-off-by: Laurent Pinchart Reviewed-by: Niklas Söderlund Reviewed-by: Jacopo Mondi Reviewed-by: Paul Elder --- src/libcamera/camera_manager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcamera/camera_manager.cpp b/src/libcamera/camera_manager.cpp index 81785f919d8b..3fef69633028 100644 --- a/src/libcamera/camera_manager.cpp +++ b/src/libcamera/camera_manager.cpp @@ -50,7 +50,7 @@ public: * - initialized_ and status_ during initialization * - cameras_ and camerasByDevnum_ after initialization */ - Mutex mutex_; + mutable Mutex mutex_; std::vector> cameras_; std::map> camerasByDevnum_; From patchwork Tue Oct 20 01:40:04 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 10110 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 840A2BDB1F for ; Tue, 20 Oct 2020 01:41:01 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 3A0B1613C7; Tue, 20 Oct 2020 03:41:01 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="Iu1I5uSh"; dkim-atps=neutral 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 99E58613BD for ; Tue, 20 Oct 2020 03:40:57 +0200 (CEST) Received: from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 3784552 for ; Tue, 20 Oct 2020 03:40:57 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1603158057; bh=gqielP2HxgvrLs4gMJ+W6IeUL4M+r8PL1YWZdA3j+Ag=; h=From:To:Subject:Date:In-Reply-To:References:From; b=Iu1I5uSh1q6WRV+kqagsCnGkw7lUDSPOtEQ/oCThXJKFDntQNpkUHbaGSxKhMvZdc fwBt2p86MxyaDVH/ZMQqecmXhTdpiB7qdZkLBwAxCEHchkLHWjHGt9e7SL7bFbKXlK 9Z3/RoBRm9Gc63CG06Gb/SCB9XZBbkOqgfaU6E3k= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Tue, 20 Oct 2020 04:40:04 +0300 Message-Id: <20201020014005.12783-5-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20201020014005.12783-1-laurent.pinchart@ideasonboard.com> References: <20201020014005.12783-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 4/5] libcamera: camera_manager: Inherit from Extensible 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: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Use the d-pointer infrastructure offered by the Extensible class to replace the custom implementation. Signed-off-by: Laurent Pinchart Reviewed-by: Niklas Söderlund --- Changes since v1: - Declare variables explicitly --- include/libcamera/camera_manager.h | 7 ++-- src/libcamera/camera_manager.cpp | 55 +++++++++++++++++++----------- 2 files changed, 38 insertions(+), 24 deletions(-) diff --git a/include/libcamera/camera_manager.h b/include/libcamera/camera_manager.h index 9eb2b6f5a5f5..6d5341c76412 100644 --- a/include/libcamera/camera_manager.h +++ b/include/libcamera/camera_manager.h @@ -12,6 +12,7 @@ #include #include +#include #include #include @@ -20,8 +21,9 @@ namespace libcamera { class Camera; class EventDispatcher; -class CameraManager : public Object +class CameraManager : public Object, public Extensible { + LIBCAMERA_DECLARE_PRIVATE(CameraManager) public: CameraManager(); CameraManager(const CameraManager &) = delete; @@ -50,9 +52,6 @@ public: private: static const std::string version_; static CameraManager *self_; - - class Private; - std::unique_ptr p_; }; } /* namespace libcamera */ diff --git a/src/libcamera/camera_manager.cpp b/src/libcamera/camera_manager.cpp index 3fef69633028..bcd6eac2d798 100644 --- a/src/libcamera/camera_manager.cpp +++ b/src/libcamera/camera_manager.cpp @@ -34,8 +34,10 @@ namespace libcamera { LOG_DEFINE_CATEGORY(Camera) -class CameraManager::Private : public Thread +class CameraManager::Private : public Extensible::Private, public Thread { + LIBCAMERA_DECLARE_PUBLIC(CameraManager) + public: Private(CameraManager *cm); @@ -62,8 +64,6 @@ private: void createPipelineHandlers(); void cleanup(); - CameraManager *cm_; - std::condition_variable cv_; bool initialized_; int status_; @@ -75,7 +75,7 @@ private: }; CameraManager::Private::Private(CameraManager *cm) - : cm_(cm), initialized_(false) + : Extensible::Private(cm), initialized_(false) { } @@ -136,6 +136,8 @@ int CameraManager::Private::init() void CameraManager::Private::createPipelineHandlers() { + CameraManager *const o = LIBCAMERA_O_PTR(CameraManager); + /* * \todo Try to read handlers and order from configuration * file and only fallback on all handlers if there is no @@ -153,7 +155,7 @@ void CameraManager::Private::createPipelineHandlers() * all pipelines it can provide. */ while (1) { - std::shared_ptr pipe = factory->create(cm_); + std::shared_ptr pipe = factory->create(o); if (!pipe->match(enumerator_.get())) break; @@ -264,7 +266,7 @@ void CameraManager::Private::removeCamera(Camera *camera) CameraManager *CameraManager::self_ = nullptr; CameraManager::CameraManager() - : p_(new CameraManager::Private(this)) + : Extensible(new CameraManager::Private(this)) { if (self_) LOG(Camera, Fatal) @@ -292,9 +294,11 @@ CameraManager::~CameraManager() */ int CameraManager::start() { + Private *const d = LIBCAMERA_D_PTR(CameraManager); + LOG(Camera, Info) << "libcamera " << version_; - int ret = p_->start(); + int ret = d->start(); if (ret) LOG(Camera, Error) << "Failed to start camera manager: " << strerror(-ret); @@ -314,8 +318,9 @@ int CameraManager::start() */ void CameraManager::stop() { - p_->exit(); - p_->wait(); + Private *const d = LIBCAMERA_D_PTR(CameraManager); + d->exit(); + d->wait(); } /** @@ -331,9 +336,11 @@ void CameraManager::stop() */ std::vector> CameraManager::cameras() const { - MutexLocker locker(p_->mutex_); + const Private *const d = LIBCAMERA_D_PTR(CameraManager); - return p_->cameras_; + MutexLocker locker(d->mutex_); + + return d->cameras_; } /** @@ -349,9 +356,11 @@ std::vector> CameraManager::cameras() const */ std::shared_ptr CameraManager::get(const std::string &id) { - MutexLocker locker(p_->mutex_); + Private *const d = LIBCAMERA_D_PTR(CameraManager); - for (std::shared_ptr camera : p_->cameras_) { + MutexLocker locker(d->mutex_); + + for (std::shared_ptr camera : d->cameras_) { if (camera->id() == id) return camera; } @@ -377,10 +386,12 @@ std::shared_ptr CameraManager::get(const std::string &id) */ std::shared_ptr CameraManager::get(dev_t devnum) { - MutexLocker locker(p_->mutex_); + Private *const d = LIBCAMERA_D_PTR(CameraManager); - auto iter = p_->camerasByDevnum_.find(devnum); - if (iter == p_->camerasByDevnum_.end()) + MutexLocker locker(d->mutex_); + + auto iter = d->camerasByDevnum_.find(devnum); + if (iter == d->camerasByDevnum_.end()) return nullptr; return iter->second.lock(); @@ -431,9 +442,11 @@ std::shared_ptr CameraManager::get(dev_t devnum) void CameraManager::addCamera(std::shared_ptr camera, const std::vector &devnums) { - ASSERT(Thread::current() == p_.get()); + Private *const d = LIBCAMERA_D_PTR(CameraManager); - p_->addCamera(camera, devnums); + ASSERT(Thread::current() == d); + + d->addCamera(camera, devnums); cameraAdded.emit(camera); } @@ -449,9 +462,11 @@ void CameraManager::addCamera(std::shared_ptr camera, */ void CameraManager::removeCamera(std::shared_ptr camera) { - ASSERT(Thread::current() == p_.get()); + Private *const d = LIBCAMERA_D_PTR(CameraManager); - p_->removeCamera(camera.get()); + ASSERT(Thread::current() == d); + + d->removeCamera(camera.get()); cameraRemoved.emit(camera); } From patchwork Tue Oct 20 01:40:05 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 10111 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id B59EDBDB1F for ; Tue, 20 Oct 2020 01:41:02 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 826BE613C6; Tue, 20 Oct 2020 03:41:02 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="nGdnWSR0"; dkim-atps=neutral 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 07120613C4 for ; Tue, 20 Oct 2020 03:40:58 +0200 (CEST) Received: from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 89C32309 for ; Tue, 20 Oct 2020 03:40:57 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1603158057; bh=CwQQ2JCE6HH8mYZQ8L+NdCxqaymtTPr13XUK5pyvKWM=; h=From:To:Subject:Date:In-Reply-To:References:From; b=nGdnWSR0Ydc/hVVCkx4ARPGc8V+Z0D9L31PSSoJLl4JJMZ/LjxhgjPfE1LGtXrPtY dKPY/NQ4AK4eXs2FbaJ0csQExpcYdpc+BfWynAj9jTSiX9/asVwe9q3OnnGrMXRspV 1gc0VO7G2VMlL6lGdLjIHRQbQ22q5MWVOeiJLpYc= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Tue, 20 Oct 2020 04:40:05 +0300 Message-Id: <20201020014005.12783-6-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20201020014005.12783-1-laurent.pinchart@ideasonboard.com> References: <20201020014005.12783-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 5/5] libcamera: camera: Inherit from Extensible 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: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Use the d-pointer infrastructure offered by the Extensible class to replace the custom implementation. Signed-off-by: Laurent Pinchart Reviewed-by: Niklas Söderlund --- Changes since v1: - Declare variables explicitly --- include/libcamera/camera.h | 9 +-- src/libcamera/camera.cpp | 123 ++++++++++++++++++++++--------------- 2 files changed, 80 insertions(+), 52 deletions(-) diff --git a/include/libcamera/camera.h b/include/libcamera/camera.h index 79ff8d6b67a4..5c5f1a05c77d 100644 --- a/include/libcamera/camera.h +++ b/include/libcamera/camera.h @@ -13,6 +13,7 @@ #include #include +#include #include #include #include @@ -70,8 +71,11 @@ protected: std::vector config_; }; -class Camera final : public Object, public std::enable_shared_from_this +class Camera final : public Object, public std::enable_shared_from_this, + public Extensible { + LIBCAMERA_DECLARE_PRIVATE(Camera) + public: static std::shared_ptr create(PipelineHandler *pipe, const std::string &id, @@ -107,9 +111,6 @@ private: const std::set &streams); ~Camera(); - class Private; - std::unique_ptr p_; - friend class PipelineHandler; void disconnect(); void requestComplete(Request *request); diff --git a/src/libcamera/camera.cpp b/src/libcamera/camera.cpp index 9590ab7249d3..a6181bba8cc7 100644 --- a/src/libcamera/camera.cpp +++ b/src/libcamera/camera.cpp @@ -270,8 +270,10 @@ std::size_t CameraConfiguration::size() const * \brief The vector of stream configurations */ -class Camera::Private +class Camera::Private : public Extensible::Private { + LIBCAMERA_DECLARE_PUBLIC(Camera) + public: enum State { CameraAvailable, @@ -280,7 +282,7 @@ public: CameraRunning, }; - Private(PipelineHandler *pipe, const std::string &id, + Private(Camera *camera, PipelineHandler *pipe, const std::string &id, const std::set &streams); ~Private(); @@ -301,10 +303,11 @@ private: std::atomic state_; }; -Camera::Private::Private(PipelineHandler *pipe, const std::string &id, +Camera::Private::Private(Camera *camera, PipelineHandler *pipe, + const std::string &id, const std::set &streams) - : pipe_(pipe->shared_from_this()), id_(id), streams_(streams), - disconnected_(false), state_(CameraAvailable) + : Extensible::Private(camera), pipe_(pipe->shared_from_this()), id_(id), + streams_(streams), disconnected_(false), state_(CameraAvailable) { } @@ -519,7 +522,8 @@ std::shared_ptr Camera::create(PipelineHandler *pipe, */ const std::string &Camera::id() const { - return p_->id_; + const Private *const d = LIBCAMERA_D_PTR(Camera); + return d->id_; } /** @@ -547,7 +551,7 @@ const std::string &Camera::id() const Camera::Camera(PipelineHandler *pipe, const std::string &id, const std::set &streams) - : p_(new Private(pipe, id, streams)) + : Extensible(new Private(this, pipe, id, streams)) { } @@ -569,28 +573,32 @@ Camera::~Camera() */ void Camera::disconnect() { + Private *const d = LIBCAMERA_D_PTR(Camera); + LOG(Camera, Debug) << "Disconnecting camera " << id(); - p_->disconnect(); + d->disconnect(); disconnected.emit(this); } int Camera::exportFrameBuffers(Stream *stream, std::vector> *buffers) { - int ret = p_->isAccessAllowed(Private::CameraConfigured); + Private *const d = LIBCAMERA_D_PTR(Camera); + + int ret = d->isAccessAllowed(Private::CameraConfigured); if (ret < 0) return ret; if (streams().find(stream) == streams().end()) return -EINVAL; - if (p_->activeStreams_.find(stream) == p_->activeStreams_.end()) + if (d->activeStreams_.find(stream) == d->activeStreams_.end()) return -EINVAL; - return p_->pipe_->invokeMethod(&PipelineHandler::exportFrameBuffers, - ConnectionTypeBlocking, this, stream, - buffers); + return d->pipe_->invokeMethod(&PipelineHandler::exportFrameBuffers, + ConnectionTypeBlocking, this, stream, + buffers); } /** @@ -619,21 +627,23 @@ int Camera::exportFrameBuffers(Stream *stream, */ int Camera::acquire() { + Private *const d = LIBCAMERA_D_PTR(Camera); + /* * No manual locking is required as PipelineHandler::lock() is * thread-safe. */ - int ret = p_->isAccessAllowed(Private::CameraAvailable); + int ret = d->isAccessAllowed(Private::CameraAvailable); if (ret < 0) return ret == -EACCES ? -EBUSY : ret; - if (!p_->pipe_->lock()) { + if (!d->pipe_->lock()) { LOG(Camera, Info) << "Pipeline handler in use by another process"; return -EBUSY; } - p_->setState(Private::CameraAcquired); + d->setState(Private::CameraAcquired); return 0; } @@ -654,14 +664,16 @@ int Camera::acquire() */ int Camera::release() { - int ret = p_->isAccessAllowed(Private::CameraAvailable, - Private::CameraConfigured, true); + Private *const d = LIBCAMERA_D_PTR(Camera); + + int ret = d->isAccessAllowed(Private::CameraAvailable, + Private::CameraConfigured, true); if (ret < 0) return ret == -EACCES ? -EBUSY : ret; - p_->pipe_->unlock(); + d->pipe_->unlock(); - p_->setState(Private::CameraAvailable); + d->setState(Private::CameraAvailable); return 0; } @@ -678,7 +690,8 @@ int Camera::release() */ const ControlInfoMap &Camera::controls() const { - return p_->pipe_->controls(this); + const Private *const d = LIBCAMERA_D_PTR(Camera); + return d->pipe_->controls(this); } /** @@ -691,7 +704,8 @@ const ControlInfoMap &Camera::controls() const */ const ControlList &Camera::properties() const { - return p_->pipe_->properties(this); + const Private *const d = LIBCAMERA_D_PTR(Camera); + return d->pipe_->properties(this); } /** @@ -707,7 +721,8 @@ const ControlList &Camera::properties() const */ const std::set &Camera::streams() const { - return p_->streams_; + const Private *const d = LIBCAMERA_D_PTR(Camera); + return d->streams_; } /** @@ -728,15 +743,17 @@ const std::set &Camera::streams() const */ std::unique_ptr Camera::generateConfiguration(const StreamRoles &roles) { - int ret = p_->isAccessAllowed(Private::CameraAvailable, - Private::CameraRunning); + Private *const d = LIBCAMERA_D_PTR(Camera); + + int ret = d->isAccessAllowed(Private::CameraAvailable, + Private::CameraRunning); if (ret < 0) return nullptr; if (roles.size() > streams().size()) return nullptr; - CameraConfiguration *config = p_->pipe_->generateConfiguration(this, roles); + CameraConfiguration *config = d->pipe_->generateConfiguration(this, roles); if (!config) { LOG(Camera, Debug) << "Pipeline handler failed to generate configuration"; @@ -787,8 +804,10 @@ std::unique_ptr Camera::generateConfiguration(const StreamR */ int Camera::configure(CameraConfiguration *config) { - int ret = p_->isAccessAllowed(Private::CameraAcquired, - Private::CameraConfigured); + Private *const d = LIBCAMERA_D_PTR(Camera); + + int ret = d->isAccessAllowed(Private::CameraAcquired, + Private::CameraConfigured); if (ret < 0) return ret; @@ -810,26 +829,26 @@ int Camera::configure(CameraConfiguration *config) LOG(Camera, Info) << msg.str(); - ret = p_->pipe_->invokeMethod(&PipelineHandler::configure, - ConnectionTypeBlocking, this, config); + ret = d->pipe_->invokeMethod(&PipelineHandler::configure, + ConnectionTypeBlocking, this, config); if (ret) return ret; - p_->activeStreams_.clear(); + d->activeStreams_.clear(); for (const StreamConfiguration &cfg : *config) { Stream *stream = cfg.stream(); if (!stream) { LOG(Camera, Fatal) << "Pipeline handler failed to update stream configuration"; - p_->activeStreams_.clear(); + d->activeStreams_.clear(); return -EINVAL; } stream->configuration_ = cfg; - p_->activeStreams_.insert(stream); + d->activeStreams_.insert(stream); } - p_->setState(Private::CameraConfigured); + d->setState(Private::CameraConfigured); return 0; } @@ -857,8 +876,10 @@ int Camera::configure(CameraConfiguration *config) */ std::unique_ptr Camera::createRequest(uint64_t cookie) { - int ret = p_->isAccessAllowed(Private::CameraConfigured, - Private::CameraRunning); + Private *const d = LIBCAMERA_D_PTR(Camera); + + int ret = d->isAccessAllowed(Private::CameraConfigured, + Private::CameraRunning); if (ret < 0) return nullptr; @@ -889,7 +910,9 @@ std::unique_ptr Camera::createRequest(uint64_t cookie) */ int Camera::queueRequest(Request *request) { - int ret = p_->isAccessAllowed(Private::CameraRunning); + Private *const d = LIBCAMERA_D_PTR(Camera); + + int ret = d->isAccessAllowed(Private::CameraRunning); if (ret < 0) return ret; @@ -907,14 +930,14 @@ int Camera::queueRequest(Request *request) for (auto const &it : request->buffers()) { const Stream *stream = it.first; - if (p_->activeStreams_.find(stream) == p_->activeStreams_.end()) { + if (d->activeStreams_.find(stream) == d->activeStreams_.end()) { LOG(Camera, Error) << "Invalid request"; return -EINVAL; } } - return p_->pipe_->invokeMethod(&PipelineHandler::queueRequest, - ConnectionTypeQueued, this, request); + return d->pipe_->invokeMethod(&PipelineHandler::queueRequest, + ConnectionTypeQueued, this, request); } /** @@ -935,18 +958,20 @@ int Camera::queueRequest(Request *request) */ int Camera::start() { - int ret = p_->isAccessAllowed(Private::CameraConfigured); + Private *const d = LIBCAMERA_D_PTR(Camera); + + int ret = d->isAccessAllowed(Private::CameraConfigured); if (ret < 0) return ret; LOG(Camera, Debug) << "Starting capture"; - ret = p_->pipe_->invokeMethod(&PipelineHandler::start, - ConnectionTypeBlocking, this); + ret = d->pipe_->invokeMethod(&PipelineHandler::start, + ConnectionTypeBlocking, this); if (ret) return ret; - p_->setState(Private::CameraRunning); + d->setState(Private::CameraRunning); return 0; } @@ -967,16 +992,18 @@ int Camera::start() */ int Camera::stop() { - int ret = p_->isAccessAllowed(Private::CameraRunning); + Private *const d = LIBCAMERA_D_PTR(Camera); + + int ret = d->isAccessAllowed(Private::CameraRunning); if (ret < 0) return ret; LOG(Camera, Debug) << "Stopping capture"; - p_->setState(Private::CameraConfigured); + d->setState(Private::CameraConfigured); - p_->pipe_->invokeMethod(&PipelineHandler::stop, ConnectionTypeBlocking, - this); + d->pipe_->invokeMethod(&PipelineHandler::stop, ConnectionTypeBlocking, + this); return 0; }