Skip to content

Commit

Permalink
check all queues are empty before removing loggers or sleeping
Browse files Browse the repository at this point in the history
  • Loading branch information
odygrd committed Jul 23, 2023
1 parent 3cb5df9 commit d84f71b
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 21 deletions.
58 changes: 39 additions & 19 deletions quill/include/quill/detail/backend/BackendWorker.h
Original file line number Diff line number Diff line change
Expand Up @@ -1041,32 +1041,52 @@ void BackendWorker::_main_loop()
// We can also clear any invalidated or empty thread contexts
_thread_context_collection.clear_invalid_and_empty_thread_contexts();

// since there are no messages we can check for invalidated loggers and clean them up
bool const loggers_removed = _logger_collection.remove_invalidated_loggers();
if (loggers_removed)
{
// if loggers were removed also check for Handlers to remove
// remove_unused_handlers is expensive and should be only called when it is needed
_handler_collection.remove_unused_handlers();
}

// resync rdtsc clock before going to sleep.
// This is useful when quill::Clock is used
_resync_rdtsc_clock();

if (_backend_thread_sleep_duration.count() != 0)
// Also check if all queues are empty as we need to know that to remove any unused Loggers
bool all_queues_empty{true};
for (ThreadContext* thread_context : cached_thread_contexts)
{
std::unique_lock<std::mutex> lock(_wake_up_mutex);

// Wait for a timeout or a notification to wake up
_wake_up_cv.wait_for(lock, _backend_thread_sleep_duration, [this] { return _wake_up; });

// set the flag back to false since we woke up here
_wake_up = false;
std::visit(
[&all_queues_empty](auto& queue)
{
using T = std::decay_t<decltype(queue)>;
if constexpr ((std::is_same_v<T, UnboundedQueue>) || (std::is_same_v<T, BoundedQueue>))
{
all_queues_empty &= queue.empty();
}
},
thread_context->spsc_queue_variant());
}
else if (_backend_thread_yield)

if (all_queues_empty)
{
std::this_thread::yield();
// since there are no messages we can check for invalidated loggers and clean them up
bool const loggers_removed = _logger_collection.remove_invalidated_loggers();
if (loggers_removed)
{
// if loggers were removed also check for Handlers to remove
// remove_unused_handlers is expensive and should be only called when it is needed
_handler_collection.remove_unused_handlers();
}

// There is nothing left to do, and we can let this thread sleep for a while
if (_backend_thread_sleep_duration.count() != 0)
{
std::unique_lock<std::mutex> lock(_wake_up_mutex);

// Wait for a timeout or a notification to wake up
_wake_up_cv.wait_for(lock, _backend_thread_sleep_duration, [this] { return _wake_up; });

// set the flag back to false since we woke up here
_wake_up = false;
}
else if (_backend_thread_yield)
{
std::this_thread::yield();
}
}

// After waking up resync rdtsc clock again and resume
Expand Down
4 changes: 2 additions & 2 deletions quill/test/QuillLogTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,10 +160,10 @@ TEST_CASE("log_from_const_function")
// log again for class b
log_test_class const log_test_class_b{filename};
log_test_class_b.use_logger_const();

quill::flush();
}

quill::flush();

// Read file and check
std::vector<std::string> const file_contents = quill::testing::file_contents(filename);
REQUIRE_EQ(file_contents.size(), 3);
Expand Down

0 comments on commit d84f71b

Please sign in to comment.