From patchwork Tue Feb 25 17:35:40 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= X-Patchwork-Id: 22871 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 D8EC2BF415 for ; Tue, 25 Feb 2025 17:35:48 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 9540B6872B; Tue, 25 Feb 2025 18:35:48 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=protonmail.com header.i=@protonmail.com header.b="P7TN++2B"; dkim-atps=neutral Received: from mail-40133.protonmail.ch (mail-40133.protonmail.ch [185.70.40.133]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 79843686D6 for ; Tue, 25 Feb 2025 18:35:47 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=protonmail.com; s=protonmail3; t=1740504947; x=1740764147; bh=NohWC25paeDD05GFZEjseHzjU2U90DXzZAy5I7nfmzw=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: Feedback-ID:From:To:Cc:Date:Subject:Reply-To:Feedback-ID: Message-ID:BIMI-Selector:List-Unsubscribe:List-Unsubscribe-Post; b=P7TN++2B6+qbaPf5Ka3aMlyXJO5SV95UDqndMwANy5IxVoRb4m6BvjhzSYwkfhQWr 95wD8fSEMlKfvt5B1UBusZcCoe7N2+GCLo8dUHjVjqtwB1/qFWpffE16ouIpzCHKR1 kpMf5Adx/DLqYuV9g5ikpqAjlCVC8lkrxCCbAzXPblVrN7pX5fyheyBlHNO7+1Odj+ 8Nd3bLMHmkzfLhO2/5N42jFHYMy0pyHOr9JBMy8d68q0vJGqxpb3xnEeVbVOghvKYf hRWTD9uEoRlPECzkhov0aAJS1EjTZ2CVQNDPWxdeXK9b0ktAjcJaQOo7+IFunirgKo YcN/Ymel1QR6Q== Date: Tue, 25 Feb 2025 17:35:40 +0000 To: libcamera-devel@lists.libcamera.org From: =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= Cc: Jacopo Mondi , Laurent Pinchart Subject: [PATCH v4 1/8] libcamera: base: log: Remove move constructor Message-ID: <20250225173531.2595922-2-pobrn@protonmail.com> In-Reply-To: <20250225173531.2595922-1-pobrn@protonmail.com> References: <20250225173531.2595922-1-pobrn@protonmail.com> Feedback-ID: 20568564:user:proton X-Pm-Message-ID: 9e5ae96a632bb3f5f7cc83d1af8d1f7ecfb54602 MIME-Version: 1.0 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" C++17 guarantees move and copy elision in certain cases, such as when returning a prvalue of the same type as the return type of the function. This is what the `_log()` functions do, thus there is no need for the move constructor, so remove it. Furthermore, do not just remove the implementation, but instead delete it as well. Signed-off-by: Barnabás Pőcze Reviewed-by: Jacopo Mondi Reviewed-by: Laurent Pinchart --- include/libcamera/base/log.h | 4 +--- src/libcamera/base/log.cpp | 19 ------------------- 2 files changed, 1 insertion(+), 22 deletions(-) diff --git a/include/libcamera/base/log.h b/include/libcamera/base/log.h index 620930125..b3050eedb 100644 --- a/include/libcamera/base/log.h +++ b/include/libcamera/base/log.h @@ -61,8 +61,6 @@ public: LogMessage(const char *fileName, unsigned int line, const LogCategory &category, LogSeverity severity, const std::string &prefix = std::string()); - - LogMessage(LogMessage &&); ~LogMessage(); std::ostream &stream() { return msgStream_; } @@ -75,7 +73,7 @@ public: const std::string msg() const { return msgStream_.str(); } private: - LIBCAMERA_DISABLE_COPY(LogMessage) + LIBCAMERA_DISABLE_COPY_AND_MOVE(LogMessage) void init(const char *fileName, unsigned int line); diff --git a/src/libcamera/base/log.cpp b/src/libcamera/base/log.cpp index 72e0db859..009f6c737 100644 --- a/src/libcamera/base/log.cpp +++ b/src/libcamera/base/log.cpp @@ -866,25 +866,6 @@ LogMessage::LogMessage(const char *fileName, unsigned int line, init(fileName, line); } -/** - * \brief Move-construct a log message - * \param[in] other The other message - * - * The move constructor is meant to support the _log() functions. Thanks to copy - * elision it will likely never be called, but C++11 only permits copy elision, - * it doesn't enforce it unlike C++17. To avoid potential link errors depending - * on the compiler type and version, and optimization level, the move - * constructor is defined even if it will likely never be called, and ensures - * that the destructor of the \a other message will not output anything to the - * log by setting the severity to LogInvalid. - */ -LogMessage::LogMessage(LogMessage &&other) - : msgStream_(std::move(other.msgStream_)), category_(other.category_), - severity_(other.severity_) -{ - other.severity_ = LogInvalid; -} - void LogMessage::init(const char *fileName, unsigned int line) { /* Log the timestamp, severity and file information. */ From patchwork Tue Feb 25 17:35:47 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= X-Patchwork-Id: 22872 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 AC5F6BF415 for ; Tue, 25 Feb 2025 17:35:54 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 74BA56872E; Tue, 25 Feb 2025 18:35:54 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=protonmail.com header.i=@protonmail.com header.b="J7gQFGzC"; dkim-atps=neutral Received: from mail-10628.protonmail.ch (mail-10628.protonmail.ch [79.135.106.28]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 8851268729 for ; Tue, 25 Feb 2025 18:35:53 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=protonmail.com; s=protonmail3; t=1740504952; x=1740764152; bh=xKvIYnd54/uUWp7DK4M4mncZabCWFRWoHU/yRFWVl/w=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: Feedback-ID:From:To:Cc:Date:Subject:Reply-To:Feedback-ID: Message-ID:BIMI-Selector:List-Unsubscribe:List-Unsubscribe-Post; b=J7gQFGzCYGeV44i4dmJQswR+KznjjzJ0mPmJgi8D1Yk4P7jOfLyszjR3hDZUJ+bbX /6L4XOi2CQAQ45axfsUuoP3jxYqa8UxhAbOCJ8A3jRWA9//GhCoUCwSrkW0cRcUVhS g798uXB0xk15kDHT8mvVLm15Qiw0N7zfTX5vFAN5USK0fmhB57/XEAq8ItOiV21RmM eOiBl4LlH/XP1jqcA65z5xcYrpk8duN1ExgHk0ZXtKffp+rzLIwJId3X+1S0ZZmmBC TC4KDTEBTv3hy8Fx/jAr6xXKiWZekri/awu1b+Xzl+YFwVMMA0oj7ldt2iNCTNMWS+ bhO4RwFJsnEXQ== Date: Tue, 25 Feb 2025 17:35:47 +0000 To: libcamera-devel@lists.libcamera.org From: =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= Cc: Laurent Pinchart , Jacopo Mondi Subject: [PATCH v4 2/8] libcamera: base: log: Use `std::from_chars()` Message-ID: <20250225173531.2595922-3-pobrn@protonmail.com> In-Reply-To: <20250225173531.2595922-1-pobrn@protonmail.com> References: <20250225173531.2595922-1-pobrn@protonmail.com> Feedback-ID: 20568564:user:proton X-Pm-Message-ID: 05ebc7f672c0c5d53f5040d859b1ce17e687f0cc MIME-Version: 1.0 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 `std::from_chars()` function from `` to parse the integral log level instead of `strtoul` as it provides an easier to use interface and better type safety. Signed-off-by: Barnabás Pőcze Reviewed-by: Laurent Pinchart Reviewed-by: Jacopo Mondi --- src/libcamera/base/log.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libcamera/base/log.cpp b/src/libcamera/base/log.cpp index 009f6c737..42514de97 100644 --- a/src/libcamera/base/log.cpp +++ b/src/libcamera/base/log.cpp @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -686,12 +687,11 @@ LogSeverity Logger::parseLogLevel(const std::string &level) "FATAL", }; - int severity; + unsigned int severity; if (std::isdigit(level[0])) { - char *endptr; - severity = strtoul(level.c_str(), &endptr, 10); - if (*endptr != '\0' || severity > LogFatal) + auto [end, ec] = std::from_chars(level.data(), level.data() + level.size(), severity); + if (ec != std::errc() || *end != '\0' || severity > LogFatal) severity = LogInvalid; } else { severity = LogInvalid; From patchwork Tue Feb 25 17:35:53 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= X-Patchwork-Id: 22873 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 6AD55BF415 for ; Tue, 25 Feb 2025 17:35:59 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 198956872E; Tue, 25 Feb 2025 18:35:59 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=protonmail.com header.i=@protonmail.com header.b="S0w79wyZ"; dkim-atps=neutral Received: from mail-40134.protonmail.ch (mail-40134.protonmail.ch [185.70.40.134]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 6138E6872E for ; Tue, 25 Feb 2025 18:35:57 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=protonmail.com; s=protonmail3; t=1740504956; x=1740764156; bh=IwldtIui0rLycRdEk/44+P4fn37khm4u5+th8XSb2r4=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: Feedback-ID:From:To:Cc:Date:Subject:Reply-To:Feedback-ID: Message-ID:BIMI-Selector:List-Unsubscribe:List-Unsubscribe-Post; b=S0w79wyZATSE+1/nHb28oTwuHZ4JvmYtggyNhZbU64gJ5TsZhUwlc3YOxZXy4THqp xosF71nsq9CMVvLwueftxDqCArOLBkWGMqDr3xTRyELFCX/8I64wc3/lEu7n/ZDh93 BR34Xj+ETLWgtI5YZmGU/2p2TkwPkvZ109yVKEFVZkSk4RD9ah8HJpGCp6roO20Nck qqcVyXvrQRuQaYwD80TD8kNfq6PhYIEG02A9oDOtYyCaWouAj5AjX4mW1Ihvtj0kB9 T21D4DBUiW8FU7ZwydjeKuCfMNps0Eo7q2WS7TkB6Mq4ONUxUQT/T3kaemAZFMbcCD dp/T7JrF+m2AA== Date: Tue, 25 Feb 2025 17:35:53 +0000 To: libcamera-devel@lists.libcamera.org From: =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= Cc: Laurent Pinchart Subject: [PATCH v4 3/8] libcamera: base: log: Remove `LogMessage::init()` Message-ID: <20250225173531.2595922-4-pobrn@protonmail.com> In-Reply-To: <20250225173531.2595922-1-pobrn@protonmail.com> References: <20250225173531.2595922-1-pobrn@protonmail.com> Feedback-ID: 20568564:user:proton X-Pm-Message-ID: e552bf9c3a6f822c524f8e6efb7c1f98b92fd69a MIME-Version: 1.0 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" It is a short function that can be merged into the constructor with essentially no change in observable behaviour, so do that. Signed-off-by: Barnabás Pőcze Reviewed-by: Laurent Pinchart Reviewed-by: Jacopo Mondi --- include/libcamera/base/log.h | 2 -- src/libcamera/base/log.cpp | 16 ++++------------ 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/include/libcamera/base/log.h b/include/libcamera/base/log.h index b3050eedb..6d2c93019 100644 --- a/include/libcamera/base/log.h +++ b/include/libcamera/base/log.h @@ -75,8 +75,6 @@ public: private: LIBCAMERA_DISABLE_COPY_AND_MOVE(LogMessage) - void init(const char *fileName, unsigned int line); - std::ostringstream msgStream_; const LogCategory &category_; LogSeverity severity_; diff --git a/src/libcamera/base/log.cpp b/src/libcamera/base/log.cpp index 42514de97..a43ed9684 100644 --- a/src/libcamera/base/log.cpp +++ b/src/libcamera/base/log.cpp @@ -861,19 +861,11 @@ const LogCategory &LogCategory::defaultCategory() LogMessage::LogMessage(const char *fileName, unsigned int line, const LogCategory &category, LogSeverity severity, const std::string &prefix) - : category_(category), severity_(severity), prefix_(prefix) + : category_(category), severity_(severity), + timestamp_(utils::clock::now()), + fileInfo_((std::ostringstream() << utils::basename(fileName) << ":" << line).str()), + prefix_(prefix) { - init(fileName, line); -} - -void LogMessage::init(const char *fileName, unsigned int line) -{ - /* Log the timestamp, severity and file information. */ - timestamp_ = utils::clock::now(); - - std::ostringstream ossFileInfo; - ossFileInfo << utils::basename(fileName) << ":" << line; - fileInfo_ = ossFileInfo.str(); } LogMessage::~LogMessage() From patchwork Tue Feb 25 17:35:59 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= X-Patchwork-Id: 22874 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 EED59BF415 for ; Tue, 25 Feb 2025 17:36:04 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id AB53868738; Tue, 25 Feb 2025 18:36:04 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=protonmail.com header.i=@protonmail.com header.b="Op+Aslk9"; dkim-atps=neutral Received: from mail-40131.protonmail.ch (mail-40131.protonmail.ch [185.70.40.131]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id E341468733 for ; Tue, 25 Feb 2025 18:36:03 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=protonmail.com; s=protonmail3; t=1740504963; x=1740764163; bh=/fV1VdETywMya9fkTsil5CAHlq6CajoFW63nglqmDN4=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: Feedback-ID:From:To:Cc:Date:Subject:Reply-To:Feedback-ID: Message-ID:BIMI-Selector:List-Unsubscribe:List-Unsubscribe-Post; b=Op+Aslk9ns2jOMWrq+4o3rKXj5XDFQzELE9g5mMK7/joPBACKYJkjKVolXLK3/l3f P+Ym5a9d4TX9AjnQHSpW4Z/Jr7TvwkFShVf1P9mTauoonBrJ8a7ZOdmOLIGPVfJdnl ABPFmNo8vy+BBLdBZsZG4mp3R5uSTEY8gTCbSP+9LRHei+cgI59C9ufPikyBUZ/JjN yPlk3kSwIVqF9JLyyxu71Qc0wIxs4V5xVTVLGqPmwzsvrBFvQ6gtdeyu+/854Ds+gJ 4DQnOZjwOP4GWExmAlsjYZd9jfdH5vsD8O/0vl6ShTHj7gU/WkoQyDhgq5wvZAM9iY S07KUyHmUkQwQ== Date: Tue, 25 Feb 2025 17:35:59 +0000 To: libcamera-devel@lists.libcamera.org From: =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= Cc: Laurent Pinchart , Jacopo Mondi Subject: [PATCH v4 4/8] libcamera: base: log: Make `LogCategory::severity_` atomic Message-ID: <20250225173531.2595922-5-pobrn@protonmail.com> In-Reply-To: <20250225173531.2595922-1-pobrn@protonmail.com> References: <20250225173531.2595922-1-pobrn@protonmail.com> Feedback-ID: 20568564:user:proton X-Pm-Message-ID: 6bbedb749388dd20e7b118b7c3c0a7063f51f0a6 MIME-Version: 1.0 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 severity of a log category may be changed from a different thread, so it is important to ensure that the reads and writes happen atomically. Using `std::memory_order_relaxed` should not introduce any synchronization overhead, it should only guarantee that the operation itself is atomic. Secondly, inline `LogCategory::setSeverity()`, as it is merely an assignment, so going through a DSO call is a big pessimization. `LogCategory` is not part of the public API, so this change has no external effects. Thirdly, assert that the atomic variable is lock free so as to ensure it won't silently fall back to libatomic (or similar) on any platform. If this assertion fails, this needs to be revisited. Signed-off-by: Barnabás Pőcze Reviewed-by: Laurent Pinchart Reviewed-by: Jacopo Mondi --- include/libcamera/base/log.h | 9 ++++++--- src/libcamera/base/log.cpp | 5 +---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/include/libcamera/base/log.h b/include/libcamera/base/log.h index 6d2c93019..4137d87a4 100644 --- a/include/libcamera/base/log.h +++ b/include/libcamera/base/log.h @@ -7,6 +7,7 @@ #pragma once +#include #include #include @@ -31,8 +32,8 @@ public: static LogCategory *create(const char *name); const std::string &name() const { return name_; } - LogSeverity severity() const { return severity_; } - void setSeverity(LogSeverity severity); + LogSeverity severity() const { return severity_.load(std::memory_order_relaxed); } + void setSeverity(LogSeverity severity) { severity_.store(severity, std::memory_order_relaxed); } static const LogCategory &defaultCategory(); @@ -40,7 +41,9 @@ private: explicit LogCategory(const char *name); const std::string name_; - LogSeverity severity_; + + std::atomic severity_; + static_assert(decltype(severity_)::is_always_lock_free); }; #define LOG_DECLARE_CATEGORY(name) \ diff --git a/src/libcamera/base/log.cpp b/src/libcamera/base/log.cpp index a43ed9684..ce3f04547 100644 --- a/src/libcamera/base/log.cpp +++ b/src/libcamera/base/log.cpp @@ -810,15 +810,12 @@ LogCategory::LogCategory(const char *name) */ /** + * \fn LogCategory::setSeverity(LogSeverity severity) * \brief Set the severity of the log category * * Messages of severity higher than or equal to the severity of the log category * are printed, other messages are discarded. */ -void LogCategory::setSeverity(LogSeverity severity) -{ - severity_ = severity; -} /** * \brief Retrieve the default log category From patchwork Tue Feb 25 17:36:05 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= X-Patchwork-Id: 22875 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 F20CEBDB1C for ; Tue, 25 Feb 2025 17:36:12 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id A931B68737; Tue, 25 Feb 2025 18:36:12 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=protonmail.com header.i=@protonmail.com header.b="cmMJx9cF"; dkim-atps=neutral Received: from mail-40131.protonmail.ch (mail-40131.protonmail.ch [185.70.40.131]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 1EC1C68733 for ; Tue, 25 Feb 2025 18:36:11 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=protonmail.com; s=protonmail3; t=1740504970; x=1740764170; bh=R499hL1Oqw34Nkmesu/RcseK3JOp4A1gHphROydOY7s=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: Feedback-ID:From:To:Cc:Date:Subject:Reply-To:Feedback-ID: Message-ID:BIMI-Selector:List-Unsubscribe:List-Unsubscribe-Post; b=cmMJx9cF27nPMk6xF/UaILEmMIaurD7ilgc7alIMr92ZJNuwUjThW/zDKCJgvOdiY hBIf+N8MRQ8HRIh0vcg4B/NEVsqah8HJNv/PZ/6I3bU5ZVYQfbKL26quKNE3pHTAQ5 sNSXDmXy3goCtnxaALSATmisWN10WJfrSX8tJG1Q4UzfJX2OXKFvzIExxiqng8Aeam 8huZkRt/wsi/HSD5fr0/cBIgXxhLYgFk7UU7FDQQVpzJ1qfNwxB/2bawXL1ejUTLTX wmCIdIxHbyJt+pvfBkKT02yTdN/45PrVcD993kf1GDyvPtmjQpCRFCOkjpRTN2dxfI QIm4NyKuUBphA== Date: Tue, 25 Feb 2025 17:36:05 +0000 To: libcamera-devel@lists.libcamera.org From: =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= Cc: Laurent Pinchart , Jacopo Mondi Subject: [PATCH v4 5/8] libcamera: base: log: Use `std::string_view` to avoid some copies Message-ID: <20250225173531.2595922-6-pobrn@protonmail.com> In-Reply-To: <20250225173531.2595922-1-pobrn@protonmail.com> References: <20250225173531.2595922-1-pobrn@protonmail.com> Feedback-ID: 20568564:user:proton X-Pm-Message-ID: ec2462dbcadd5a661e27f9f9bb53ebc12b3ec1f4 MIME-Version: 1.0 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 `std::string_view` to avoid some largely unnecessary copies, and to make string comparisong potentially faster by eliminating repeated `strlen()` calls. Signed-off-by: Barnabás Pőcze Reviewed-by: Laurent Pinchart Reviewed-by: Jacopo Mondi --- include/libcamera/base/log.h | 5 +++-- src/libcamera/base/log.cpp | 25 +++++++++++++------------ 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/include/libcamera/base/log.h b/include/libcamera/base/log.h index 4137d87a4..acef24203 100644 --- a/include/libcamera/base/log.h +++ b/include/libcamera/base/log.h @@ -9,6 +9,7 @@ #include #include +#include #include @@ -29,7 +30,7 @@ enum LogSeverity { class LogCategory { public: - static LogCategory *create(const char *name); + static LogCategory *create(std::string_view name); const std::string &name() const { return name_; } LogSeverity severity() const { return severity_.load(std::memory_order_relaxed); } @@ -38,7 +39,7 @@ public: static const LogCategory &defaultCategory(); private: - explicit LogCategory(const char *name); + explicit LogCategory(std::string_view name); const std::string name_; diff --git a/src/libcamera/base/log.cpp b/src/libcamera/base/log.cpp index ce3f04547..c0e0be60f 100644 --- a/src/libcamera/base/log.cpp +++ b/src/libcamera/base/log.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -313,11 +314,11 @@ private: void parseLogFile(); void parseLogLevels(); - static LogSeverity parseLogLevel(const std::string &level); + static LogSeverity parseLogLevel(std::string_view level); friend LogCategory; void registerCategory(LogCategory *category); - LogCategory *findCategory(const char *name) const; + LogCategory *findCategory(std::string_view name) const; static bool destroyed_; @@ -642,17 +643,17 @@ void Logger::parseLogLevels() if (!len) continue; - std::string category; - std::string level; + std::string_view category; + std::string_view level; const char *colon = static_cast(memchr(pair, ':', len)); if (!colon) { /* 'x' is a shortcut for '*:x'. */ category = "*"; - level = std::string(pair, len); + level = std::string_view(pair, len); } else { - category = std::string(pair, colon - pair); - level = std::string(colon + 1, comma - colon - 1); + category = std::string_view(pair, colon - pair); + level = std::string_view(colon + 1, comma - colon - 1); } /* Both the category and the level must be specified. */ @@ -663,7 +664,7 @@ void Logger::parseLogLevels() if (severity == LogInvalid) continue; - levels_.push_back({ category, severity }); + levels_.emplace_back(category, severity); } } @@ -677,7 +678,7 @@ void Logger::parseLogLevels() * * \return The log severity, or LogInvalid if the string is invalid */ -LogSeverity Logger::parseLogLevel(const std::string &level) +LogSeverity Logger::parseLogLevel(std::string_view level) { static const char *const names[] = { "DEBUG", @@ -729,7 +730,7 @@ void Logger::registerCategory(LogCategory *category) * \param[in] name Name of the log category * \return The pointer to the found log category or nullptr if not found */ -LogCategory *Logger::findCategory(const char *name) const +LogCategory *Logger::findCategory(std::string_view name) const { if (auto it = std::find_if(categories_.begin(), categories_.end(), [name](auto c) { return c->name() == name; }); @@ -773,7 +774,7 @@ LogCategory *Logger::findCategory(const char *name) const * * \return The pointer to the LogCategory */ -LogCategory *LogCategory::create(const char *name) +LogCategory *LogCategory::create(std::string_view name) { static Mutex mutex_; MutexLocker locker(mutex_); @@ -791,7 +792,7 @@ LogCategory *LogCategory::create(const char *name) * \brief Construct a log category * \param[in] name The category name */ -LogCategory::LogCategory(const char *name) +LogCategory::LogCategory(std::string_view name) : name_(name), severity_(LogSeverity::LogInfo) { } From patchwork Tue Feb 25 17:36:10 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= X-Patchwork-Id: 22876 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 03AAFBDB1C for ; Tue, 25 Feb 2025 17:36:17 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id ABFC868737; Tue, 25 Feb 2025 18:36:16 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=protonmail.com header.i=@protonmail.com header.b="Q3ibdWN+"; dkim-atps=neutral Received: from mail-40134.protonmail.ch (mail-40134.protonmail.ch [185.70.40.134]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id C66A468733 for ; Tue, 25 Feb 2025 18:36:15 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=protonmail.com; s=protonmail3; t=1740504975; x=1740764175; bh=/noqSu4fVaWgCxSoaRAATgwSqN50IgRkfAlKy4jj8y0=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: Feedback-ID:From:To:Cc:Date:Subject:Reply-To:Feedback-ID: Message-ID:BIMI-Selector:List-Unsubscribe:List-Unsubscribe-Post; b=Q3ibdWN+X1mtu6tlwKrUWdwhfFgkmSFXVdKcPZuvbKSkSFVHEyyMuxRH2NKuUokxz 4N3j5hELYKpiw7nun770wX8eRCM7GhWetZhk5VtseQmBFZqjWHRubKJ7tIq+uKUeWD Pjt//4OUBPg6uQzjwvF3ShsIRxXqVKc9+uAqr2nyt8FXB5+K8CA5yU9ikeDFizSEfa efnL4PbM3GDuSHthIAjenVLn0ZA+kQZDwA6ugz+As6iHS1gm6Nw0fqWnEgt7Apn8kX e2Z/QKy4AhKutoNg1ryXC1Gw7Z3714R2p08bjWV83bpNrAQRAox10G0nK5p00TwTIB VpF3cx5TFVoOA== Date: Tue, 25 Feb 2025 17:36:10 +0000 To: libcamera-devel@lists.libcamera.org From: =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= Cc: Laurent Pinchart Subject: [PATCH v4 6/8] libcamera: base: log: Pass dynamic prefix through Message-ID: <20250225173531.2595922-7-pobrn@protonmail.com> In-Reply-To: <20250225173531.2595922-1-pobrn@protonmail.com> References: <20250225173531.2595922-1-pobrn@protonmail.com> Feedback-ID: 20568564:user:proton X-Pm-Message-ID: 7a640fd162f6ea3af5dea77205916449c6e5dabf MIME-Version: 1.0 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 move construction to essentially pass through the string returned by `Loggable::logPrefix()` to avoid an unnecessary copy. Signed-off-by: Barnabás Pőcze Reviewed-by: Laurent Pinchart Reviewed-by: Jacopo Mondi --- include/libcamera/base/log.h | 2 +- src/libcamera/base/log.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/libcamera/base/log.h b/include/libcamera/base/log.h index acef24203..1fb92603f 100644 --- a/include/libcamera/base/log.h +++ b/include/libcamera/base/log.h @@ -64,7 +64,7 @@ class LogMessage public: LogMessage(const char *fileName, unsigned int line, const LogCategory &category, LogSeverity severity, - const std::string &prefix = std::string()); + std::string prefix = {}); ~LogMessage(); std::ostream &stream() { return msgStream_; } diff --git a/src/libcamera/base/log.cpp b/src/libcamera/base/log.cpp index c0e0be60f..6687deb93 100644 --- a/src/libcamera/base/log.cpp +++ b/src/libcamera/base/log.cpp @@ -858,11 +858,11 @@ const LogCategory &LogCategory::defaultCategory() */ LogMessage::LogMessage(const char *fileName, unsigned int line, const LogCategory &category, LogSeverity severity, - const std::string &prefix) + std::string prefix) : category_(category), severity_(severity), timestamp_(utils::clock::now()), fileInfo_((std::ostringstream() << utils::basename(fileName) << ":" << line).str()), - prefix_(prefix) + prefix_(std::move(prefix)) { } From patchwork Tue Feb 25 17:36:16 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= X-Patchwork-Id: 22877 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 4C65DBDB1C for ; Tue, 25 Feb 2025 17:36:25 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 9F4BD6873C; Tue, 25 Feb 2025 18:36:24 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=protonmail.com header.i=@protonmail.com header.b="vlD/o1pp"; dkim-atps=neutral Received: from mail-4316.protonmail.ch (mail-4316.protonmail.ch [185.70.43.16]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id BBBAB686D6 for ; Tue, 25 Feb 2025 18:36:22 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=protonmail.com; s=protonmail3; t=1740504982; x=1740764182; bh=3o/9e0VmUVhmnmrr6PgXseKVF982IpuzpXNd86t5QDw=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: Feedback-ID:From:To:Cc:Date:Subject:Reply-To:Feedback-ID: Message-ID:BIMI-Selector:List-Unsubscribe:List-Unsubscribe-Post; b=vlD/o1pp+McEMLxQ5WuIl1otJLFrCBbrAArAY0s5NY3FXJs6PB/cyyqFEHdsI9IsS 2WlCwHRGe9DO/Rnmw4Nkvtu4uyKyXG9gPqQ1DxXvTmPysRMaeY052j3EIOMeXkEits PoFi9BPHWfvcHH2vODDozDA/FhbPjk6Yfair40qVntD0fwvCru6Ld//83UP+O6j+em 6f1YibYN51vyqfXLLUuckAcaUPkdK+76ZLytmQSyI/CJ8Ub1ST14EjAtL/zgdsjvuN sWCL2IKehZJjYOMGNYEZbxr6Tla4RtopYz0nPv6WV1g4jR43M1iQ3gDtywY7MxBF3+ SMLefFjV0ntHw== Date: Tue, 25 Feb 2025 17:36:16 +0000 To: libcamera-devel@lists.libcamera.org From: =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= Cc: Jacopo Mondi , Laurent Pinchart Subject: [PATCH v4 7/8] libcamera: base: log: Protect log categories with lock Message-ID: <20250225173531.2595922-8-pobrn@protonmail.com> In-Reply-To: <20250225173531.2595922-1-pobrn@protonmail.com> References: <20250225173531.2595922-1-pobrn@protonmail.com> Feedback-ID: 20568564:user:proton X-Pm-Message-ID: 6e7f7f3c8d198df5efde20fe48d732c3cb9c68aa MIME-Version: 1.0 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" Log categories may be added from any thread, so it is important to synchronize access to the `Logger::categories_` list between its two users: category creation (by LogCategory::create(), which calls Logger::findCategory() and Logger::registerCategory()); and log level setting (by Logger::logSetLevel()). The LogCategory::create() function uses a mutex to serialize category creation, but Logger::logSetLevel() can access `Logger::categories_` concurrently without any protection. To fix the issue, move the mutex to the Logger class, and use it to protect all accesses to the categories list. This requires moving all the logic of LogCategory::create() to a new Logger::findOrCreateCategory() function that combines both Logger::findCategory() and Logger::registerCategory() in order to make the two operations exacute atomically. Signed-off-by: Barnabás Pőcze Reviewed-by: Jacopo Mondi Reviewed-by: Laurent Pinchart --- include/libcamera/base/log.h | 1 + src/libcamera/base/log.cpp | 58 +++++++++++++----------------------- 2 files changed, 22 insertions(+), 37 deletions(-) diff --git a/include/libcamera/base/log.h b/include/libcamera/base/log.h index 1fb92603f..8af74b59d 100644 --- a/include/libcamera/base/log.h +++ b/include/libcamera/base/log.h @@ -39,6 +39,7 @@ public: static const LogCategory &defaultCategory(); private: + friend class Logger; explicit LogCategory(std::string_view name); const std::string name_; diff --git a/src/libcamera/base/log.cpp b/src/libcamera/base/log.cpp index 6687deb93..155355f0c 100644 --- a/src/libcamera/base/log.cpp +++ b/src/libcamera/base/log.cpp @@ -317,12 +317,12 @@ private: static LogSeverity parseLogLevel(std::string_view level); friend LogCategory; - void registerCategory(LogCategory *category); - LogCategory *findCategory(std::string_view name) const; + LogCategory *findOrCreateCategory(std::string_view name); static bool destroyed_; - std::vector categories_; + Mutex mutex_; + std::vector categories_ LIBCAMERA_TSA_GUARDED_BY(mutex_); std::list> levels_; std::shared_ptr output_; @@ -572,6 +572,8 @@ void Logger::logSetLevel(const char *category, const char *level) if (severity == LogInvalid) return; + MutexLocker locker(mutex_); + for (LogCategory *c : categories_) { if (c->name() == category) { c->setSeverity(severity); @@ -708,37 +710,28 @@ LogSeverity Logger::parseLogLevel(std::string_view level) } /** - * \brief Register a log category with the logger - * \param[in] category The log category - * - * Log categories must have unique names. It is invalid to call this function - * if a log category with the same name already exists. + * \brief Find an existing log category with the given name or create one + * \param[in] name Name of the log category + * \return The pointer to the log category found or created */ -void Logger::registerCategory(LogCategory *category) +LogCategory *Logger::findOrCreateCategory(std::string_view name) { - categories_.push_back(category); + MutexLocker locker(mutex_); - const std::string &name = category->name(); - for (const auto &[pattern, severity] : levels_) { - if (fnmatch(pattern.c_str(), name.c_str(), FNM_NOESCAPE) == 0) - category->setSeverity(severity); + for (LogCategory *category : categories_) { + if (category->name() == name) + return category; } -} -/** - * \brief Find an existing log category with the given name - * \param[in] name Name of the log category - * \return The pointer to the found log category or nullptr if not found - */ -LogCategory *Logger::findCategory(std::string_view name) const -{ - if (auto it = std::find_if(categories_.begin(), categories_.end(), - [name](auto c) { return c->name() == name; }); - it != categories_.end()) { - return *it; + LogCategory *category = categories_.emplace_back(new LogCategory(name)); + const char *categoryName = category->name().c_str(); + + for (const auto &[pattern, severity] : levels_) { + if (fnmatch(pattern.c_str(), categoryName, FNM_NOESCAPE) == 0) + category->setSeverity(severity); } - return nullptr; + return category; } /** @@ -776,16 +769,7 @@ LogCategory *Logger::findCategory(std::string_view name) const */ LogCategory *LogCategory::create(std::string_view name) { - static Mutex mutex_; - MutexLocker locker(mutex_); - LogCategory *category = Logger::instance()->findCategory(name); - - if (!category) { - category = new LogCategory(name); - Logger::instance()->registerCategory(category); - } - - return category; + return Logger::instance()->findOrCreateCategory(name); } /** From patchwork Tue Feb 25 17:36:22 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= X-Patchwork-Id: 22878 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 E05D5BDB1C for ; Tue, 25 Feb 2025 17:36:29 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 9BEF66873C; Tue, 25 Feb 2025 18:36:29 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=protonmail.com header.i=@protonmail.com header.b="Y5MWTuey"; dkim-atps=neutral Received: from mail-10630.protonmail.ch (mail-10630.protonmail.ch [79.135.106.30]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 3667368725 for ; Tue, 25 Feb 2025 18:36:27 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=protonmail.com; s=protonmail3; t=1740504986; x=1740764186; bh=Ub0xATXAZom6FXNmQZ3DrfsR/hgEl3RCjniWHGgBM7Q=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: Feedback-ID:From:To:Cc:Date:Subject:Reply-To:Feedback-ID: Message-ID:BIMI-Selector:List-Unsubscribe:List-Unsubscribe-Post; b=Y5MWTueyqNKkgW7mEGagWxHvMdfWqZUkv8b1Eqe0fWh9oDlVWL6sxKxk7LtC8R5eM lX8XFyL009rxTxtyltnFtYnwenWTusIN0B1tjjTufa0ynaF07UQ9ZQboKwAAPso5ih ow+Bf+QqvPFJJCn/fXww96J/QuVmKI35w1y8UhutGQv91mb9KTbMuRZS1p8s+KR+cp d5nAWQnv+invpmh7q/ZU4zHcD4NTHdvprURZ/J0Q1Mmf9jjWAwAlR8jhkj4eVyaGd/ 0UbMl2VfFh+fPkjyrwNxkyJxWqlvmGfvzrUPbHsWkkb9yqDb/ZPBl9HAQEsEu2Kymg DWUH3sSME5PDA== Date: Tue, 25 Feb 2025 17:36:22 +0000 To: libcamera-devel@lists.libcamera.org From: =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= Cc: Laurent Pinchart Subject: [PATCH v4 8/8] libcamera: base: log: Avoid manual `LogCategory` deletion Message-ID: <20250225173531.2595922-9-pobrn@protonmail.com> In-Reply-To: <20250225173531.2595922-1-pobrn@protonmail.com> References: <20250225173531.2595922-1-pobrn@protonmail.com> Feedback-ID: 20568564:user:proton X-Pm-Message-ID: 985a84bd74ef8a2b5ae65e0368901862f7a0a068 MIME-Version: 1.0 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" Wrap the `LogCategory` pointers in `std::unique_ptr` to avoid the need for manual deletion in the destructor. Signed-off-by: Barnabás Pőcze Reviewed-by: Laurent Pinchart Reviewed-by: Jacopo Mondi --- src/libcamera/base/log.cpp | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/libcamera/base/log.cpp b/src/libcamera/base/log.cpp index 155355f0c..72614eeb1 100644 --- a/src/libcamera/base/log.cpp +++ b/src/libcamera/base/log.cpp @@ -322,7 +322,7 @@ private: static bool destroyed_; Mutex mutex_; - std::vector categories_ LIBCAMERA_TSA_GUARDED_BY(mutex_); + std::vector> categories_ LIBCAMERA_TSA_GUARDED_BY(mutex_); std::list> levels_; std::shared_ptr output_; @@ -439,9 +439,6 @@ void logSetLevel(const char *category, const char *level) Logger::~Logger() { destroyed_ = true; - - for (LogCategory *category : categories_) - delete category; } /** @@ -574,7 +571,7 @@ void Logger::logSetLevel(const char *category, const char *level) MutexLocker locker(mutex_); - for (LogCategory *c : categories_) { + for (const auto &c : categories_) { if (c->name() == category) { c->setSeverity(severity); break; @@ -718,12 +715,12 @@ LogCategory *Logger::findOrCreateCategory(std::string_view name) { MutexLocker locker(mutex_); - for (LogCategory *category : categories_) { + for (const auto &category : categories_) { if (category->name() == name) - return category; + return category.get(); } - LogCategory *category = categories_.emplace_back(new LogCategory(name)); + LogCategory *category = categories_.emplace_back(std::unique_ptr(new LogCategory(name))).get(); const char *categoryName = category->name().c_str(); for (const auto &[pattern, severity] : levels_) {