From 78e19d66d35bfbbbe350b49a09ec9e2645c478f2 Mon Sep 17 00:00:00 2001 From: gabime Date: Thu, 8 May 2025 15:33:08 +0300 Subject: [PATCH] Add register_or_replace(logger) to atomically replace logger in registry --- include/spdlog/details/registry-inl.h | 11 ++++++++++- include/spdlog/details/registry.h | 2 ++ include/spdlog/spdlog-inl.h | 4 ++++ include/spdlog/spdlog.h | 5 +++++ tests/test_registry.cpp | 12 ++++++++++++ 5 files changed, 33 insertions(+), 1 deletion(-) diff --git a/include/spdlog/details/registry-inl.h b/include/spdlog/details/registry-inl.h index f447848e..4cbdeb75 100644 --- a/include/spdlog/details/registry-inl.h +++ b/include/spdlog/details/registry-inl.h @@ -54,6 +54,11 @@ SPDLOG_INLINE void registry::register_logger(std::shared_ptr new_logger) register_logger_(std::move(new_logger)); } +SPDLOG_INLINE void registry::register_or_replace(std::shared_ptr new_logger) { + std::lock_guard lock(logger_map_mutex_); + register_or_replace_(std::move(new_logger)); +} + SPDLOG_INLINE void registry::initialize_logger(std::shared_ptr new_logger) { std::lock_guard lock(logger_map_mutex_); new_logger->set_formatter(formatter_->clone()); @@ -252,10 +257,14 @@ SPDLOG_INLINE void registry::throw_if_exists_(const std::string &logger_name) { } SPDLOG_INLINE void registry::register_logger_(std::shared_ptr new_logger) { - auto logger_name = new_logger->name(); + auto &logger_name = new_logger->name(); throw_if_exists_(logger_name); loggers_[logger_name] = std::move(new_logger); } +SPDLOG_INLINE void registry::register_or_replace_(std::shared_ptr new_logger) { + loggers_[new_logger->name()] = std::move(new_logger); +} + } // namespace details } // namespace spdlog diff --git a/include/spdlog/details/registry.h b/include/spdlog/details/registry.h index 8afcbd6f..72c70b82 100644 --- a/include/spdlog/details/registry.h +++ b/include/spdlog/details/registry.h @@ -31,6 +31,7 @@ public: registry &operator=(const registry &) = delete; void register_logger(std::shared_ptr new_logger); + void register_or_replace(std::shared_ptr new_logger); void initialize_logger(std::shared_ptr new_logger); std::shared_ptr get(const std::string &logger_name); std::shared_ptr default_logger(); @@ -105,6 +106,7 @@ private: void throw_if_exists_(const std::string &logger_name); void register_logger_(std::shared_ptr new_logger); + void register_or_replace_(std::shared_ptr new_logger); bool set_level_from_cfg_(logger *logger); std::mutex logger_map_mutex_, flusher_mutex_; std::recursive_mutex tp_mutex_; diff --git a/include/spdlog/spdlog-inl.h b/include/spdlog/spdlog-inl.h index 97c36222..e02081fe 100644 --- a/include/spdlog/spdlog-inl.h +++ b/include/spdlog/spdlog-inl.h @@ -59,6 +59,10 @@ SPDLOG_INLINE void register_logger(std::shared_ptr logger) { details::registry::instance().register_logger(std::move(logger)); } +SPDLOG_INLINE void register_or_replace(std::shared_ptr logger) { + details::registry::instance().register_or_replace(std::move(logger)); +} + SPDLOG_INLINE void apply_all(const std::function)> &fun) { details::registry::instance().apply_all(fun); } diff --git a/include/spdlog/spdlog.h b/include/spdlog/spdlog.h index 36e7f77d..b51b470b 100644 --- a/include/spdlog/spdlog.h +++ b/include/spdlog/spdlog.h @@ -91,8 +91,13 @@ inline void flush_every(std::chrono::duration interval) { SPDLOG_API void set_error_handler(void (*handler)(const std::string &msg)); // Register the given logger with the given name +// Will throw if a logger with the same name already exists. SPDLOG_API void register_logger(std::shared_ptr logger); +// Register the given logger with the given name +// Will replace any the existing logger with the same name if exists. +SPDLOG_API void register_or_replace(std::shared_ptr logger); + // Apply a user-defined function on all registered loggers // Example: // spdlog::apply_all([&](std::shared_ptr l) {l->flush();}); diff --git a/tests/test_registry.cpp b/tests/test_registry.cpp index 69ec8f53..6397f2a3 100644 --- a/tests/test_registry.cpp +++ b/tests/test_registry.cpp @@ -25,6 +25,18 @@ TEST_CASE("explicit register", "[registry]") { } #endif +TEST_CASE("register_or_replace", "[registry]") { + spdlog::drop_all(); + auto logger1 = std::make_shared(tested_logger_name, + std::make_shared()); + spdlog::register_logger(logger1); + REQUIRE(spdlog::get(tested_logger_name) == logger1); + + auto logger2 = std::make_shared(tested_logger_name, std::make_shared()); + spdlog::register_or_replace(logger2); + REQUIRE(spdlog::get(tested_logger_name) == logger2); +} + TEST_CASE("apply_all", "[registry]") { spdlog::drop_all(); auto logger = std::make_shared(tested_logger_name,