Show a patch.

GET /api/1.1/patches/17518/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 17518,
    "url": "https://patchwork.libcamera.org/api/1.1/patches/17518/?format=api",
    "web_url": "https://patchwork.libcamera.org/patch/17518/",
    "project": {
        "id": 1,
        "url": "https://patchwork.libcamera.org/api/1.1/projects/1/?format=api",
        "name": "libcamera",
        "link_name": "libcamera",
        "list_id": "libcamera_core",
        "list_email": "libcamera-devel@lists.libcamera.org",
        "web_url": "",
        "scm_url": "",
        "webscm_url": ""
    },
    "msgid": "<20221003212128.32429-9-laurent.pinchart@ideasonboard.com>",
    "date": "2022-10-03T21:21:28",
    "name": "[libcamera-devel,8/8] libcamera: pipeline_handler: Implement factories through class templates",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": false,
    "hash": "51436a54daebb4e1332720972ff099f7600c215f",
    "submitter": {
        "id": 2,
        "url": "https://patchwork.libcamera.org/api/1.1/people/2/?format=api",
        "name": "Laurent Pinchart",
        "email": "laurent.pinchart@ideasonboard.com"
    },
    "delegate": null,
    "mbox": "https://patchwork.libcamera.org/patch/17518/mbox/",
    "series": [
        {
            "id": 3528,
            "url": "https://patchwork.libcamera.org/api/1.1/series/3528/?format=api",
            "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=3528",
            "date": "2022-10-03T21:21:20",
            "name": "libcamera: Use class templates for auto-registration",
            "version": 1,
            "mbox": "https://patchwork.libcamera.org/series/3528/mbox/"
        }
    ],
    "comments": "https://patchwork.libcamera.org/api/patches/17518/comments/",
    "check": "pending",
    "checks": "https://patchwork.libcamera.org/api/patches/17518/checks/",
    "tags": {},
    "headers": {
        "Return-Path": "<libcamera-devel-bounces@lists.libcamera.org>",
        "X-Original-To": "parsemail@patchwork.libcamera.org",
        "Delivered-To": "parsemail@patchwork.libcamera.org",
        "Received": [
            "from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id A5F94C3286\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon,  3 Oct 2022 21:21:45 +0000 (UTC)",
            "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 4FC6C60A86;\n\tMon,  3 Oct 2022 23:21:45 +0200 (CEST)",
            "from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 78EE060A73\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon,  3 Oct 2022 23:21:43 +0200 (CEST)",
            "from pendragon.ideasonboard.com (62-78-145-57.bb.dnainternet.fi\n\t[62.78.145.57])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 053A4519\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon,  3 Oct 2022 23:21:42 +0200 (CEST)"
        ],
        "DKIM-Signature": [
            "v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1664832105;\n\tbh=Y+UrL7/BUdya+hm4IVrhHl5+vkkku68PkiPAjiycm0c=;\n\th=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:\n\tFrom;\n\tb=LgdxIbTT0mCLfMbDcwaiM+jFNceeZ4A1qpdD4vbOmTSy5rkjDIkx+0ZHQCgKTFiNk\n\tkBj9y+ysZ4gaP+tkR2P9RUfCYBkkTdNM0JItgDwNMkZvLyM20OMQON3+kgCrbGp9IK\n\tPsQyFaQqh/pNq3oYoi9OERwBs0RedbnP9gSrLmmuJFa4f8Tg27tBn3T70Hw4Dfoql8\n\tspj3cIkuz0jtklty+jWyJ6KuUrSxIUUQ75BP0ERLrpZIZ9woNkLAr0Q+0UHy6Ug0zI\n\t3gP4/RGyu0KwiYcwpACtgTJeYfdiDfoZzlSUsNvTr4r0iz/wGbwQqn1Jcharp558eN\n\tMSe2lJnqaiNuA==",
            "v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1664832103;\n\tbh=Y+UrL7/BUdya+hm4IVrhHl5+vkkku68PkiPAjiycm0c=;\n\th=From:To:Subject:Date:In-Reply-To:References:From;\n\tb=RVgrMY9pISbl6RsEgejJfrJzD9MxtG2xmr80LO+wiYxLWl4648ZuFE/Ft5+RxXanj\n\teLDJfrSCi1Hw6nLOQ2L36B2OfyII9NjXRCnZ1khhSqwyWMqr97bTGOqbx0drQUVHYv\n\tZ+RjNHFYtwvfFxYNvXU+OqAlEmFzJFih5BwyTniA="
        ],
        "Authentication-Results": "lancelot.ideasonboard.com; dkim=pass (1024-bit key; \n\tunprotected) header.d=ideasonboard.com\n\theader.i=@ideasonboard.com\n\theader.b=\"RVgrMY9p\"; dkim-atps=neutral",
        "To": "libcamera-devel@lists.libcamera.org",
        "Date": "Tue,  4 Oct 2022 00:21:28 +0300",
        "Message-Id": "<20221003212128.32429-9-laurent.pinchart@ideasonboard.com>",
        "X-Mailer": "git-send-email 2.35.1",
        "In-Reply-To": "<20221003212128.32429-1-laurent.pinchart@ideasonboard.com>",
        "References": "<20221003212128.32429-1-laurent.pinchart@ideasonboard.com>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "Subject": "[libcamera-devel] [PATCH 8/8] libcamera: pipeline_handler:\n\tImplement factories through class templates",
        "X-BeenThere": "libcamera-devel@lists.libcamera.org",
        "X-Mailman-Version": "2.1.29",
        "Precedence": "list",
        "List-Id": "<libcamera-devel.lists.libcamera.org>",
        "List-Unsubscribe": "<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>",
        "List-Archive": "<https://lists.libcamera.org/pipermail/libcamera-devel/>",
        "List-Post": "<mailto:libcamera-devel@lists.libcamera.org>",
        "List-Help": "<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>",
        "List-Subscribe": "<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>",
        "From": "Laurent Pinchart via libcamera-devel\n\t<libcamera-devel@lists.libcamera.org>",
        "Reply-To": "Laurent Pinchart <laurent.pinchart@ideasonboard.com>",
        "Errors-To": "libcamera-devel-bounces@lists.libcamera.org",
        "Sender": "\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"
    },
    "content": "The REGISTER_PIPELINE_HANDLER() macro defines a class type that inherits\nfrom the PipelineHandlerFactory class, and implements a constructor and\na createInstance() function. Replace the code generation through macro\nwith the C++ equivalent, a class template, as done in libipa with the\nAlgorithm and CameraSensorHelper factories.\n\nSigned-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n---\n include/libcamera/internal/pipeline_handler.h | 44 +++++++------\n src/libcamera/camera_manager.cpp              |  6 +-\n src/libcamera/pipeline_handler.cpp            | 65 ++++++++++++-------\n test/ipa/ipa_interface_test.cpp               |  6 +-\n 4 files changed, 71 insertions(+), 50 deletions(-)",
    "diff": "diff --git a/include/libcamera/internal/pipeline_handler.h b/include/libcamera/internal/pipeline_handler.h\nindex ad74dc823290..b6139a88d421 100644\n--- a/include/libcamera/internal/pipeline_handler.h\n+++ b/include/libcamera/internal/pipeline_handler.h\n@@ -95,23 +95,23 @@ private:\n \tMutex lock_;\n \tunsigned int useCount_ LIBCAMERA_TSA_GUARDED_BY(lock_);\n \n-\tfriend class PipelineHandlerFactory;\n+\tfriend class PipelineHandlerFactoryBase;\n };\n \n-class PipelineHandlerFactory\n+class PipelineHandlerFactoryBase\n {\n public:\n-\tPipelineHandlerFactory(const char *name);\n-\tvirtual ~PipelineHandlerFactory() = default;\n+\tPipelineHandlerFactoryBase(const char *name);\n+\tvirtual ~PipelineHandlerFactoryBase() = default;\n \n \tstd::shared_ptr<PipelineHandler> create(CameraManager *manager) const;\n \n \tconst std::string &name() const { return name_; }\n \n-\tstatic std::vector<PipelineHandlerFactory *> &factories();\n+\tstatic std::vector<PipelineHandlerFactoryBase *> &factories();\n \n private:\n-\tstatic void registerType(PipelineHandlerFactory *factory);\n+\tstatic void registerType(PipelineHandlerFactoryBase *factory);\n \n \tvirtual std::unique_ptr<PipelineHandler>\n \tcreateInstance(CameraManager *manager) const = 0;\n@@ -119,19 +119,23 @@ private:\n \tstd::string name_;\n };\n \n-#define REGISTER_PIPELINE_HANDLER(handler)\t\t\t\t\\\n-class handler##Factory final : public PipelineHandlerFactory\t\t\\\n-{\t\t\t\t\t\t\t\t\t\\\n-public:\t\t\t\t\t\t\t\t\t\\\n-\thandler##Factory() : PipelineHandlerFactory(#handler) {}\t\\\n-\t\t\t\t\t\t\t\t\t\\\n-private:\t\t\t\t\t\t\t\t\\\n-\tstd::unique_ptr<PipelineHandler>\t\t\t\t\\\n-\tcreateInstance(CameraManager *manager) const\t\t\t\\\n-\t{\t\t\t\t\t\t\t\t\\\n-\t\treturn std::make_unique<handler>(manager);\t\t\\\n-\t}\t\t\t\t\t\t\t\t\\\n-};\t\t\t\t\t\t\t\t\t\\\n-static handler##Factory global_##handler##Factory;\n+template<typename _PipelineHandler>\n+class PipelineHandlerFactory final : public PipelineHandlerFactoryBase\n+{\n+public:\n+\tPipelineHandlerFactory(const char *name)\n+\t\t: PipelineHandlerFactoryBase(name)\n+\t{\n+\t}\n+\n+\tstd::unique_ptr<PipelineHandler>\n+\tcreateInstance(CameraManager *manager) const override\n+\t{\n+\t\treturn std::make_unique<_PipelineHandler>(manager);\n+\t}\n+};\n+\n+#define REGISTER_PIPELINE_HANDLER(handler) \\\n+static PipelineHandlerFactory<handler> global_##handler##Factory(#handler);\n \n } /* namespace libcamera */\ndiff --git a/src/libcamera/camera_manager.cpp b/src/libcamera/camera_manager.cpp\nindex 2c3f2d86c469..2c100c24af4d 100644\n--- a/src/libcamera/camera_manager.cpp\n+++ b/src/libcamera/camera_manager.cpp\n@@ -142,10 +142,10 @@ void CameraManager::Private::createPipelineHandlers()\n \t * file and only fallback on all handlers if there is no\n \t * configuration file.\n \t */\n-\tconst std::vector<PipelineHandlerFactory *> &factories =\n-\t\tPipelineHandlerFactory::factories();\n+\tconst std::vector<PipelineHandlerFactoryBase *> &factories =\n+\t\tPipelineHandlerFactoryBase::factories();\n \n-\tfor (const PipelineHandlerFactory *factory : factories) {\n+\tfor (const PipelineHandlerFactoryBase *factory : factories) {\n \t\tLOG(Camera, Debug)\n \t\t\t<< \"Found registered pipeline handler '\"\n \t\t\t<< factory->name() << \"'\";\ndiff --git a/src/libcamera/pipeline_handler.cpp b/src/libcamera/pipeline_handler.cpp\nindex 488dd8d32cdf..44f6fc531ad7 100644\n--- a/src/libcamera/pipeline_handler.cpp\n+++ b/src/libcamera/pipeline_handler.cpp\n@@ -64,8 +64,7 @@ LOG_DEFINE_CATEGORY(Pipeline)\n  *\n  * In order to honour the std::enable_shared_from_this<> contract,\n  * PipelineHandler instances shall never be constructed manually, but always\n- * through the PipelineHandlerFactory::create() function implemented by the\n- * respective factories.\n+ * through the PipelineHandlerFactoryBase::create() function.\n  */\n PipelineHandler::PipelineHandler(CameraManager *manager)\n \t: manager_(manager), useCount_(0)\n@@ -643,27 +642,25 @@ void PipelineHandler::disconnect()\n  */\n \n /**\n- * \\class PipelineHandlerFactory\n- * \\brief Registration of PipelineHandler classes and creation of instances\n+ * \\class PipelineHandlerFactoryBase\n+ * \\brief Base class for pipeline handler factories\n  *\n- * To facilitate discovery and instantiation of PipelineHandler classes, the\n- * PipelineHandlerFactory class maintains a registry of pipeline handler\n- * classes. Each PipelineHandler subclass shall register itself using the\n- * REGISTER_PIPELINE_HANDLER() macro, which will create a corresponding\n- * instance of a PipelineHandlerFactory subclass and register it with the\n- * static list of factories.\n+ * The PipelineHandlerFactoryBase class is the base of all specializations of\n+ * the PipelineHandlerFactory class template. It implements the factory\n+ * registration, maintains a registry of factories, and provides access to the\n+ * registered factories.\n  */\n \n /**\n- * \\brief Construct a pipeline handler factory\n+ * \\brief Construct a pipeline handler factory base\n  * \\param[in] name Name of the pipeline handler class\n  *\n- * Creating an instance of the factory registers is with the global list of\n+ * Creating an instance of the factory base registers is with the global list of\n  * factories, accessible through the factories() function.\n  *\n  * The factory \\a name is used for debug purpose and shall be unique.\n  */\n-PipelineHandlerFactory::PipelineHandlerFactory(const char *name)\n+PipelineHandlerFactoryBase::PipelineHandlerFactoryBase(const char *name)\n \t: name_(name)\n {\n \tregisterType(this);\n@@ -676,7 +673,7 @@ PipelineHandlerFactory::PipelineHandlerFactory(const char *name)\n  * \\return A shared pointer to a new instance of the PipelineHandler subclass\n  * corresponding to the factory\n  */\n-std::shared_ptr<PipelineHandler> PipelineHandlerFactory::create(CameraManager *manager) const\n+std::shared_ptr<PipelineHandler> PipelineHandlerFactoryBase::create(CameraManager *manager) const\n {\n \tstd::unique_ptr<PipelineHandler> handler = createInstance(manager);\n \thandler->name_ = name_.c_str();\n@@ -684,7 +681,7 @@ std::shared_ptr<PipelineHandler> PipelineHandlerFactory::create(CameraManager *m\n }\n \n /**\n- * \\fn PipelineHandlerFactory::name()\n+ * \\fn PipelineHandlerFactoryBase::name()\n  * \\brief Retrieve the factory name\n  * \\return The factory name\n  */\n@@ -696,9 +693,10 @@ std::shared_ptr<PipelineHandler> PipelineHandlerFactory::create(CameraManager *m\n  * The caller is responsible to guarantee the uniqueness of the pipeline handler\n  * name.\n  */\n-void PipelineHandlerFactory::registerType(PipelineHandlerFactory *factory)\n+void PipelineHandlerFactoryBase::registerType(PipelineHandlerFactoryBase *factory)\n {\n-\tstd::vector<PipelineHandlerFactory *> &factories = PipelineHandlerFactory::factories();\n+\tstd::vector<PipelineHandlerFactoryBase *> &factories =\n+\t\tPipelineHandlerFactoryBase::factories();\n \n \tfactories.push_back(factory);\n }\n@@ -707,26 +705,45 @@ void PipelineHandlerFactory::registerType(PipelineHandlerFactory *factory)\n  * \\brief Retrieve the list of all pipeline handler factories\n  * \\return the list of pipeline handler factories\n  */\n-std::vector<PipelineHandlerFactory *> &PipelineHandlerFactory::factories()\n+std::vector<PipelineHandlerFactoryBase *> &PipelineHandlerFactoryBase::factories()\n {\n \t/*\n \t * The static factories map is defined inside the function to ensure\n \t * it gets initialized on first use, without any dependency on\n \t * link order.\n \t */\n-\tstatic std::vector<PipelineHandlerFactory *> factories;\n+\tstatic std::vector<PipelineHandlerFactoryBase *> factories;\n \treturn factories;\n }\n \n+/**\n+ * \\class PipelineHandlerFactory\n+ * \\brief Registration of PipelineHandler classes and creation of instances\n+ * \\tparam _PipelineHandler The pipeline handler class type for this factory\n+ *\n+ * To facilitate discovery and instantiation of PipelineHandler classes, the\n+ * PipelineHandlerFactory class implements auto-registration of pipeline\n+ * handlers. Each PipelineHandler subclass shall register itself using the\n+ * REGISTER_PIPELINE_HANDLER() macro, which will create a corresponding\n+ * instance of a PipelineHandlerFactory and register it with the static list of\n+ * factories.\n+ */\n+\n+/**\n+ * \\fn PipelineHandlerFactory::PipelineHandlerFactory(const char *name)\n+ * \\brief Construct a pipeline handler factory\n+ * \\param[in] name Name of the pipeline handler class\n+ *\n+ * Creating an instance of the factory registers is with the global list of\n+ * factories, accessible through the factories() function.\n+ *\n+ * The factory \\a name is used for debug purpose and shall be unique.\n+ */\n+\n /**\n  * \\fn PipelineHandlerFactory::createInstance() const\n  * \\brief Create an instance of the PipelineHandler corresponding to the factory\n  * \\param[in] manager The camera manager\n- *\n- * This virtual function is implemented by the REGISTER_PIPELINE_HANDLER()\n- * macro. It creates a pipeline handler instance associated with the camera\n- * \\a manager.\n- *\n  * \\return A unique pointer to a newly constructed instance of the\n  * PipelineHandler subclass corresponding to the factory\n  */\ndiff --git a/test/ipa/ipa_interface_test.cpp b/test/ipa/ipa_interface_test.cpp\nindex a629abc28da7..6b93e976a587 100644\n--- a/test/ipa/ipa_interface_test.cpp\n+++ b/test/ipa/ipa_interface_test.cpp\n@@ -52,9 +52,9 @@ protected:\n \t\tipaManager_ = make_unique<IPAManager>();\n \n \t\t/* Create a pipeline handler for vimc. */\n-\t\tconst std::vector<PipelineHandlerFactory *> &factories =\n-\t\t\tPipelineHandlerFactory::factories();\n-\t\tfor (const PipelineHandlerFactory *factory : factories) {\n+\t\tconst std::vector<PipelineHandlerFactoryBase *> &factories =\n+\t\t\tPipelineHandlerFactoryBase::factories();\n+\t\tfor (const PipelineHandlerFactoryBase *factory : factories) {\n \t\t\tif (factory->name() == \"PipelineHandlerVimc\") {\n \t\t\t\tpipe_ = factory->create(nullptr);\n \t\t\t\tbreak;\n",
    "prefixes": [
        "libcamera-devel",
        "8/8"
    ]
}