diff --git a/CMakeLists.txt b/CMakeLists.txt index b67bcb02f6..ea996b2f35 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,7 +29,7 @@ if(SPDLOG_USE_STD_FORMAT) set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) elseif(NOT CMAKE_CXX_STANDARD) - set(CMAKE_CXX_STANDARD 11) + set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED ON) endif() diff --git a/include/spdlog/async_logger-inl.h b/include/spdlog/async_logger-inl.h index 1e79479850..9148c5b6d7 100644 --- a/include/spdlog/async_logger-inl.h +++ b/include/spdlog/async_logger-inl.h @@ -44,14 +44,18 @@ SPDLOG_LOGGER_CATCH(msg.source) // send flush request to the thread pool SPDLOG_INLINE void spdlog::async_logger::flush_(){ - SPDLOG_TRY{if (auto pool_ptr = thread_pool_.lock()){ - pool_ptr->post_flush(shared_from_this(), overflow_policy_); -} -else { - throw_spdlog_ex("async flush: thread pool doesn't exist anymore"); -} -} -SPDLOG_LOGGER_CATCH(source_loc()) + SPDLOG_TRY { + auto pool_ptr = thread_pool_.lock(); + if (!pool_ptr) { + throw_spdlog_ex("async flush: thread pool doesn't exist anymore"); + } + + std::future future = pool_ptr->post_flush(shared_from_this(), overflow_policy_); + // Wait for the flush operation to complete. + // This might throw exception if the flush message get dropped because of overflow. + future.get(); + } + SPDLOG_LOGGER_CATCH(source_loc()) } // diff --git a/include/spdlog/details/thread_pool-inl.h b/include/spdlog/details/thread_pool-inl.h index 17e01c092a..fe5562e543 100644 --- a/include/spdlog/details/thread_pool-inl.h +++ b/include/spdlog/details/thread_pool-inl.h @@ -8,6 +8,7 @@ #endif #include +#include #include namespace spdlog { @@ -62,9 +63,13 @@ void SPDLOG_INLINE thread_pool::post_log(async_logger_ptr &&worker_ptr, post_async_msg_(std::move(async_m), overflow_policy); } -void SPDLOG_INLINE thread_pool::post_flush(async_logger_ptr &&worker_ptr, - async_overflow_policy overflow_policy) { - post_async_msg_(async_msg(std::move(worker_ptr), async_msg_type::flush), overflow_policy); +std::future SPDLOG_INLINE thread_pool::post_flush(async_logger_ptr &&worker_ptr, + async_overflow_policy overflow_policy) { + std::unique_ptr> promise = std::make_unique>(); + std::future future = promise->get_future(); + post_async_msg_(async_msg(std::move(worker_ptr), async_msg_type::flush, std::move(promise)), + overflow_policy); + return future; } size_t SPDLOG_INLINE thread_pool::overrun_counter() { return q_.overrun_counter(); } @@ -101,18 +106,22 @@ bool SPDLOG_INLINE thread_pool::process_next_msg_() { async_msg incoming_async_msg; q_.dequeue(incoming_async_msg); + bool active = true; switch (incoming_async_msg.msg_type) { case async_msg_type::log: { incoming_async_msg.worker_ptr->backend_sink_it_(incoming_async_msg); - return true; + active = true; + break; } case async_msg_type::flush: { incoming_async_msg.worker_ptr->backend_flush_(); - return true; + active = true; + break; } case async_msg_type::terminate: { - return false; + active = false; + break; } default: { @@ -120,7 +129,11 @@ bool SPDLOG_INLINE thread_pool::process_next_msg_() { } } - return true; + if (incoming_async_msg.promise) { + incoming_async_msg.promise->set_value(); + } + + return active; } } // namespace details diff --git a/include/spdlog/details/thread_pool.h b/include/spdlog/details/thread_pool.h index f22b078210..9b6324f7a0 100644 --- a/include/spdlog/details/thread_pool.h +++ b/include/spdlog/details/thread_pool.h @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -27,6 +28,7 @@ enum class async_msg_type { log, flush, terminate }; struct async_msg : log_msg_buffer { async_msg_type msg_type{async_msg_type::log}; async_logger_ptr worker_ptr; + std::unique_ptr> promise; async_msg() = default; ~async_msg() = default; @@ -56,12 +58,20 @@ struct async_msg : log_msg_buffer { async_msg(async_logger_ptr &&worker, async_msg_type the_type, const details::log_msg &m) : log_msg_buffer{m}, msg_type{the_type}, - worker_ptr{std::move(worker)} {} + worker_ptr{std::move(worker)}, + promise{nullptr} {} async_msg(async_logger_ptr &&worker, async_msg_type the_type) : log_msg_buffer{}, msg_type{the_type}, - worker_ptr{std::move(worker)} {} + worker_ptr{std::move(worker)}, + promise{nullptr} {} + + async_msg(async_logger_ptr &&worker, async_msg_type the_type, std::unique_ptr> promise) + : log_msg_buffer{}, + msg_type{the_type}, + worker_ptr{std::move(worker)}, + promise{std::move(promise)} {} explicit async_msg(async_msg_type the_type) : async_msg{nullptr, the_type} {} @@ -88,7 +98,8 @@ class SPDLOG_API thread_pool { void post_log(async_logger_ptr &&worker_ptr, const details::log_msg &msg, async_overflow_policy overflow_policy); - void post_flush(async_logger_ptr &&worker_ptr, async_overflow_policy overflow_policy); + std::future post_flush(async_logger_ptr &&worker_ptr, + async_overflow_policy overflow_policy); size_t overrun_counter(); void reset_overrun_counter(); size_t discard_counter();