diff --git a/include/spdlog/async_logger.h b/include/spdlog/async_logger.h index c894399c..7cb5cf13 100644 --- a/include/spdlog/async_logger.h +++ b/include/spdlog/async_logger.h @@ -35,6 +35,7 @@ // Upong destruction, logs all remaining messages in the queue before destructing.. #include +#include #include "common.h" #include "logger.h" @@ -51,9 +52,9 @@ class async_logger :public logger { public: template - async_logger(const std::string& name, const It& begin, const It& end, size_t queue_size); - async_logger(const std::string& logger_name, sinks_init_list sinks, size_t queue_size); - async_logger(const std::string& logger_name, sink_ptr single_sink, size_t queue_size); + async_logger(const std::string& name, const It& begin, const It& end, size_t queue_size, const std::function& worker_warmup_cb = nullptr); + async_logger(const std::string& logger_name, sinks_init_list sinks, size_t queue_size, const std::function& worker_warmup_cb = nullptr); + async_logger(const std::string& logger_name, sink_ptr single_sink, size_t queue_size, const std::function& worker_warmup_cb = nullptr); protected: diff --git a/include/spdlog/details/async_log_helper.h b/include/spdlog/details/async_log_helper.h index ca306f4f..eecf804a 100644 --- a/include/spdlog/details/async_log_helper.h +++ b/include/spdlog/details/async_log_helper.h @@ -36,6 +36,7 @@ #include #include #include +#include #include "../common.h" #include "../sinks/sink.h" @@ -108,7 +109,7 @@ public: using clock = std::chrono::steady_clock; - async_log_helper(formatter_ptr formatter, const std::vector& sinks, size_t queue_size); + async_log_helper(formatter_ptr formatter, const std::vector& sinks, size_t queue_size, const std::function& worker_warmup_cb = nullptr); void log(const details::log_msg& msg); //Stop logging and join the back thread @@ -125,6 +126,9 @@ private: // last exception thrown from the worker thread std::shared_ptr _last_workerthread_ex; + // worker thread warmup callback - one can set thread priority, affinity, etc + const std::function _worker_warmup_cb; + // throw last worker thread exception or if worker thread is not active void throw_if_bad_worker(); @@ -136,7 +140,7 @@ private: //return true if a message was available (queue was not empty), will set the last_pop to the pop time bool process_next_msg(clock::time_point& last_pop); - // guess how much to sleep if queue is empty/full using last succesful op time as hint + // guess how much to sleep if queue is empty/full using last successful op time as hint static void sleep_or_yield(const clock::time_point& last_op_time); }; @@ -146,10 +150,11 @@ private: /////////////////////////////////////////////////////////////////////////////// // async_sink class implementation /////////////////////////////////////////////////////////////////////////////// -inline spdlog::details::async_log_helper::async_log_helper(formatter_ptr formatter, const std::vector& sinks, size_t queue_size): +inline spdlog::details::async_log_helper::async_log_helper(formatter_ptr formatter, const std::vector& sinks, size_t queue_size, const std::function& worker_warmup_cb): _formatter(formatter), _sinks(sinks), _q(queue_size), + _worker_warmup_cb(worker_warmup_cb), _worker_thread(&async_log_helper::worker_loop, this) {} @@ -189,6 +194,7 @@ inline void spdlog::details::async_log_helper::worker_loop() { try { + if (_worker_warmup_cb) _worker_warmup_cb(); clock::time_point last_pop = clock::now(); while(process_next_msg(last_pop)); } diff --git a/include/spdlog/details/async_logger_impl.h b/include/spdlog/details/async_logger_impl.h index 0129e2fd..ec341578 100644 --- a/include/spdlog/details/async_logger_impl.h +++ b/include/spdlog/details/async_logger_impl.h @@ -34,17 +34,17 @@ template -inline spdlog::async_logger::async_logger(const std::string& logger_name, const It& begin, const It& end, size_t queue_size) : +inline spdlog::async_logger::async_logger(const std::string& logger_name, const It& begin, const It& end, size_t queue_size, const std::function& worker_warmup_cb) : logger(logger_name, begin, end), - _async_log_helper(new details::async_log_helper(_formatter, _sinks, queue_size)) + _async_log_helper(new details::async_log_helper(_formatter, _sinks, queue_size, worker_warmup_cb)) { } -inline spdlog::async_logger::async_logger(const std::string& logger_name, sinks_init_list sinks, size_t queue_size) : - async_logger(logger_name, sinks.begin(), sinks.end(), queue_size) {} +inline spdlog::async_logger::async_logger(const std::string& logger_name, sinks_init_list sinks, size_t queue_size, const std::function& worker_warmup_cb) : + async_logger(logger_name, sinks.begin(), sinks.end(), queue_size, worker_warmup_cb) {} -inline spdlog::async_logger::async_logger(const std::string& logger_name, sink_ptr single_sink, size_t queue_size) : - async_logger(logger_name, { single_sink }, queue_size) {} +inline spdlog::async_logger::async_logger(const std::string& logger_name, sink_ptr single_sink, size_t queue_size, const std::function& worker_warmup_cb) : + async_logger(logger_name, { single_sink }, queue_size, worker_warmup_cb) {} inline void spdlog::async_logger::_set_formatter(spdlog::formatter_ptr msg_formatter) diff --git a/include/spdlog/details/registry.h b/include/spdlog/details/registry.h index 8d815e1f..9c25845f 100644 --- a/include/spdlog/details/registry.h +++ b/include/spdlog/details/registry.h @@ -31,6 +31,7 @@ #include #include #include +#include #include "../logger.h" #include "../async_logger.h" @@ -61,7 +62,7 @@ public: return found->second; std::shared_ptr new_logger; if (_async_mode) - new_logger = std::make_shared(logger_name, sinks_begin, sinks_end, _async_q_size); + new_logger = std::make_shared(logger_name, sinks_begin, sinks_end, _async_q_size, _worker_warmup_cb); else new_logger = std::make_shared(logger_name, sinks_begin, sinks_end); @@ -119,11 +120,12 @@ public: l.second->set_level(log_level); } - void set_async_mode(size_t q_size) + void set_async_mode(size_t q_size, const std::function& worker_warmup_cb = nullptr) { std::lock_guard lock(_mutex); _async_mode = true; _async_q_size = q_size; + _worker_warmup_cb = worker_warmup_cb; } void set_sync_mode() @@ -149,6 +151,7 @@ private: level::level_enum _level = level::info; bool _async_mode = false; size_t _async_q_size = 0; + std::function _worker_warmup_cb = nullptr; }; } } diff --git a/include/spdlog/details/spdlog_impl.h b/include/spdlog/details/spdlog_impl.h index 02840b0b..e1e6a5d4 100644 --- a/include/spdlog/details/spdlog_impl.h +++ b/include/spdlog/details/spdlog_impl.h @@ -132,9 +132,9 @@ inline void spdlog::set_level(level::level_enum log_level) } -inline void spdlog::set_async_mode(size_t queue_size) +inline void spdlog::set_async_mode(size_t queue_size, const std::function& worker_warmup_cb) { - details::registry::instance().set_async_mode(queue_size); + details::registry::instance().set_async_mode(queue_size, worker_warmup_cb); } inline void spdlog::set_sync_mode() diff --git a/include/spdlog/spdlog.h b/include/spdlog/spdlog.h index 7ce1735b..92894b85 100644 --- a/include/spdlog/spdlog.h +++ b/include/spdlog/spdlog.h @@ -63,7 +63,7 @@ void set_level(level::level_enum log_level); // Turn on async mode and set the queue size for each async_logger -void set_async_mode(size_t queue_size); +void set_async_mode(size_t queue_size, const std::function& worker_warmup_cb = nullptr); // Turn off async mode void set_sync_mode();