Store logging streams in a manually linked list instead of std::list

LogMessage::streams_ is a global and thus should have trivial destructor

Bug: None
Change-Id: Ie6a8029602f50b2bc5bab546ffc0365ef0954024
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/157042
Commit-Queue: Danil Chapovalov <danilchap@webrtc.org>
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#29552}
This commit is contained in:
Danil Chapovalov 2019-10-21 09:19:10 +02:00 committed by Commit Bot
parent 82a3f0ad7f
commit b9f69028a0
5 changed files with 37 additions and 31 deletions

View file

@ -12,6 +12,7 @@
#include <algorithm> #include <algorithm>
#include <cstring> #include <cstring>
#include <list>
#include <memory> #include <memory>
#include <numeric> #include <numeric>

View file

@ -14,6 +14,7 @@
#include <initguid.h> #include <initguid.h>
#include <algorithm> #include <algorithm>
#include <list>
#include "rtc_base/arraysize.h" #include "rtc_base/arraysize.h"
#include "rtc_base/checks.h" #include "rtc_base/checks.h"

View file

@ -93,7 +93,8 @@ bool LogMessage::log_to_stderr_ = true;
// Note: we explicitly do not clean this up, because of the uncertain ordering // Note: we explicitly do not clean this up, because of the uncertain ordering
// of destructors at program exit. Let the person who sets the stream trigger // of destructors at program exit. Let the person who sets the stream trigger
// cleanup by setting to null, or let it leak (safe at program exit). // cleanup by setting to null, or let it leak (safe at program exit).
LogMessage::StreamList LogMessage::streams_ RTC_GUARDED_BY(g_log_crit); ABSL_CONST_INIT LogSink* LogMessage::streams_ RTC_GUARDED_BY(g_log_crit) =
nullptr;
// Boolean options default to false (0) // Boolean options default to false (0)
bool LogMessage::thread_, LogMessage::timestamp_; bool LogMessage::thread_, LogMessage::timestamp_;
@ -201,12 +202,12 @@ LogMessage::~LogMessage() {
} }
GlobalLockScope cs(&g_log_crit); GlobalLockScope cs(&g_log_crit);
for (auto& kv : streams_) { for (LogSink* entry = streams_; entry != nullptr; entry = entry->next_) {
if (severity_ >= kv.second) { if (severity_ >= entry->min_severity_) {
#if defined(WEBRTC_ANDROID) #if defined(WEBRTC_ANDROID)
kv.first->OnLogMessage(str, severity_, tag_); entry->OnLogMessage(str, severity_, tag_);
#else #else
kv.first->OnLogMessage(str, severity_); entry->OnLogMessage(str, severity_);
#endif #endif
} }
} }
@ -260,9 +261,9 @@ void LogMessage::SetLogToStderr(bool log_to_stderr) {
int LogMessage::GetLogToStream(LogSink* stream) { int LogMessage::GetLogToStream(LogSink* stream) {
GlobalLockScope cs(&g_log_crit); GlobalLockScope cs(&g_log_crit);
LoggingSeverity sev = LS_NONE; LoggingSeverity sev = LS_NONE;
for (auto& kv : streams_) { for (LogSink* entry = streams_; entry != nullptr; entry = entry->next_) {
if (!stream || stream == kv.first) { if (stream == nullptr || stream == entry) {
sev = std::min(sev, kv.second); sev = std::min(sev, entry->min_severity_);
} }
} }
return sev; return sev;
@ -270,15 +271,18 @@ int LogMessage::GetLogToStream(LogSink* stream) {
void LogMessage::AddLogToStream(LogSink* stream, LoggingSeverity min_sev) { void LogMessage::AddLogToStream(LogSink* stream, LoggingSeverity min_sev) {
GlobalLockScope cs(&g_log_crit); GlobalLockScope cs(&g_log_crit);
streams_.push_back(std::make_pair(stream, min_sev)); stream->min_severity_ = min_sev;
stream->next_ = streams_;
streams_ = stream;
UpdateMinLogSeverity(); UpdateMinLogSeverity();
} }
void LogMessage::RemoveLogToStream(LogSink* stream) { void LogMessage::RemoveLogToStream(LogSink* stream) {
GlobalLockScope cs(&g_log_crit); GlobalLockScope cs(&g_log_crit);
for (StreamList::iterator it = streams_.begin(); it != streams_.end(); ++it) { for (LogSink** entry = &streams_; *entry != nullptr;
if (stream == it->first) { entry = &(*entry)->next_) {
streams_.erase(it); if (*entry == stream) {
*entry = (*entry)->next_;
break; break;
} }
} }
@ -337,9 +341,8 @@ void LogMessage::ConfigureLogging(const char* params) {
void LogMessage::UpdateMinLogSeverity() void LogMessage::UpdateMinLogSeverity()
RTC_EXCLUSIVE_LOCKS_REQUIRED(g_log_crit) { RTC_EXCLUSIVE_LOCKS_REQUIRED(g_log_crit) {
LoggingSeverity min_sev = g_dbg_sev; LoggingSeverity min_sev = g_dbg_sev;
for (const auto& kv : streams_) { for (LogSink* entry = streams_; entry != nullptr; entry = entry->next_) {
const LoggingSeverity sev = kv.second; min_sev = std::min(min_sev, entry->min_severity_);
min_sev = std::min(min_sev, sev);
} }
g_min_sev = min_sev; g_min_sev = min_sev;
} }
@ -445,10 +448,7 @@ bool LogMessage::IsNoop(LoggingSeverity severity) {
// is going to be logged. This introduces unnecessary synchronization for // is going to be logged. This introduces unnecessary synchronization for
// a feature that's mostly used for testing. // a feature that's mostly used for testing.
GlobalLockScope cs(&g_log_crit); GlobalLockScope cs(&g_log_crit);
if (streams_.size() > 0) return streams_ == nullptr;
return false;
return true;
} }
void LogMessage::FinishPrintStream() { void LogMessage::FinishPrintStream() {

View file

@ -46,7 +46,6 @@
#include <errno.h> #include <errno.h>
#include <list>
#include <sstream> // no-presubmit-check TODO(webrtc:8982) #include <sstream> // no-presubmit-check TODO(webrtc:8982)
#include <string> #include <string>
#include <utility> #include <utility>
@ -99,6 +98,7 @@ enum LogErrorContext {
ERRCTX_HR = ERRCTX_HRESULT, // LOG_E(sev, HR, x) ERRCTX_HR = ERRCTX_HRESULT, // LOG_E(sev, HR, x)
}; };
class LogMessage;
// Virtual sink interface that can receive log messages. // Virtual sink interface that can receive log messages.
class LogSink { class LogSink {
public: public:
@ -110,6 +110,12 @@ class LogSink {
virtual void OnLogMessage(const std::string& message, virtual void OnLogMessage(const std::string& message,
LoggingSeverity severity); LoggingSeverity severity);
virtual void OnLogMessage(const std::string& message) = 0; virtual void OnLogMessage(const std::string& message) = 0;
private:
friend class ::rtc::LogMessage;
// Members for LogMessage class to keep linked list of the registered sinks.
LogSink* next_ = nullptr;
LoggingSeverity min_severity_;
}; };
namespace webrtc_logging_impl { namespace webrtc_logging_impl {
@ -437,16 +443,15 @@ class LogMessage {
// Sets whether logs will be directed to stderr in debug mode. // Sets whether logs will be directed to stderr in debug mode.
static void SetLogToStderr(bool log_to_stderr); static void SetLogToStderr(bool log_to_stderr);
// Stream: Any non-blocking stream interface. LogMessage takes ownership of // Stream: Any non-blocking stream interface.
// the stream. Multiple streams may be specified by using AddLogToStream. // Installs the |stream| to collect logs with severtiy |min_sev| or higher.
// LogToStream is retained for backwards compatibility; when invoked, it // |stream| must live until deinstalled by RemoveLogToStream
// will discard any previously set streams and install the specified stream.
// GetLogToStream gets the severity for the specified stream, of if none
// is specified, the minimum stream severity.
// RemoveLogToStream removes the specified stream, without destroying it.
static int GetLogToStream(LogSink* stream = nullptr);
static void AddLogToStream(LogSink* stream, LoggingSeverity min_sev); static void AddLogToStream(LogSink* stream, LoggingSeverity min_sev);
// Removes the specified stream, without destroying it.
static void RemoveLogToStream(LogSink* stream); static void RemoveLogToStream(LogSink* stream);
// Returns the severity for the specified stream, of if none is specified,
// the minimum stream severity.
static int GetLogToStream(LogSink* stream = nullptr);
// Testing against MinLogSeverity allows code to avoid potentially expensive // Testing against MinLogSeverity allows code to avoid potentially expensive
// logging operations by pre-checking the logging level. // logging operations by pre-checking the logging level.
@ -464,8 +469,6 @@ class LogMessage {
private: private:
friend class LogMessageForTesting; friend class LogMessageForTesting;
typedef std::pair<LogSink*, LoggingSeverity> StreamAndSeverity;
typedef std::list<StreamAndSeverity> StreamList;
// Updates min_sev_ appropriately when debug sinks change. // Updates min_sev_ appropriately when debug sinks change.
static void UpdateMinLogSeverity(); static void UpdateMinLogSeverity();
@ -499,7 +502,7 @@ class LogMessage {
std::string extra_; std::string extra_;
// The output streams and their associated severities // The output streams and their associated severities
static StreamList streams_; static LogSink* streams_;
// Flags for formatting options // Flags for formatting options
static bool thread_, timestamp_; static bool thread_, timestamp_;

View file

@ -8,6 +8,7 @@
* be found in the AUTHORS file in the root of the source tree. * be found in the AUTHORS file in the root of the source tree.
*/ */
#include <list>
#include <memory> #include <memory>
#include <numeric> #include <numeric>