From 3916674bc5d0bc2ed58f3a699014b37f560a7010 Mon Sep 17 00:00:00 2001 From: gabi Date: Wed, 3 Dec 2014 00:28:33 +0200 Subject: [PATCH] async_helper sleep_or_yield or full/empty queue --- include/spdlog/details/async_log_helper.h | 57 ++++++++++++++--------- 1 file changed, 36 insertions(+), 21 deletions(-) diff --git a/include/spdlog/details/async_log_helper.h b/include/spdlog/details/async_log_helper.h index 7ea0ac04..92c2f18d 100644 --- a/include/spdlog/details/async_log_helper.h +++ b/include/spdlog/details/async_log_helper.h @@ -125,8 +125,8 @@ private: // worker thread loop void _thread_loop(); - // guess how much to sleep if queue is empty - static clock::duration spdlog::details::async_log_helper::_calc_pop_sleep(const clock::time_point& last_pop); + // guess how much to sleep if queue is empty/full using last succesful op time as hint + static void _sleep_or_yield(const clock::time_point& last_op_time); // clear all remaining messages(if any), stop the _worker_thread and join it @@ -151,11 +151,22 @@ inline spdlog::details::async_log_helper::~async_log_helper() _join(); } + +//Try to push and block until succeeded inline void spdlog::details::async_log_helper::log(const details::log_msg& msg) { _push_sentry(); - _q.push(std::unique_ptr(new async_msg(msg))); + //Only if queue is full, enter wait loop + if (!_q.push(std::unique_ptr < async_msg >(new async_msg(msg)))) + { + auto last_op_time = clock::now(); + do + { + _sleep_or_yield(last_op_time); + } + while (!_q.push(std::unique_ptr < async_msg >(new async_msg(msg)))); + } } inline void spdlog::details::async_log_helper::_thread_loop() @@ -189,30 +200,14 @@ inline void spdlog::details::async_log_helper::_thread_loop() _last_workerthread_ex = std::make_shared("Unknown exception"); } } - //Sleep for a while if empty. + // sleep or yield if queue is empty. else { - std::this_thread::sleep_for(_calc_pop_sleep(last_pop)); + _sleep_or_yield(last_pop); } } } -//Try to guess sleep duration according to the time passed since last message -inline spdlog::details::async_log_helper::clock::duration spdlog::details::async_log_helper::_calc_pop_sleep(const clock::time_point& last_pop) -{ - using std::chrono::milliseconds; - using std::chrono::microseconds; - auto time_since_pop = clock::now() - last_pop; - - - if (time_since_pop > milliseconds(1000)) - return milliseconds(500); - if (time_since_pop > microseconds(0)) - return(time_since_pop / 2); - return microseconds(0); - - -} inline void spdlog::details::async_log_helper::add_sink(spdlog::sink_ptr s) { @@ -249,6 +244,23 @@ inline void spdlog::details::async_log_helper::shutdown(const log_clock::duratio } +// Sleep or yield using the time passed since last message as a hint +inline void spdlog::details::async_log_helper::_sleep_or_yield(const clock::time_point& last_op_time) +{ + using std::chrono::milliseconds; + using std::this_thread::sleep_for; + using std::this_thread::yield; + + clock::duration sleep_duration; + auto time_since_op = clock::now() - last_op_time; + if (time_since_op > milliseconds(1000)) + sleep_for(milliseconds(500)); + else if (time_since_op > milliseconds(1)) + sleep_for(time_since_op / 2); + else + yield(); +} + inline void spdlog::details::async_log_helper::_push_sentry() { if (_last_workerthread_ex) @@ -278,3 +290,6 @@ inline void spdlog::details::async_log_helper::_join() } + + +