// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. // Distributed under the MIT License (http://opensource.org/licenses/MIT) #include "spdlog/sinks/async_sink.h" #include #include #include #include "spdlog/details/mpmc_blocking_q.h" #include "spdlog/common.h" #include "spdlog/pattern_formatter.h" namespace spdlog { namespace sinks { template async_sink::async_sink(size_t queue_size, std::function on_thread_start, std::function on_thread_stop) : base_t() { if (queue_size == 0 || queue_size > max_queue_size) { throw spdlog_ex("async_sink: invalid queue size"); } // printf("........... Allocating queue: slot: %zu X %zu bytes ====> %lld KB ..............\n", // queue_size, sizeof(details::async_log_msg), (sizeof(details::async_log_msg) * queue_size)/1024); q_ = std::make_unique(queue_size); worker_thread_ = std::thread([this, on_thread_start, on_thread_stop] { if (on_thread_start) on_thread_start(); this->worker_loop(); if (on_thread_stop) on_thread_stop(); }); } template async_sink::~async_sink() { try { q_->enqueue(async_log_msg(async_log_msg::type::terminate)); worker_thread_.join(); } catch (...) { } }; template async_sink::async_sink() : async_sink(default_queue_size, nullptr, nullptr) {} template async_sink::async_sink(size_t queue_size) : async_sink(queue_size, nullptr, nullptr) {} template async_sink::async_sink(std::function on_thread_start, std::function on_thread_stop) : async_sink(default_queue_size, on_thread_start, on_thread_stop) {} template void async_sink::sink_it_(const details::log_msg &msg) { send_message_(async_log_msg::type::log, msg); } template void async_sink::set_overflow_policy(overflow_policy policy) { overflow_policy_ = policy; } template typename async_sink::overflow_policy async_sink::get_overflow_policy() const { return overflow_policy_; } template size_t async_sink::get_overrun_counter() const { return q_->overrun_counter(); } template void async_sink::reset_overrun_counter() const { q_->reset_overrun_counter(); } template size_t async_sink::get_discard_counter() const { return q_->discard_counter(); } template void async_sink::reset_discard_counter() const { q_->reset_discard_counter(); } template void async_sink::flush_() { send_message_(async_log_msg::type::flush, details::log_msg()); } template void async_sink::send_message_(async_log_msg::type msg_type, const details::log_msg &msg) { switch (overflow_policy_) { case overflow_policy::block: q_->enqueue(async_log_msg(msg_type, msg)); break; case overflow_policy::overrun_oldest: q_->enqueue_nowait(async_log_msg(msg_type, msg)); break; case overflow_policy::discard_new: q_->enqueue_if_have_room(async_log_msg(msg_type, msg)); break; default: assert(false); throw spdlog_ex("async_sink: invalid overflow policy"); } } template void async_sink::worker_loop() { details::async_log_msg incoming_msg; for (;;) { q_->dequeue(incoming_msg); switch (incoming_msg.message_type()) { case async_log_msg::type::log: base_t::sink_it_(incoming_msg); break; case async_log_msg::type::flush: base_t::flush_(); break; case async_log_msg::type::terminate: return; default: assert(false); } } } } // namespace sinks } // namespace spdlog // template instantiations #include "spdlog/details/null_mutex.h" template class SPDLOG_API spdlog::sinks::async_sink; template class SPDLOG_API spdlog::sinks::async_sink;