JDevlieghere updated this revision to Diff 437651.
JDevlieghere marked 4 inline comments as done.
JDevlieghere added a comment.

- Add `EmitThreadSafe`
- Remove `Flush`


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D127922/new/

https://reviews.llvm.org/D127922

Files:
  lldb/include/lldb/Core/Debugger.h
  lldb/include/lldb/Utility/Log.h
  lldb/include/lldb/Utility/StreamCallback.h
  lldb/source/Core/Debugger.cpp
  lldb/source/Utility/CMakeLists.txt
  lldb/source/Utility/Log.cpp
  lldb/source/Utility/StreamCallback.cpp
  lldb/tools/lldb-server/LLDBServerUtilities.cpp
  lldb/unittests/Core/CMakeLists.txt
  lldb/unittests/Core/StreamCallbackTest.cpp
  lldb/unittests/Utility/LogTest.cpp

Index: lldb/unittests/Utility/LogTest.cpp
===================================================================
--- lldb/unittests/Utility/LogTest.cpp
+++ lldb/unittests/Utility/LogTest.cpp
@@ -39,13 +39,13 @@
 } // namespace lldb_private
 
 // Wrap enable, disable and list functions to make them easier to test.
-static bool EnableChannel(std::shared_ptr<llvm::raw_ostream> stream_sp,
+static bool EnableChannel(std::shared_ptr<LogHandler> log_handler_sp,
                           uint32_t log_options, llvm::StringRef channel,
                           llvm::ArrayRef<const char *> categories,
                           std::string &error) {
   error.clear();
   llvm::raw_string_ostream error_stream(error);
-  return Log::EnableLogChannel(stream_sp, log_options, channel, categories,
+  return Log::EnableLogChannel(log_handler_sp, log_options, channel, categories,
                                error_stream);
 }
 
@@ -78,18 +78,27 @@
   }
 };
 
+class TestLogHandler : public LogHandler {
+public:
+  TestLogHandler() : m_messages(), m_stream(m_messages) {}
+
+  void Emit(llvm::StringRef message) override { m_stream << message; }
+
+  llvm::SmallString<0> m_messages;
+  llvm::raw_svector_ostream m_stream;
+};
+
 // A test fixture which provides tests with a pre-registered and pre-enabled
 // channel. Additionally, the messages written to that channel are captured and
 // made available via getMessage().
 class LogChannelEnabledTest : public LogChannelTest {
-  llvm::SmallString<0> m_messages;
-  std::shared_ptr<llvm::raw_svector_ostream> m_stream_sp =
-      std::make_shared<llvm::raw_svector_ostream>(m_messages);
+  std::shared_ptr<TestLogHandler> m_log_handler_sp =
+      std::make_shared<TestLogHandler>();
   Log *m_log;
   size_t m_consumed_bytes = 0;
 
 protected:
-  std::shared_ptr<llvm::raw_ostream> getStream() { return m_stream_sp; }
+  std::shared_ptr<LogHandler> getLogHandler() { return m_log_handler_sp; }
   Log *getLog() { return m_log; }
   llvm::StringRef takeOutput();
   llvm::StringRef logAndTakeOutput(llvm::StringRef Message);
@@ -103,14 +112,15 @@
   LogChannelTest::SetUp();
 
   std::string error;
-  ASSERT_TRUE(EnableChannel(m_stream_sp, 0, "chan", {}, error));
+  ASSERT_TRUE(EnableChannel(m_log_handler_sp, 0, "chan", {}, error));
 
   m_log = GetLog(TestChannel::FOO);
   ASSERT_NE(nullptr, m_log);
 }
 
 llvm::StringRef LogChannelEnabledTest::takeOutput() {
-  llvm::StringRef result = m_stream_sp->str().drop_front(m_consumed_bytes);
+  llvm::StringRef result =
+      m_log_handler_sp->m_stream.str().drop_front(m_consumed_bytes);
   m_consumed_bytes+= result.size();
   return result;
 }
@@ -138,9 +148,9 @@
   Log::Register("chan", test_channel);
   EXPECT_EQ(nullptr, GetLog(TestChannel::FOO));
   std::string message;
-  std::shared_ptr<llvm::raw_string_ostream> stream_sp(
-      new llvm::raw_string_ostream(message));
-  EXPECT_TRUE(Log::EnableLogChannel(stream_sp, 0, "chan", {"foo"}, llvm::nulls()));
+  auto log_handler_sp = std::make_shared<TestLogHandler>();
+  EXPECT_TRUE(
+      Log::EnableLogChannel(log_handler_sp, 0, "chan", {"foo"}, llvm::nulls()));
   EXPECT_NE(nullptr, GetLog(TestChannel::FOO));
   Log::Unregister("chan");
   EXPECT_EQ(nullptr, GetLog(TestChannel::FOO));
@@ -149,22 +159,21 @@
 TEST_F(LogChannelTest, Enable) {
   EXPECT_EQ(nullptr, GetLog(TestChannel::FOO));
   std::string message;
-  std::shared_ptr<llvm::raw_string_ostream> stream_sp(
-      new llvm::raw_string_ostream(message));
+  auto log_handler_sp = std::make_shared<TestLogHandler>();
   std::string error;
-  ASSERT_FALSE(EnableChannel(stream_sp, 0, "chanchan", {}, error));
+  ASSERT_FALSE(EnableChannel(log_handler_sp, 0, "chanchan", {}, error));
   EXPECT_EQ("Invalid log channel 'chanchan'.\n", error);
 
-  EXPECT_TRUE(EnableChannel(stream_sp, 0, "chan", {}, error));
+  EXPECT_TRUE(EnableChannel(log_handler_sp, 0, "chan", {}, error));
   EXPECT_NE(nullptr, GetLog(TestChannel::FOO));
   EXPECT_EQ(nullptr, GetLog(TestChannel::BAR));
   EXPECT_NE(nullptr, GetLog(TestChannel::FOO | TestChannel::BAR));
 
-  EXPECT_TRUE(EnableChannel(stream_sp, 0, "chan", {"bar"}, error));
+  EXPECT_TRUE(EnableChannel(log_handler_sp, 0, "chan", {"bar"}, error));
   EXPECT_NE(nullptr, GetLog(TestChannel::FOO));
   EXPECT_NE(nullptr, GetLog(TestChannel::BAR));
 
-  EXPECT_TRUE(EnableChannel(stream_sp, 0, "chan", {"baz"}, error));
+  EXPECT_TRUE(EnableChannel(log_handler_sp, 0, "chan", {"baz"}, error));
   EXPECT_NE(std::string::npos, error.find("unrecognized log category 'baz'"))
       << "error: " << error;
 }
@@ -172,11 +181,10 @@
 TEST_F(LogChannelTest, EnableOptions) {
   EXPECT_EQ(nullptr, GetLog(TestChannel::FOO));
   std::string message;
-  std::shared_ptr<llvm::raw_string_ostream> stream_sp(
-      new llvm::raw_string_ostream(message));
+  auto log_handler_sp = std::make_shared<TestLogHandler>();
   std::string error;
-  EXPECT_TRUE(
-      EnableChannel(stream_sp, LLDB_LOG_OPTION_VERBOSE, "chan", {}, error));
+  EXPECT_TRUE(EnableChannel(log_handler_sp, LLDB_LOG_OPTION_VERBOSE, "chan", {},
+                            error));
 
   Log *log = GetLog(TestChannel::FOO);
   ASSERT_NE(nullptr, log);
@@ -186,10 +194,9 @@
 TEST_F(LogChannelTest, Disable) {
   EXPECT_EQ(nullptr, GetLog(TestChannel::FOO));
   std::string message;
-  std::shared_ptr<llvm::raw_string_ostream> stream_sp(
-      new llvm::raw_string_ostream(message));
+  auto log_handler_sp = std::make_shared<TestLogHandler>();
   std::string error;
-  EXPECT_TRUE(EnableChannel(stream_sp, 0, "chan", {"foo", "bar"}, error));
+  EXPECT_TRUE(EnableChannel(log_handler_sp, 0, "chan", {"foo", "bar"}, error));
   EXPECT_NE(nullptr, GetLog(TestChannel::FOO));
   EXPECT_NE(nullptr, GetLog(TestChannel::BAR));
 
@@ -226,12 +233,12 @@
 TEST_F(LogChannelEnabledTest, log_options) {
   std::string Err;
   EXPECT_EQ("Hello World\n", logAndTakeOutput("Hello World"));
-  EXPECT_TRUE(EnableChannel(getStream(), LLDB_LOG_OPTION_THREADSAFE, "chan", {},
-                            Err));
+  EXPECT_TRUE(EnableChannel(getLogHandler(), LLDB_LOG_OPTION_THREADSAFE, "chan",
+                            {}, Err));
   EXPECT_EQ("Hello World\n", logAndTakeOutput("Hello World"));
 
   {
-    EXPECT_TRUE(EnableChannel(getStream(), LLDB_LOG_OPTION_PREPEND_SEQUENCE,
+    EXPECT_TRUE(EnableChannel(getLogHandler(), LLDB_LOG_OPTION_PREPEND_SEQUENCE,
                               "chan", {}, Err));
     llvm::StringRef Msg = logAndTakeOutput("Hello World");
     int seq_no;
@@ -239,19 +246,21 @@
   }
 
   {
-    EXPECT_TRUE(EnableChannel(getStream(), LLDB_LOG_OPTION_PREPEND_FILE_FUNCTION,
-                              "chan", {}, Err));
+    EXPECT_TRUE(EnableChannel(getLogHandler(),
+                              LLDB_LOG_OPTION_PREPEND_FILE_FUNCTION, "chan", {},
+                              Err));
     llvm::StringRef Msg = logAndTakeOutput("Hello World");
     char File[12];
     char Function[17];
-      
+
     sscanf(Msg.str().c_str(), "%[^:]:%s                                 Hello World", File, Function);
     EXPECT_STRCASEEQ("LogTest.cpp", File);
     EXPECT_STREQ("logAndTakeOutput", Function);
   }
 
-  EXPECT_TRUE(EnableChannel(
-      getStream(), LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD, "chan", {}, Err));
+  EXPECT_TRUE(EnableChannel(getLogHandler(),
+                            LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD, "chan", {},
+                            Err));
   EXPECT_EQ(llvm::formatv("[{0,0+4}/{1,0+4}] Hello World\n", ::getpid(),
                           llvm::get_threadid())
                 .str(),
@@ -300,7 +309,7 @@
   // (with different log options).
   std::thread log_thread([this] { LLDB_LOGV(getLog(), "Hello World"); });
   EXPECT_TRUE(
-      EnableChannel(getStream(), LLDB_LOG_OPTION_VERBOSE, "chan", {}, err));
+      EnableChannel(getLogHandler(), LLDB_LOG_OPTION_VERBOSE, "chan", {}, err));
   log_thread.join();
 
   // The log thread either managed to write to the log, or it didn't. In either
Index: lldb/unittests/Core/StreamCallbackTest.cpp
===================================================================
--- lldb/unittests/Core/StreamCallbackTest.cpp
+++ /dev/null
@@ -1,27 +0,0 @@
-//===-- StreamCallbackTest.cpp --------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "lldb/Utility/StreamCallback.h"
-#include "gtest/gtest.h"
-
-using namespace lldb;
-using namespace lldb_private;
-
-static char test_baton;
-static size_t callback_count = 0;
-static void TestCallback(const char *data, void *baton) {
-  EXPECT_STREQ("Foobar", data);
-  EXPECT_EQ(&test_baton, baton);
-  ++callback_count;
-}
-
-TEST(StreamCallbackTest, Callback) {
-  StreamCallback stream(TestCallback, &test_baton);
-  stream << "Foobar";
-  EXPECT_EQ(1u, callback_count);
-}
Index: lldb/unittests/Core/CMakeLists.txt
===================================================================
--- lldb/unittests/Core/CMakeLists.txt
+++ lldb/unittests/Core/CMakeLists.txt
@@ -8,7 +8,6 @@
   RichManglingContextTest.cpp
   SourceLocationSpecTest.cpp
   SourceManagerTest.cpp
-  StreamCallbackTest.cpp
   UniqueCStringMapTest.cpp
 
   LINK_LIBS
Index: lldb/tools/lldb-server/LLDBServerUtilities.cpp
===================================================================
--- lldb/tools/lldb-server/LLDBServerUtilities.cpp
+++ lldb/tools/lldb-server/LLDBServerUtilities.cpp
@@ -18,21 +18,37 @@
 
 using namespace lldb;
 using namespace lldb_private::lldb_server;
+using namespace lldb_private;
 using namespace llvm;
 
-static std::shared_ptr<raw_ostream> GetLogStream(StringRef log_file) {
+class TestLogHandler : public LogHandler {
+public:
+  TestLogHandler(std::shared_ptr<llvm::raw_ostream> stream_sp)
+      : m_stream_sp(stream_sp) {}
+
+  void Emit(llvm::StringRef message) override {
+    (*m_stream_sp) << message;
+    m_stream_sp->flush();
+  }
+
+private:
+  std::shared_ptr<raw_ostream> m_stream_sp;
+};
+
+static std::shared_ptr<TestLogHandler> GetLogStream(StringRef log_file) {
   if (!log_file.empty()) {
     std::error_code EC;
-    std::shared_ptr<raw_ostream> stream_sp = std::make_shared<raw_fd_ostream>(
+    auto stream_sp = std::make_shared<raw_fd_ostream>(
         log_file, EC, sys::fs::OF_TextWithCRLF | sys::fs::OF_Append);
     if (!EC)
-      return stream_sp;
+      return std::make_shared<TestLogHandler>(stream_sp);
     errs() << llvm::formatv(
         "Failed to open log file `{0}`: {1}\nWill log to stderr instead.\n",
         log_file, EC.message());
   }
   // No need to delete the stderr stream.
-  return std::shared_ptr<raw_ostream>(&errs(), [](raw_ostream *) {});
+  return std::make_shared<TestLogHandler>(
+      std::shared_ptr<raw_ostream>(&errs(), [](raw_ostream *) {}));
 }
 
 bool LLDBServerUtilities::SetupLogging(const std::string &log_file,
Index: lldb/source/Utility/StreamCallback.cpp
===================================================================
--- lldb/source/Utility/StreamCallback.cpp
+++ /dev/null
@@ -1,22 +0,0 @@
-//===-- StreamCallback.cpp ------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "lldb/Utility/StreamCallback.h"
-
-#include <string>
-
-using namespace lldb_private;
-
-StreamCallback::StreamCallback(lldb::LogOutputCallback callback, void *baton)
-    : llvm::raw_ostream(true), m_callback(callback), m_baton(baton) {}
-
-void StreamCallback::write_impl(const char *Ptr, size_t Size) {
-  m_callback(std::string(Ptr, Size).c_str(), m_baton);
-}
-
-uint64_t StreamCallback::current_pos() const { return 0; }
Index: lldb/source/Utility/Log.cpp
===================================================================
--- lldb/source/Utility/Log.cpp
+++ lldb/source/Utility/Log.cpp
@@ -84,14 +84,14 @@
   return flags;
 }
 
-void Log::Enable(const std::shared_ptr<llvm::raw_ostream> &stream_sp,
+void Log::Enable(const std::shared_ptr<LogHandler> &handler_sp,
                  uint32_t options, uint32_t flags) {
   llvm::sys::ScopedWriter lock(m_mutex);
 
   MaskType mask = m_mask.fetch_or(flags, std::memory_order_relaxed);
   if (mask | flags) {
     m_options.store(options, std::memory_order_relaxed);
-    m_stream_sp = stream_sp;
+    m_handler = handler_sp;
     m_channel.log_ptr.store(this, std::memory_order_relaxed);
   }
 }
@@ -101,7 +101,7 @@
 
   MaskType mask = m_mask.fetch_and(~flags, std::memory_order_relaxed);
   if (!(mask & ~flags)) {
-    m_stream_sp.reset();
+    m_handler.reset();
     m_channel.log_ptr.store(nullptr, std::memory_order_relaxed);
   }
 }
@@ -191,10 +191,10 @@
   g_channel_map->erase(iter);
 }
 
-bool Log::EnableLogChannel(
-    const std::shared_ptr<llvm::raw_ostream> &log_stream_sp,
-    uint32_t log_options, llvm::StringRef channel,
-    llvm::ArrayRef<const char *> categories, llvm::raw_ostream &error_stream) {
+bool Log::EnableLogChannel(const std::shared_ptr<LogHandler> &log_handler_sp,
+                           uint32_t log_options, llvm::StringRef channel,
+                           llvm::ArrayRef<const char *> categories,
+                           llvm::raw_ostream &error_stream) {
   auto iter = g_channel_map->find(channel);
   if (iter == g_channel_map->end()) {
     error_stream << llvm::formatv("Invalid log channel '{0}'.\n", channel);
@@ -203,7 +203,7 @@
   uint32_t flags = categories.empty()
                        ? iter->second.m_channel.default_flags
                        : GetFlags(error_stream, *iter, categories);
-  iter->second.Enable(log_stream_sp, log_options, flags);
+  iter->second.Enable(log_handler_sp, log_options, flags);
   return true;
 }
 
@@ -314,20 +314,15 @@
 void Log::WriteMessage(const std::string &message) {
   // Make a copy of our stream shared pointer in case someone disables our log
   // while we are logging and releases the stream
-  auto stream_sp = GetStream();
-  if (!stream_sp)
+  auto handler_sp = GetHandler();
+  if (!handler_sp)
     return;
 
   Flags options = GetOptions();
-  if (options.Test(LLDB_LOG_OPTION_THREADSAFE)) {
-    static std::recursive_mutex g_LogThreadedMutex;
-    std::lock_guard<std::recursive_mutex> guard(g_LogThreadedMutex);
-    *stream_sp << message;
-    stream_sp->flush();
-  } else {
-    *stream_sp << message;
-    stream_sp->flush();
-  }
+  if (options.Test(LLDB_LOG_OPTION_THREADSAFE))
+    handler_sp->EmitThreadSafe(message);
+  else
+    handler_sp->Emit(message);
 }
 
 void Log::Format(llvm::StringRef file, llvm::StringRef function,
@@ -338,3 +333,35 @@
   message << payload << "\n";
   WriteMessage(message.str());
 }
+
+void LogHandler::EmitThreadSafe(llvm::StringRef message) {
+  std::lock_guard<std::mutex> guard(m_mutex);
+  Emit(message);
+}
+
+StreamLogHandler::StreamLogHandler(int fd, bool should_close, bool unbuffered)
+    : m_stream(fd, should_close, unbuffered) {}
+
+void StreamLogHandler::Emit(llvm::StringRef message) {
+  m_stream << message;
+  m_stream.flush();
+}
+
+std::shared_ptr<StreamLogHandler> StreamLogHandler::Create(int fd,
+                                                           bool should_close) {
+  constexpr const bool unbuffered = true;
+  return std::make_shared<StreamLogHandler>(fd, should_close, unbuffered);
+}
+
+CallbackLogHandler::CallbackLogHandler(lldb::LogOutputCallback callback,
+                                       void *baton)
+    : m_callback(callback), m_baton(baton) {}
+
+void CallbackLogHandler::Emit(llvm::StringRef message) {
+  m_callback(message.data(), m_baton);
+}
+
+std::shared_ptr<CallbackLogHandler>
+CallbackLogHandler::Create(lldb::LogOutputCallback callback, void *baton) {
+  return std::make_shared<CallbackLogHandler>(callback, baton);
+}
Index: lldb/source/Utility/CMakeLists.txt
===================================================================
--- lldb/source/Utility/CMakeLists.txt
+++ lldb/source/Utility/CMakeLists.txt
@@ -56,7 +56,6 @@
   State.cpp
   Status.cpp
   Stream.cpp
-  StreamCallback.cpp
   StreamString.cpp
   StringExtractor.cpp
   StringExtractorGDBRemote.cpp
Index: lldb/source/Core/Debugger.cpp
===================================================================
--- lldb/source/Core/Debugger.cpp
+++ lldb/source/Core/Debugger.cpp
@@ -51,7 +51,6 @@
 #include "lldb/Utility/ReproducerProvider.h"
 #include "lldb/Utility/State.h"
 #include "lldb/Utility/Stream.h"
-#include "lldb/Utility/StreamCallback.h"
 #include "lldb/Utility/StreamString.h"
 
 #if defined(_WIN32)
@@ -758,8 +757,7 @@
       m_forward_listener_sp(), m_clear_once() {
   m_instance_name.SetString(llvm::formatv("debugger_{0}", GetID()).str());
   if (log_callback)
-    m_log_callback_stream_sp =
-        std::make_shared<StreamCallback>(log_callback, baton);
+    m_callback_handler_sp = CallbackLogHandler::Create(log_callback, baton);
   m_command_interpreter_up->Initialize();
   // Always add our default platform to the platform list
   PlatformSP default_platform_sp(Platform::GetHostPlatform());
@@ -1292,8 +1290,7 @@
   // For simplicity's sake, I am not going to deal with how to close down any
   // open logging streams, I just redirect everything from here on out to the
   // callback.
-  m_log_callback_stream_sp =
-      std::make_shared<StreamCallback>(log_callback, baton);
+  m_callback_handler_sp = CallbackLogHandler::Create(log_callback, baton);
 }
 
 static void PrivateReportProgress(Debugger &debugger, uint64_t progress_id,
@@ -1412,22 +1409,21 @@
                          llvm::StringRef log_file, uint32_t log_options,
                          llvm::raw_ostream &error_stream) {
   const bool should_close = true;
-  const bool unbuffered = true;
 
-  std::shared_ptr<llvm::raw_ostream> log_stream_sp;
-  if (m_log_callback_stream_sp) {
-    log_stream_sp = m_log_callback_stream_sp;
+  std::shared_ptr<LogHandler> log_handler_sp;
+  if (m_callback_handler_sp) {
+    log_handler_sp = m_callback_handler_sp;
     // For now when using the callback mode you always get thread & timestamp.
     log_options |=
         LLDB_LOG_OPTION_PREPEND_TIMESTAMP | LLDB_LOG_OPTION_PREPEND_THREAD_NAME;
   } else if (log_file.empty()) {
-    log_stream_sp = std::make_shared<llvm::raw_fd_ostream>(
-        GetOutputFile().GetDescriptor(), !should_close, unbuffered);
+    log_handler_sp = StreamLogHandler::Create(GetOutputFile().GetDescriptor(),
+                                              !should_close);
   } else {
-    auto pos = m_log_streams.find(log_file);
-    if (pos != m_log_streams.end())
-      log_stream_sp = pos->second.lock();
-    if (!log_stream_sp) {
+    auto pos = m_stream_handlers.find(log_file);
+    if (pos != m_stream_handlers.end())
+      log_handler_sp = pos->second.lock();
+    if (!log_handler_sp) {
       File::OpenOptions flags =
           File::eOpenOptionWriteOnly | File::eOpenOptionCanCreate;
       if (log_options & LLDB_LOG_OPTION_APPEND)
@@ -1442,18 +1438,18 @@
         return false;
       }
 
-      log_stream_sp = std::make_shared<llvm::raw_fd_ostream>(
-          (*file)->GetDescriptor(), should_close, unbuffered);
-      m_log_streams[log_file] = log_stream_sp;
+      log_handler_sp =
+          StreamLogHandler::Create((*file)->GetDescriptor(), should_close);
+      m_stream_handlers[log_file] = log_handler_sp;
     }
   }
-  assert(log_stream_sp);
+  assert(log_handler_sp);
 
   if (log_options == 0)
     log_options =
         LLDB_LOG_OPTION_PREPEND_THREAD_NAME | LLDB_LOG_OPTION_THREADSAFE;
 
-  return Log::EnableLogChannel(log_stream_sp, log_options, channel, categories,
+  return Log::EnableLogChannel(log_handler_sp, log_options, channel, categories,
                                error_stream);
 }
 
Index: lldb/include/lldb/Utility/StreamCallback.h
===================================================================
--- lldb/include/lldb/Utility/StreamCallback.h
+++ /dev/null
@@ -1,35 +0,0 @@
-//===-- StreamCallback.h -----------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLDB_UTILITY_STREAMCALLBACK_H
-#define LLDB_UTILITY_STREAMCALLBACK_H
-
-#include "lldb/lldb-types.h"
-#include "llvm/Support/raw_ostream.h"
-
-#include <cstddef>
-#include <cstdint>
-
-namespace lldb_private {
-
-class StreamCallback : public llvm::raw_ostream {
-public:
-  StreamCallback(lldb::LogOutputCallback callback, void *baton);
-  ~StreamCallback() override = default;
-
-private:
-  lldb::LogOutputCallback m_callback;
-  void *m_baton;
-
-  void write_impl(const char *Ptr, size_t Size) override;
-  uint64_t current_pos() const override;
-};
-
-} // namespace lldb_private
-
-#endif // LLDB_UTILITY_STREAMCALLBACK_H
Index: lldb/include/lldb/Utility/Log.h
===================================================================
--- lldb/include/lldb/Utility/Log.h
+++ lldb/include/lldb/Utility/Log.h
@@ -25,6 +25,7 @@
 #include <cstdarg>
 #include <cstdint>
 #include <memory>
+#include <mutex>
 #include <string>
 #include <type_traits>
 
@@ -45,6 +46,42 @@
 // Logging Functions
 namespace lldb_private {
 
+class LogHandler {
+public:
+  virtual ~LogHandler() = default;
+  virtual void Emit(llvm::StringRef message) = 0;
+  void EmitThreadSafe(llvm::StringRef message);
+
+private:
+  std::mutex m_mutex;
+};
+
+class StreamLogHandler : public LogHandler {
+public:
+  StreamLogHandler(int fd, bool should_close, bool unbuffered);
+
+  void Emit(llvm::StringRef message) override;
+
+  static std::shared_ptr<StreamLogHandler> Create(int fd, bool unbuffered);
+
+private:
+  llvm::raw_fd_ostream m_stream;
+};
+
+class CallbackLogHandler : public LogHandler {
+public:
+  CallbackLogHandler(lldb::LogOutputCallback callback, void *baton);
+
+  void Emit(llvm::StringRef message) override;
+
+  static std::shared_ptr<CallbackLogHandler>
+  Create(lldb::LogOutputCallback callback, void *baton);
+
+private:
+  lldb::LogOutputCallback m_callback;
+  void *m_baton;
+};
+
 class Log final {
 public:
   /// The underlying type of all log channel enums. Declare them as:
@@ -111,7 +148,7 @@
   static void Unregister(llvm::StringRef name);
 
   static bool
-  EnableLogChannel(const std::shared_ptr<llvm::raw_ostream> &log_stream_sp,
+  EnableLogChannel(const std::shared_ptr<LogHandler> &log_handler_sp,
                    uint32_t log_options, llvm::StringRef channel,
                    llvm::ArrayRef<const char *> categories,
                    llvm::raw_ostream &error_stream);
@@ -188,7 +225,7 @@
   // Their modification however, is still protected by this mutex.
   llvm::sys::RWMutex m_mutex;
 
-  std::shared_ptr<llvm::raw_ostream> m_stream_sp;
+  std::shared_ptr<LogHandler> m_handler;
   std::atomic<uint32_t> m_options{0};
   std::atomic<MaskType> m_mask{0};
 
@@ -199,13 +236,13 @@
   void Format(llvm::StringRef file, llvm::StringRef function,
               const llvm::formatv_object_base &payload);
 
-  std::shared_ptr<llvm::raw_ostream> GetStream() {
+  std::shared_ptr<LogHandler> GetHandler() {
     llvm::sys::ScopedReader lock(m_mutex);
-    return m_stream_sp;
+    return m_handler;
   }
 
-  void Enable(const std::shared_ptr<llvm::raw_ostream> &stream_sp,
-              uint32_t options, uint32_t flags);
+  void Enable(const std::shared_ptr<LogHandler> &handler_sp, uint32_t options,
+              uint32_t flags);
 
   void Disable(uint32_t flags);
 
Index: lldb/include/lldb/Core/Debugger.h
===================================================================
--- lldb/include/lldb/Core/Debugger.h
+++ lldb/include/lldb/Core/Debugger.h
@@ -53,6 +53,8 @@
 }
 
 namespace lldb_private {
+class LogHandler;
+class CallbackLogHandler;
 class Address;
 class CommandInterpreter;
 class Process;
@@ -553,8 +555,8 @@
 
   llvm::Optional<uint64_t> m_current_event_id;
 
-  llvm::StringMap<std::weak_ptr<llvm::raw_ostream>> m_log_streams;
-  std::shared_ptr<llvm::raw_ostream> m_log_callback_stream_sp;
+  llvm::StringMap<std::weak_ptr<LogHandler>> m_stream_handlers;
+  std::shared_ptr<CallbackLogHandler> m_callback_handler_sp;
   ConstString m_instance_name;
   static LoadPluginCallbackType g_load_plugin_callback;
   typedef std::vector<llvm::sys::DynamicLibrary> LoadedPluginsList;
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to