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}
diff --git a/modules/audio_device/audio_device_unittest.cc b/modules/audio_device/audio_device_unittest.cc
index 3e75d76..1b970d5 100644
--- a/modules/audio_device/audio_device_unittest.cc
+++ b/modules/audio_device/audio_device_unittest.cc
@@ -12,6 +12,7 @@
 
 #include <algorithm>
 #include <cstring>
+#include <list>
 #include <memory>
 #include <numeric>
 
diff --git a/modules/video_capture/windows/sink_filter_ds.cc b/modules/video_capture/windows/sink_filter_ds.cc
index 5e8960c..9019b12 100644
--- a/modules/video_capture/windows/sink_filter_ds.cc
+++ b/modules/video_capture/windows/sink_filter_ds.cc
@@ -14,6 +14,7 @@
 #include <initguid.h>
 
 #include <algorithm>
+#include <list>
 
 #include "rtc_base/arraysize.h"
 #include "rtc_base/checks.h"
diff --git a/rtc_base/logging.cc b/rtc_base/logging.cc
index 71e0f4f..158be33 100644
--- a/rtc_base/logging.cc
+++ b/rtc_base/logging.cc
@@ -93,7 +93,8 @@
 // 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
 // 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)
 bool LogMessage::thread_, LogMessage::timestamp_;
@@ -201,12 +202,12 @@
   }
 
   GlobalLockScope cs(&g_log_crit);
-  for (auto& kv : streams_) {
-    if (severity_ >= kv.second) {
+  for (LogSink* entry = streams_; entry != nullptr; entry = entry->next_) {
+    if (severity_ >= entry->min_severity_) {
 #if defined(WEBRTC_ANDROID)
-      kv.first->OnLogMessage(str, severity_, tag_);
+      entry->OnLogMessage(str, severity_, tag_);
 #else
-      kv.first->OnLogMessage(str, severity_);
+      entry->OnLogMessage(str, severity_);
 #endif
     }
   }
@@ -260,9 +261,9 @@
 int LogMessage::GetLogToStream(LogSink* stream) {
   GlobalLockScope cs(&g_log_crit);
   LoggingSeverity sev = LS_NONE;
-  for (auto& kv : streams_) {
-    if (!stream || stream == kv.first) {
-      sev = std::min(sev, kv.second);
+  for (LogSink* entry = streams_; entry != nullptr; entry = entry->next_) {
+    if (stream == nullptr || stream == entry) {
+      sev = std::min(sev, entry->min_severity_);
     }
   }
   return sev;
@@ -270,15 +271,18 @@
 
 void LogMessage::AddLogToStream(LogSink* stream, LoggingSeverity min_sev) {
   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();
 }
 
 void LogMessage::RemoveLogToStream(LogSink* stream) {
   GlobalLockScope cs(&g_log_crit);
-  for (StreamList::iterator it = streams_.begin(); it != streams_.end(); ++it) {
-    if (stream == it->first) {
-      streams_.erase(it);
+  for (LogSink** entry = &streams_; *entry != nullptr;
+       entry = &(*entry)->next_) {
+    if (*entry == stream) {
+      *entry = (*entry)->next_;
       break;
     }
   }
@@ -337,9 +341,8 @@
 void LogMessage::UpdateMinLogSeverity()
     RTC_EXCLUSIVE_LOCKS_REQUIRED(g_log_crit) {
   LoggingSeverity min_sev = g_dbg_sev;
-  for (const auto& kv : streams_) {
-    const LoggingSeverity sev = kv.second;
-    min_sev = std::min(min_sev, sev);
+  for (LogSink* entry = streams_; entry != nullptr; entry = entry->next_) {
+    min_sev = std::min(min_sev, entry->min_severity_);
   }
   g_min_sev = min_sev;
 }
@@ -445,10 +448,7 @@
   // is going to be logged. This introduces unnecessary synchronization for
   // a feature that's mostly used for testing.
   GlobalLockScope cs(&g_log_crit);
-  if (streams_.size() > 0)
-    return false;
-
-  return true;
+  return streams_ == nullptr;
 }
 
 void LogMessage::FinishPrintStream() {
diff --git a/rtc_base/logging.h b/rtc_base/logging.h
index 17c6c24b..1ca6ea8 100644
--- a/rtc_base/logging.h
+++ b/rtc_base/logging.h
@@ -46,7 +46,6 @@
 
 #include <errno.h>
 
-#include <list>
 #include <sstream>  // no-presubmit-check TODO(webrtc:8982)
 #include <string>
 #include <utility>
@@ -99,6 +98,7 @@
   ERRCTX_HR = ERRCTX_HRESULT,  // LOG_E(sev, HR, x)
 };
 
+class LogMessage;
 // Virtual sink interface that can receive log messages.
 class LogSink {
  public:
@@ -110,6 +110,12 @@
   virtual void OnLogMessage(const std::string& message,
                             LoggingSeverity severity);
   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 {
@@ -437,16 +443,15 @@
   // Sets whether logs will be directed to stderr in debug mode.
   static void SetLogToStderr(bool log_to_stderr);
 
-  //  Stream: Any non-blocking stream interface.  LogMessage takes ownership of
-  //   the stream. Multiple streams may be specified by using AddLogToStream.
-  //   LogToStream is retained for backwards compatibility; when invoked, it
-  //   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);
+  // Stream: Any non-blocking stream interface.
+  // Installs the |stream| to collect logs with severtiy |min_sev| or higher.
+  // |stream| must live until deinstalled by RemoveLogToStream
   static void AddLogToStream(LogSink* stream, LoggingSeverity min_sev);
+  // Removes the specified stream, without destroying it.
   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
   // logging operations by pre-checking the logging level.
@@ -464,8 +469,6 @@
 
  private:
   friend class LogMessageForTesting;
-  typedef std::pair<LogSink*, LoggingSeverity> StreamAndSeverity;
-  typedef std::list<StreamAndSeverity> StreamList;
 
   // Updates min_sev_ appropriately when debug sinks change.
   static void UpdateMinLogSeverity();
@@ -499,7 +502,7 @@
   std::string extra_;
 
   // The output streams and their associated severities
-  static StreamList streams_;
+  static LogSink* streams_;
 
   // Flags for formatting options
   static bool thread_, timestamp_;
diff --git a/sdk/android/native_unittests/audio_device/audio_device_unittest.cc b/sdk/android/native_unittests/audio_device/audio_device_unittest.cc
index da7790c..88dfad4 100644
--- a/sdk/android/native_unittests/audio_device/audio_device_unittest.cc
+++ b/sdk/android/native_unittests/audio_device/audio_device_unittest.cc
@@ -8,6 +8,7 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
+#include <list>
 #include <memory>
 #include <numeric>