diff --git a/toolbox/sys/Logger.cpp b/toolbox/sys/Logger.cpp index 686fdada..52605fec 100644 --- a/toolbox/sys/Logger.cpp +++ b/toolbox/sys/Logger.cpp @@ -240,9 +240,16 @@ AsyncLogger::~AsyncLogger() void AsyncLogger::write_all_messages() { Task t; + int fake_cnt = 0; + while (tq_.pop(t)) { - logger_.write_log(t.ts, t.level, t.tid, LogMsgPtr{t.msg}, t.size); + if (t.msg != nullptr) { + logger_.write_log(t.ts, t.level, t.tid, LogMsgPtr{t.msg}, t.size); + } else { + fake_cnt++; + } } + fake_pushed_count_.fetch_sub(fake_cnt, std::memory_order_relaxed); } bool AsyncLogger::run() @@ -258,12 +265,32 @@ void AsyncLogger::stop() stop_ = true; } +void AsyncLogger::set_warming_mode(bool enable) noexcept +{ + warming_mode_enabled_ = enable; +} + void AsyncLogger::do_write_log(WallTime ts, LogLevel level, int tid, LogMsgPtr&& msg, size_t size) noexcept { char* const msg_ptr = msg.release(); + auto push_to_queue = [&](char* ptr) { + return tq_.push(Task{.ts = ts, .level = level, .tid = tid, .msg = ptr, .size = size}); + }; try { - if (tq_.push(Task{.ts = ts, .level = level, .tid = tid, .msg = msg_ptr, .size = size})) { + if (warming_mode_enabled_) [[unlikely]] { + const auto d = ts - last_time_fake_pushed_; + const auto cnt = fake_pushed_count_.load(std::memory_order_relaxed); + + constexpr Millis FakePushInterval = 10ms; + constexpr int MaxPushedFakeCount = 25; + + if (duration_cast(d) >= FakePushInterval && cnt < MaxPushedFakeCount) { + push_to_queue(nullptr); + last_time_fake_pushed_ = ts; + fake_pushed_count_.fetch_add(1, std::memory_order_relaxed); + } + } else if (push_to_queue(msg_ptr)) [[likely]] { // Successfully pushed the task to the queue, release ownership of msg_ptr. return; } diff --git a/toolbox/sys/Logger.hpp b/toolbox/sys/Logger.hpp index 9b315f18..c8ebdf33 100644 --- a/toolbox/sys/Logger.hpp +++ b/toolbox/sys/Logger.hpp @@ -153,6 +153,9 @@ class TOOLBOX_API AsyncLogger : public Logger { /// Interrupt and exit any inprogress call to run(). void stop(); + /// Any logged lines will be dropped while this mode is enabled. + void set_warming_mode(bool enable) noexcept; + private: void write_all_messages(); void do_write_log(WallTime ts, LogLevel level, int tid, LogMsgPtr&& msg, @@ -161,6 +164,11 @@ class TOOLBOX_API AsyncLogger : public Logger { Logger& logger_; boost::lockfree::queue> tq_{512}; std::atomic stop_{false}; + + // warming variables + bool warming_mode_enabled_{false}; + std::atomic fake_pushed_count_{0}; + WallTime last_time_fake_pushed_{}; }; /// ScopedLogLevel provides a convenient RAII-style utility for setting the log-level for the