From patchwork Tue Jan 21 18:50:52 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: 22602 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 0999DC330F for ; Tue, 21 Jan 2025 18:50:59 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id A87406855B; Tue, 21 Jan 2025 19:50:58 +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="BNf3LcRm"; dkim-atps=neutral Received: from mail-4322.protonmail.ch (mail-4322.protonmail.ch [185.70.43.22]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 5571C60380 for ; Tue, 21 Jan 2025 19:50:57 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=protonmail.com; s=protonmail3; t=1737485456; x=1737744656; bh=5i8jlI0r5scu2yXPeGcWMDWPcNk23fMJN2hE4FT/2nc=; h=Date:To:From: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=BNf3LcRmo+DgmkY4HvADX83nvZUqSTNY41F6jOiThxgNXSxv383yAqkdGFzoBU4VP jfUQqmqnSt+8yzeX1rAlEYgpGzxXlEOkFHq9ZMi2b4k4AbB1BRq+1Hj4/QGR/cEO6x D7pmf/8inSLMASfEjFAoo4xdarWmi2oye7/j9GixKLnU5ltjTQOKd+YMuaU+SLpEpz V7E45junt+W2CH3GW9FESTyke0iZvVt/XEy1mtcrRWbYFygPD7Ku3Yf+5qrI98ebzS +UPYFBcspvwsfZOyjEY1gPo+U7Wr6erFt0esZrw4KqTA2DEjQgZFdg8f3JzA1vPIHb 10G5bwpb3itwQ== Date: Tue, 21 Jan 2025 18:50:52 +0000 To: libcamera-devel@lists.libcamera.org From: =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= Subject: [RFC PATCH v1 1/7] libcamera: base: log: Move all fields of `LogMessage` Message-ID: <20250121185044.300816-2-pobrn@protonmail.com> In-Reply-To: <20250121185044.300816-1-pobrn@protonmail.com> References: <20250121185044.300816-1-pobrn@protonmail.com> Feedback-ID: 20568564:user:proton X-Pm-Message-ID: 4b6c4e5ec3332e831eb0b7276d6d7b773a1fbcb7 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" Move all fields of `LogMessage` in the move constructor. Signed-off-by: Barnabás Pőcze --- src/libcamera/base/log.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/libcamera/base/log.cpp b/src/libcamera/base/log.cpp index 3a656b8f0..61a43d525 100644 --- a/src/libcamera/base/log.cpp +++ b/src/libcamera/base/log.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include @@ -894,9 +895,10 @@ LogMessage::LogMessage(const char *fileName, unsigned int line, */ LogMessage::LogMessage(LogMessage &&other) : msgStream_(std::move(other.msgStream_)), category_(other.category_), - severity_(other.severity_) + severity_(std::exchange(other.severity_, LogInvalid)), + timestamp_(other.timestamp_), fileInfo_(std::move(other.fileInfo_)), + prefix_(std::move(other.prefix_)) { - other.severity_ = LogInvalid; } void LogMessage::init(const char *fileName, unsigned int line) From patchwork Tue Jan 21 18:50:58 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: 22603 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 ED7A4BD16B for ; Tue, 21 Jan 2025 18:51:03 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id B3F836855D; Tue, 21 Jan 2025 19:51:03 +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="DR5nmybS"; dkim-atps=neutral Received: from mail-4322.protonmail.ch (mail-4322.protonmail.ch [185.70.43.22]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 6F9FD60380 for ; Tue, 21 Jan 2025 19:51:02 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=protonmail.com; s=protonmail3; t=1737485461; x=1737744661; bh=pzEZ4IbBHAq23BnuKGlTxXSMQlmVd18qIypC2hErXjI=; h=Date:To:From: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=DR5nmybSCJq70EKEuhtRksOvSB/U02N8s0x3Lo8bm/jrjsHdHRb5YrpOzeKdQ2Igm Aw4JoNX/Akxj/AcFnfkyHE0G+bXcu8/L76DZQ+8Ezobob5i76HGCumZ5bFp/d/Ffep P0zoYAtl4cSHrwJChF8qmAeEY7t1kF2WEnknQSvba+1ZkfOVdUdFpBuqJ4KOLVAVCe PJgZdrOg2xwSaluOr217Cz45O5DXvPKFqlCBKnu6mYmG1x9fs1KcX7vtoaPNtuDZzW fYVpLBZ+3XdVPBheBoXjyLgmwPTTe0tMbZ+PDM0OjRytWLq3MRmvySXxviTqA1CmlN OCwFmEGbAzQbA== Date: Tue, 21 Jan 2025 18:50:58 +0000 To: libcamera-devel@lists.libcamera.org From: =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= Subject: [RFC PATCH v1 2/7] libcamera: base: log: Use `std::from_chars()` Message-ID: <20250121185044.300816-3-pobrn@protonmail.com> In-Reply-To: <20250121185044.300816-1-pobrn@protonmail.com> References: <20250121185044.300816-1-pobrn@protonmail.com> Feedback-ID: 20568564:user:proton X-Pm-Message-ID: 6031d72237e92d7b78308b19f636b7f4ce7ea943 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 --- 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 61a43d525..1024fed7f 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, 10); + if (ec != std::errc() || *end != '\0' || severity > LogFatal) severity = LogInvalid; } else { severity = LogInvalid; From patchwork Tue Jan 21 18:55:56 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: 22604 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 8D3B5BD160 for ; Tue, 21 Jan 2025 18:56:07 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id B3B0A68503; Tue, 21 Jan 2025 19:56:06 +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="TJxPIzIa"; 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 0DD1860380 for ; Tue, 21 Jan 2025 19:56:04 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=protonmail.com; s=protonmail3; t=1737485763; x=1737744963; bh=inYsCoT9BMm1Qo17lhRjtpTS9yz04iQOJCGsmUDqf+g=; h=Date:To:From:Subject:Message-ID:Feedback-ID:From:To:Cc:Date: Subject:Reply-To:Feedback-ID:Message-ID:BIMI-Selector: List-Unsubscribe:List-Unsubscribe-Post; b=TJxPIzIa5w5578ZByJWJ34edO5Oai6TQtSZINB3/frn4X6pvNHbhQrd8xQ/PtDjJn MmT/7lFzmr9+pHVBHsdj5CqlCBBjHrr6ik0aBuNfjSAuCgDm7Z3ddVn8uSetQcJRZX WIOmuDNrcroOaz0OqR9XU2cm7gHBa1+Hn3AMHKNO/j14V9uez0r2SCHyqXLB4gbW5I AH90vqpf/buocljFlO7W51TE3Y2UopZasFVCB9ihSV658M2E9fqKQ+gcn3U+Jz2wI/ Z0hQ9TbDp6pgvko9fRHavuDR5gGJGBEoXJiWU0J8EmLW7q5IGQSg69LRknBrvggTrf 46xNPmvG3wRCQ== Date: Tue, 21 Jan 2025 18:55:56 +0000 To: libcamera-devel@lists.libcamera.org From: =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= Subject: [RFC PATCH v1 3/7] libcamera: base: log: Remove `LogMessage::init()` Message-ID: <20250121185554.301901-1-pobrn@protonmail.com> Feedback-ID: 20568564:user:proton X-Pm-Message-ID: d93e837d6a92c0de7f7a3d770ff826e6bece2bf7 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 --- include/libcamera/base/log.h | 2 -- src/libcamera/base/log.cpp | 17 +++++------------ 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/include/libcamera/base/log.h b/include/libcamera/base/log.h index 620930125..d73aa7913 100644 --- a/include/libcamera/base/log.h +++ b/include/libcamera/base/log.h @@ -77,8 +77,6 @@ public: private: LIBCAMERA_DISABLE_COPY(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 1024fed7f..1513e41fb 100644 --- a/src/libcamera/base/log.cpp +++ b/src/libcamera/base/log.cpp @@ -876,9 +876,12 @@ 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()), prefix_(prefix) { - init(fileName, line); + std::ostringstream ossFileInfo; + ossFileInfo << utils::basename(fileName) << ":" << line; + fileInfo_ = std::move(ossFileInfo).str(); } /** @@ -901,16 +904,6 @@ LogMessage::LogMessage(LogMessage &&other) { } -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() { /* Don't print anything if we have been moved to another LogMessage. */ From patchwork Tue Jan 21 18:56:02 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: 22605 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 75D21BD160 for ; Tue, 21 Jan 2025 18:56:09 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 5647A68558; Tue, 21 Jan 2025 19:56:08 +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="YSnCQg9i"; 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 C92EC68558 for ; Tue, 21 Jan 2025 19:56:06 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=protonmail.com; s=protonmail3; t=1737485766; x=1737744966; bh=hzCptBc18jSwK9BKJSVcLKAPe5QgqQtTZu6w4EUwioQ=; h=Date:To:From: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=YSnCQg9igKZedVZ6oyDV4uUECKwj0MN5szgr1L07WvmMX05Xpvfb8xj32hfxWbmcm hh65FWlVFsvmcJejGmcDniLJZwb2dGEHH0jaNhEUbdlEwZGVCD72kqY5nEVEJNZt+H R0MUPuNLtMMzieJACLfyy3u9GADVTysa+Ocnucb0jl919zsyd4e1OUtqiXoa2WUlGd xFtVLaX63i2/HesdGJW6u5h1DpL3OzEhXRgbB1QNVBOXlRi7bDRPgyDlQ50Ar1ZgHg wdcmTFqWdO5yagsuKk0ulmz5+oyjCW6x/hBrKuw6fPbGX3dYh9CW8OVCUvU985G4qR NB4gH262gXE9Q== Date: Tue, 21 Jan 2025 18:56:02 +0000 To: libcamera-devel@lists.libcamera.org From: =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= Subject: [RFC PATCH v1 4/7] libcamera: base: log: Make `LogCategory::severity_` atomic Message-ID: <20250121185554.301901-2-pobrn@protonmail.com> In-Reply-To: <20250121185554.301901-1-pobrn@protonmail.com> References: <20250121185554.301901-1-pobrn@protonmail.com> Feedback-ID: 20568564:user:proton X-Pm-Message-ID: 93197c02f271ba111e67183bf004394f13cd0377 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 --- 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 d73aa7913..89f707e54 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 1513e41fb..795260b0a 100644 --- a/src/libcamera/base/log.cpp +++ b/src/libcamera/base/log.cpp @@ -825,15 +825,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 Jan 21 18:56:07 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: 22606 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 071F1BD160 for ; Tue, 21 Jan 2025 18:56:13 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id A78D868551; Tue, 21 Jan 2025 19:56:13 +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="rrxkpaBB"; 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 4C97D68503 for ; Tue, 21 Jan 2025 19:56:12 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=protonmail.com; s=protonmail3; t=1737485771; x=1737744971; bh=mT1gGibnHhvJaaZgc3Zmplug3lJwxIgsUTRvF+/Boxk=; h=Date:To:From: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=rrxkpaBB64WzVfCki3vnMVvjp5RBk6i8TERJEsToVO8JCY5q7LR5fXmUG8tocOZsl inahsLuk8yDdXkQyAd3qOrlOY3WxUWaAy6bawBQLy/uJ8V9bdlaGOXCnGIDzecJnUf NefYaZ43ORnK7K0gZT3F5aYSotHpdmNCDMDQCbKMAJT7RF8iRwa/Opn036skXaKl4t zpSUOR10jxkPtw6kTm7WfDep3BpdHWvNCMUjRSMXcRUUO5SNGutg5aMJEsWVZ6LZKY Bstgvg8cXw44rMsVyCrwuE6708nOD4q72w7qim7GI/PS6ll0TlAD1LXEaa2ikWVZsX gLYpK9cyeX3Rw== Date: Tue, 21 Jan 2025 18:56:07 +0000 To: libcamera-devel@lists.libcamera.org From: =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= Subject: [RFC PATCH v1 5/7] libcamera: base: log: Use `std::string_view` to avoid some copies Message-ID: <20250121185554.301901-3-pobrn@protonmail.com> In-Reply-To: <20250121185554.301901-1-pobrn@protonmail.com> References: <20250121185554.301901-1-pobrn@protonmail.com> Feedback-ID: 20568564:user:proton X-Pm-Message-ID: bfaf80448bcf3490e3d3578c10a70c849ee035ea 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 --- 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 89f707e54..9c7775660 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 795260b0a..78db4990c 100644 --- a/src/libcamera/base/log.cpp +++ b/src/libcamera/base/log.cpp @@ -15,6 +15,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", @@ -744,7 +745,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; }); @@ -788,7 +789,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_); @@ -806,7 +807,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 Jan 21 18:56:11 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: 22607 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 6DFB7BD160 for ; Tue, 21 Jan 2025 18:56:17 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 2EDA56855C; Tue, 21 Jan 2025 19:56:17 +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="kjsVaL0v"; 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 1D3D468503 for ; Tue, 21 Jan 2025 19:56:16 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=protonmail.com; s=protonmail3; t=1737485775; x=1737744975; bh=cBhOGid0r8VciX/qWugH9YEsNhr4QLNKHtT5Z78Y72c=; h=Date:To:From: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=kjsVaL0vvMbGosX9EdQPsmozdEVHXAwJ9I2f+taJqY23s40yj9PTAXU5fq5Kee6LB bB/8kKEYIcS9EStWg4WPQHVDLIQZUOb54G1Xm5MAHeSGW1Z4v70slCObrzMXX5Iqfz KzDkG8Op9+/i8KtlZ1VfPiQCwTwvh+W/mnodZxOWg91VQLwDVgvKp58k+epHRzK19L Ehv12h4YW4bzSEHWqBPo9jqu11X4C/VylL0g1nritZuHN45lKPqXNKe0dVtyomYYuM kZ5HGIC1r8wSc/xcKFX+kkYTYHznpuAC1LEeAJTSk0A4rFOIUmFitNrrP6BvfG6ls0 zyYec02InricA== Date: Tue, 21 Jan 2025 18:56:11 +0000 To: libcamera-devel@lists.libcamera.org From: =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= Subject: [RFC PATCH v1 6/7] libcamera: base: log: Pass dynamic prefix through Message-ID: <20250121185554.301901-4-pobrn@protonmail.com> In-Reply-To: <20250121185554.301901-1-pobrn@protonmail.com> References: <20250121185554.301901-1-pobrn@protonmail.com> Feedback-ID: 20568564:user:proton X-Pm-Message-ID: b87d09b4fbb4ab77f22944f33f63bc361d8a487e 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 --- 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 9c7775660..ef161bece 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(LogMessage &&); ~LogMessage(); diff --git a/src/libcamera/base/log.cpp b/src/libcamera/base/log.cpp index 78db4990c..6430650ec 100644 --- a/src/libcamera/base/log.cpp +++ b/src/libcamera/base/log.cpp @@ -873,9 +873,9 @@ 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()), prefix_(prefix) + timestamp_(utils::clock::now()), prefix_(std::move(prefix)) { std::ostringstream ossFileInfo; ossFileInfo << utils::basename(fileName) << ":" << line; From patchwork Tue Jan 21 18:56: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: 22608 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 6008CBD160 for ; Tue, 21 Jan 2025 18:56:22 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 15A296855F; Tue, 21 Jan 2025 19:56:22 +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="OSDu8I1X"; dkim-atps=neutral Received: from mail-10631.protonmail.ch (mail-10631.protonmail.ch [79.135.106.31]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id DD38E68503 for ; Tue, 21 Jan 2025 19:56:19 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=protonmail.com; s=protonmail3; t=1737485778; x=1737744978; bh=tRnrGPXV3ZBCOP1M93HbbxpJB+M8In0TCeEHyNnuqxY=; h=Date:To:From: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=OSDu8I1XvLIeLBX62JZqEqk1JbNgTW571uKp/tHYyNVNDdmuq03+RBR+8RdovdJPt hfx4Is7+ov8kFnHIPFQYtOUVSIW4smEDll5hNhQo12w+paimK7aH9xOpY40ZuRRJuw gQUzOtZvFHIvnEcRnAnRhG8jPrsvOX/5OJEMTNbO5/BAcMRJ8nwD+QIL9PNENHjp5m M9BIY3Usme9Qvnr8tX/4Z/FFJERw1uKs1/9Z9O0AcKgXv7x116W4aVhtB0oUcuAGXc DfIMB+WIIxOclEmNe7tJbhU7Ib636/8jOgKFGlAjDPvyY35FLTDtwsN6tH+o9AbL1N SSEF65XvrYguQ== Date: Tue, 21 Jan 2025 18:56:16 +0000 To: libcamera-devel@lists.libcamera.org From: =?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= Subject: [RFC PATCH v1 7/7] libcamera: base: log: Protect log categories with lock Message-ID: <20250121185554.301901-5-pobrn@protonmail.com> In-Reply-To: <20250121185554.301901-1-pobrn@protonmail.com> References: <20250121185554.301901-1-pobrn@protonmail.com> Feedback-ID: 20568564:user:proton X-Pm-Message-ID: d984294653f07e4422d50e9cbdd1b3e756226cbc 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: `Logger::findOrCreateCategory()` and `Logger::logSetLevel()`. To achieve that, `Logger::{find,register}Category()` are merged into a single function: `Logger::findOrCreateCategory()`; and the mutex from `LogCategory::create()` is moved into the `Logger` class. Furthermore, appropriate `MutexLocker`s are placed in `Logger::findOrCreateCategory()` and `Logger::logSetLevel()`. Signed-off-by: Barnabás Pőcze --- include/libcamera/base/log.h | 2 +- src/libcamera/base/log.cpp | 235 ++++++++++++++++------------------- 2 files changed, 110 insertions(+), 127 deletions(-) diff --git a/include/libcamera/base/log.h b/include/libcamera/base/log.h index ef161bece..58e873fa9 100644 --- a/include/libcamera/base/log.h +++ b/include/libcamera/base/log.h @@ -30,6 +30,7 @@ enum LogSeverity { class LogCategory { public: + explicit LogCategory(std::string_view name); static LogCategory *create(std::string_view name); const std::string &name() const { return name_; } @@ -39,7 +40,6 @@ public: static const LogCategory &defaultCategory(); private: - 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 6430650ec..d2de5a80e 100644 --- a/src/libcamera/base/log.cpp +++ b/src/libcamera/base/log.cpp @@ -66,7 +66,9 @@ namespace libcamera { -static int log_severity_to_syslog(LogSeverity severity) +namespace { + +int log_severity_to_syslog(LogSeverity severity) { switch (severity) { case LogDebug: @@ -84,7 +86,7 @@ static int log_severity_to_syslog(LogSeverity severity) } } -static const char *log_severity_name(LogSeverity severity) +const char *log_severity_name(LogSeverity severity) { static const char *const names[] = { "DEBUG", @@ -100,6 +102,92 @@ static const char *log_severity_name(LogSeverity severity) return "UNKWN"; } +/** + * \brief Parse a log level string into a LogSeverity + * \param[in] level The log level string + * + * Log levels can be specified as an integer value in the range from LogDebug to + * LogFatal, or as a string corresponding to the severity name in uppercase. Any + * other value is invalid. + * + * \return The log severity, or LogInvalid if the string is invalid + */ +LogSeverity parseLogLevel(std::string_view level) +{ + static const char *const names[] = { + "DEBUG", + "INFO", + "WARN", + "ERROR", + "FATAL", + }; + + unsigned int severity; + + if (std::isdigit(level[0])) { + auto [end, ec] = std::from_chars(level.data(), level.data() + level.size(), severity, 10); + if (ec != std::errc() || *end != '\0' || severity > LogFatal) + severity = LogInvalid; + } else { + severity = LogInvalid; + for (unsigned int i = 0; i < std::size(names); ++i) { + if (names[i] == level) { + severity = i; + break; + } + } + } + + return static_cast(severity); +} + +/** + * \brief Parse the log levels from the environment + * + * The log levels are stored in the LIBCAMERA_LOG_LEVELS environment variable + * as a list of "category:level" pairs, separated by commas (','). Parse the + * variable and store the levels to configure all log categories. + */ +void parseLogLevels(const char *line, std::list> &levels) +{ + for (const char *pair = line; *line != '\0'; pair = line) { + const char *comma = strchrnul(line, ','); + size_t len = comma - pair; + + /* Skip over the comma. */ + line = *comma == ',' ? comma + 1 : comma; + + /* Skip to the next pair if the pair is empty. */ + if (!len) + continue; + + 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_view(pair, len); + } else { + 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. */ + if (category.empty() || level.empty()) + continue; + + LogSeverity severity = parseLogLevel(level); + if (severity == LogInvalid) + continue; + + levels.emplace_back(category, severity); + } +} + +} /* namespace */ + /** * \brief Log output * @@ -313,15 +401,13 @@ private: Logger(); void parseLogFile(); - void parseLogLevels(); - 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_; + Mutex mutex_; std::vector categories_; std::list> levels_; @@ -572,6 +658,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); @@ -593,7 +681,9 @@ Logger::Logger() logSetStream(&std::cerr, color); parseLogFile(); - parseLogLevels(); + + if (const char *debug = utils::secure_getenv("LIBCAMERA_LOG_LEVELS")) + parseLogLevels(debug, levels_); } /** @@ -620,105 +710,21 @@ void Logger::parseLogFile() } /** - * \brief Parse the log levels from the environment - * - * The log levels are stored in the LIBCAMERA_LOG_LEVELS environment variable - * as a list of "category:level" pairs, separated by commas (','). Parse the - * variable and store the levels to configure all log categories. - */ -void Logger::parseLogLevels() -{ - const char *debug = utils::secure_getenv("LIBCAMERA_LOG_LEVELS"); - if (!debug) - return; - - for (const char *pair = debug; *debug != '\0'; pair = debug) { - const char *comma = strchrnul(debug, ','); - size_t len = comma - pair; - - /* Skip over the comma. */ - debug = *comma == ',' ? comma + 1 : comma; - - /* Skip to the next pair if the pair is empty. */ - if (!len) - continue; - - 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_view(pair, len); - } else { - 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. */ - if (category.empty() || level.empty()) - continue; - - LogSeverity severity = parseLogLevel(level); - if (severity == LogInvalid) - continue; - - levels_.emplace_back(category, severity); - } -} - -/** - * \brief Parse a log level string into a LogSeverity - * \param[in] level The log level string - * - * Log levels can be specified as an integer value in the range from LogDebug to - * LogFatal, or as a string corresponding to the severity name in uppercase. Any - * other value is invalid. - * - * \return The log severity, or LogInvalid if the string is invalid + * \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 */ -LogSeverity Logger::parseLogLevel(std::string_view level) +LogCategory *Logger::findOrCreateCategory(std::string_view name) { - static const char *const names[] = { - "DEBUG", - "INFO", - "WARN", - "ERROR", - "FATAL", - }; - - unsigned int severity; + MutexLocker locker(mutex_); - if (std::isdigit(level[0])) { - auto [end, ec] = std::from_chars(level.data(), level.data() + level.size(), severity, 10); - if (ec != std::errc() || *end != '\0' || severity > LogFatal) - severity = LogInvalid; - } else { - severity = LogInvalid; - for (unsigned int i = 0; i < std::size(names); ++i) { - if (names[i] == level) { - severity = i; - break; - } - } + for (LogCategory *c : categories_) { + if (c->name() == name) + return c; } - return static_cast(severity); -} - -/** - * \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. - */ -void Logger::registerCategory(LogCategory *category) -{ - categories_.push_back(category); + LogCategory *c = categories_.emplace_back(new LogCategory(name)); - const std::string &name = category->name(); for (const std::pair &level : levels_) { bool match = true; @@ -734,26 +740,12 @@ void Logger::registerCategory(LogCategory *category) } if (match) { - category->setSeverity(level.second); + c->setSeverity(level.second); break; } } -} -/** - * \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; - } - - return nullptr; + return c; } /** @@ -791,16 +783,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); } /**