From patchwork Fri Feb 8 14:45:39 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 550 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 390B66101F for ; Fri, 8 Feb 2019 15:45:45 +0100 (CET) Received: from pendragon.ideasonboard.com (d51A4137F.access.telenet.be [81.164.19.127]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id B6995F9 for ; Fri, 8 Feb 2019 15:45:44 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1549637144; bh=S7QKr3bt37u0JJIVa6LLliKnTdpxqLDVlTrplif6/Lo=; h=From:To:Subject:Date:From; b=T/0mAGds8QvsN5/QBhuGasHlK6f6M7LK4FZ4beCADiKETIagKpwnCQH5egs55YqrT wnLX9VsUm+gmYDRrar7D4dhLziDJHN0/oRWy4GYoWyfx+JMmTL5I8jHd3QDyHvBdNb RZSDKMILtMP9hWCDAhaE7crKSJFCg81Fo/yGd/QY= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Fri, 8 Feb 2019 16:45:39 +0200 Message-Id: <20190208144540.15529-1-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.19.2 MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 1/2] libcamera: log: Allow extending log messages X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 08 Feb 2019 14:45:45 -0000 Introduce a base Loggable class that can be inherited from by other classes to support adding per-instance information to the log messages. Signed-off-by: Laurent Pinchart Reviewed-by: Niklas Söderlund --- src/libcamera/include/log.h | 23 ++++++- src/libcamera/log.cpp | 124 ++++++++++++++++++++++++++++++++++++ 2 files changed, 145 insertions(+), 2 deletions(-) diff --git a/src/libcamera/include/log.h b/src/libcamera/include/log.h index ad8f8452c333..8ea5a1eb673a 100644 --- a/src/libcamera/include/log.h +++ b/src/libcamera/include/log.h @@ -54,6 +54,7 @@ public: LogMessage(const char *fileName, unsigned int line, const LogCategory &category, LogSeverity severity); LogMessage(const LogMessage &) = delete; + LogMessage(LogMessage &&); ~LogMessage(); std::ostream &stream() { return msgStream_; } @@ -66,13 +67,31 @@ private: LogSeverity severity_; }; +class Loggable +{ +public: + virtual ~Loggable(); + +protected: + virtual std::string logPrefix() const = 0; + + LogMessage _log(const char *file, unsigned int line, + LogSeverity severity); + LogMessage _log(const char *file, unsigned int line, + const LogCategory &category, LogSeverity severity); +}; + +LogMessage _log(const char *file, unsigned int line, LogSeverity severity); +LogMessage _log(const char *file, unsigned int line, + const LogCategory &category, LogSeverity severity); + #ifndef __DOXYGEN__ #define _LOG_CATEGORY(name) logCategory##name #define _LOG1(severity) \ - LogMessage(__FILE__, __LINE__, Log##severity).stream() + _log(__FILE__, __LINE__, Log##severity).stream() #define _LOG2(category, severity) \ - LogMessage(__FILE__, __LINE__, _LOG_CATEGORY(category)(), Log##severity).stream() + _log(__FILE__, __LINE__, _LOG_CATEGORY(category)(), Log##severity).stream() /* * Expand the LOG() macro to _LOG1() or _LOG2() based on the number of diff --git a/src/libcamera/log.cpp b/src/libcamera/log.cpp index edeb5eabb264..26ebf410a7a9 100644 --- a/src/libcamera/log.cpp +++ b/src/libcamera/log.cpp @@ -405,6 +405,25 @@ 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 -1. + */ +LogMessage::LogMessage(LogMessage &&other) + : msgStream_(std::move(other.msgStream_)), category_(other.category_), + severity_(other.severity_) +{ + other.severity_ = static_cast(-1); +} + void LogMessage::init(const char *fileName, unsigned int line) { /* Log the timestamp, severity and file information. */ @@ -424,6 +443,10 @@ void LogMessage::init(const char *fileName, unsigned int line) LogMessage::~LogMessage() { + /* Don't print anything if we have been moved to another LogMessage. */ + if (severity_ == -1) + return; + msgStream_ << std::endl; if (severity_ >= category_.severity()) { @@ -445,6 +468,107 @@ LogMessage::~LogMessage() * \return A reference to the log message stream */ +/** + * \class Loggable + * \brief Base class to support log message extensions + * + * The Loggable class allows classes to extend log messages without any change + * to the way the LOG() macro is invoked. By inheriting from Loggable and + * implementing the logPrefix() virtual method, a class can specify extra + * information to be automatically added to messages logged from class member + * methods. + */ + +Loggable::~Loggable() +{ +} + +/** + * \fn Loggable::logPrefix() + * \brief Retrieve a string to be prefixed to the log message + * + * This method allows classes inheriting from the Loggable class to extend the + * logger with an object-specific prefix output right before the log message + * contents. + * + * \return A string to be prefixed to the log message + */ + +/** + * \brief Create a temporary LogMessage object to log a message + * \param[in] fileName The file name where the message is logged from + * \param[in] line The line number where the message is logged from + * \param[in] severity The log message severity + * + * This method is used as a backeng by the LOG() macro to create a log message + * for locations inheriting from the Loggable class. + * + * \return A log message + */ +LogMessage Loggable::_log(const char *fileName, unsigned int line, + LogSeverity severity) +{ + LogMessage msg(fileName, line, severity); + + msg.stream() << logPrefix() << ": "; + return msg; +} + +/** + * \brief Create a temporary LogMessage object to log a message + * \param[in] fileName The file name where the message is logged from + * \param[in] line The line number where the message is logged from + * \param[in] category The log message category + * \param[in] severity The log message severity + * + * This method is used as a backeng by the LOG() macro to create a log message + * for locations inheriting from the Loggable class. + * + * \return A log message + */ +LogMessage Loggable::_log(const char *fileName, unsigned int line, + const LogCategory &category, LogSeverity severity) +{ + LogMessage msg(fileName, line, category, severity); + + msg.stream() << logPrefix() << ": "; + return msg; +} + +/** + * \brief Create a temporary LogMessage object to log a message + * \param[in] fileName The file name where the message is logged from + * \param[in] line The line number where the message is logged from + * \param[in] severity The log message severity + * + * This function is used as a backeng by the LOG() macro to create a log + * message for locations not inheriting from the Loggable class. + * + * \return A log message + */ +LogMessage _log(const char *fileName, unsigned int line, LogSeverity severity) +{ + return LogMessage(fileName, line, severity); +} + +/** + * \brief Create a temporary LogMessage object to log a message + * \param[in] fileName The file name where the message is logged from + * \param[in] line The line number where the message is logged from + * \param[in] category The log message category + * \param[in] severity The log message severity + * + * This function is used as a backeng by the LOG() macro to create a log + * message for locations not inheriting from the Loggable class. + * + * \return A log message + */ +LogMessage _log(const char *fileName, unsigned int line, + const LogCategory &category, LogSeverity severity) +{ + return LogMessage(fileName, line, category, severity); +} + /** * \def LOG_DECLARE_CATEGORY(name) * \hideinitializer