Index: lldb/include/lldb/Utility/Log.h =================================================================== --- lldb/include/lldb/Utility/Log.h +++ lldb/include/lldb/Utility/Log.h @@ -77,6 +77,21 @@ void *m_baton; }; +class BufferedLogHandler : public LogHandler { +public: + BufferedLogHandler(size_t size, std::shared_ptr delegate); + ~BufferedLogHandler(); + + void Emit(llvm::StringRef message) override; + void Flush(); + +private: + std::shared_ptr m_delegate; + std::unique_ptr m_messages; + const size_t m_size = 0; + size_t m_next_index = 0; +}; + class RotatingLogHandler : public LogHandler { public: RotatingLogHandler(size_t size); Index: lldb/source/Utility/Log.cpp =================================================================== --- lldb/source/Utility/Log.cpp +++ lldb/source/Utility/Log.cpp @@ -355,6 +355,27 @@ m_callback(message.data(), m_baton); } +BufferedLogHandler::BufferedLogHandler(size_t size, + std::shared_ptr delegate) + : m_delegate(delegate), m_messages(std::make_unique(size)), + m_size(size) {} + +BufferedLogHandler::~BufferedLogHandler() { Flush(); } + +void BufferedLogHandler::Emit(llvm::StringRef message) { + m_messages[m_next_index++] = message.str(); + if (m_next_index == m_size) + Flush(); +} + +void BufferedLogHandler::Flush() { + for (size_t i = 0; i < m_next_index; ++i) { + m_delegate->Emit(m_messages[i]); + m_messages[i].clear(); + } + m_next_index = 0; +} + RotatingLogHandler::RotatingLogHandler(size_t size) : m_messages(std::make_unique(size)), m_size(size) {} Index: lldb/unittests/Utility/LogTest.cpp =================================================================== --- lldb/unittests/Utility/LogTest.cpp +++ lldb/unittests/Utility/LogTest.cpp @@ -193,6 +193,34 @@ EXPECT_EQ(GetDumpAsString(handler), "bazquxquux"); } +TEST(LogHandlerTest, BufferedLogHandler) { + auto delegate_sp = std::make_shared(); + + { + BufferedLogHandler handler(3, delegate_sp); + + handler.Emit("1"); + handler.Emit("2"); + EXPECT_EQ(delegate_sp->m_stream.str(), ""); + + handler.Emit("3"); + EXPECT_EQ(delegate_sp->m_stream.str(), "123"); + + handler.Emit("4"); + handler.Emit("5"); + EXPECT_EQ(delegate_sp->m_stream.str(), "123"); + + handler.Emit("6"); + EXPECT_EQ(delegate_sp->m_stream.str(), "123456"); + + handler.Emit("7"); + EXPECT_EQ(delegate_sp->m_stream.str(), "123456"); + } + + // Make sure we flush on destruction. + EXPECT_EQ(delegate_sp->m_stream.str(), "1234567"); +} + TEST_F(LogChannelTest, Enable) { EXPECT_EQ(nullptr, GetLog(TestChannel::FOO)); std::string message;