diff --git a/include/spdlog/.spdlog.h.kate-swp b/include/spdlog/.spdlog.h.kate-swp deleted file mode 100644 index 546ce39c..00000000 Binary files a/include/spdlog/.spdlog.h.kate-swp and /dev/null differ diff --git a/include/spdlog/details/os.h b/include/spdlog/details/os.h index 0467e944..5cf97635 100644 --- a/include/spdlog/details/os.h +++ b/include/spdlog/details/os.h @@ -68,9 +68,9 @@ size_t thread_id() SPDLOG_NOEXCEPT; // See https://github.com/gabime/spdlog/issues/609 void sleep_for_millis(int milliseconds) SPDLOG_NOEXCEPT; -std::string filename_to_str(const filename_t &filename); +std::string filename_to_str(const filename_t &filename) SPDLOG_NOEXCEPT; -int pid(); +int pid() SPDLOG_NOEXCEPT; // Determine if the terminal supports colors // Source: https://github.com/agauniyal/rang/ diff --git a/include/spdlog/details/periodic_worker.h b/include/spdlog/details/periodic_worker.h index fa6488d1..9e9cd731 100644 --- a/include/spdlog/details/periodic_worker.h +++ b/include/spdlog/details/periodic_worker.h @@ -23,43 +23,12 @@ namespace details { class periodic_worker { public: - periodic_worker(const std::function &callback_fun, std::chrono::seconds interval) - { - active_ = (interval > std::chrono::seconds::zero()); - if (!active_) - { - return; - } - - worker_thread_ = std::thread([this, callback_fun, interval]() { - for (;;) - { - std::unique_lock lock(this->mutex_); - if (this->cv_.wait_for(lock, interval, [this] { return !this->active_; })) - { - return; // active_ == false, so exit this thread - } - callback_fun(); - } - }); - } - + periodic_worker(const std::function &callback_fun, std::chrono::seconds interval); periodic_worker(const periodic_worker &) = delete; periodic_worker &operator=(const periodic_worker &) = delete; - // stop the worker thread and join it - ~periodic_worker() - { - if (worker_thread_.joinable()) - { - { - std::lock_guard lock(mutex_); - active_ = false; - } - cv_.notify_one(); - worker_thread_.join(); - } - } + ~periodic_worker(); + private: bool active_; @@ -69,3 +38,8 @@ private: }; } // namespace details } // namespace spdlog + + +#ifndef SPDLOG_STATIC_LIB +#include "spdlog/impl/periodic_worker.cpp" +#endif diff --git a/include/spdlog/details/thread_pool.h b/include/spdlog/details/thread_pool.h index a1efcee6..80c2d11f 100644 --- a/include/spdlog/details/thread_pool.h +++ b/include/spdlog/details/thread_pool.h @@ -123,118 +123,36 @@ public: using item_type = async_msg; using q_type = details::mpmc_blocking_queue; - thread_pool(size_t q_max_items, size_t threads_n) - : q_(q_max_items) - { - // std::cout << "thread_pool() q_size_bytes: " << q_size_bytes << - // "\tthreads_n: " << threads_n << std::endl; - if (threads_n == 0 || threads_n > 1000) - { - throw spdlog_ex("spdlog::thread_pool(): invalid threads_n param (valid " - "range is 1-1000)"); - } - for (size_t i = 0; i < threads_n; i++) - { - threads_.emplace_back(&thread_pool::worker_loop_, this); - } - } - + thread_pool(size_t q_max_items, size_t threads_n); // message all threads to terminate gracefully join them - ~thread_pool() - { - try - { - for (size_t i = 0; i < threads_.size(); i++) - { - post_async_msg_(async_msg(async_msg_type::terminate), async_overflow_policy::block); - } + ~thread_pool(); - for (auto &t : threads_) - { - t.join(); - } - } - catch (...) - { - } - } thread_pool(const thread_pool &) = delete; thread_pool &operator=(thread_pool &&) = delete; - void post_log(async_logger_ptr &&worker_ptr, details::log_msg &msg, async_overflow_policy overflow_policy) - { - async_msg async_m(std::move(worker_ptr), async_msg_type::log, msg); - post_async_msg_(std::move(async_m), overflow_policy); - } + void post_log(async_logger_ptr &&worker_ptr, details::log_msg &msg, async_overflow_policy overflow_policy); + void post_flush(async_logger_ptr &&worker_ptr, async_overflow_policy overflow_policy); + size_t overrun_counter(); - void 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); - } - - size_t overrun_counter() - { - return q_.overrun_counter(); - } private: q_type q_; std::vector threads_; - void post_async_msg_(async_msg &&new_msg, async_overflow_policy overflow_policy) - { - if (overflow_policy == async_overflow_policy::block) - { - q_.enqueue(std::move(new_msg)); - } - else - { - q_.enqueue_nowait(std::move(new_msg)); - } - } - - void worker_loop_() - { - while (process_next_msg_()) {}; - } + void post_async_msg_(async_msg &&new_msg, async_overflow_policy overflow_policy); + void worker_loop_(); // process next message in the queue // return true if this thread should still be active (while no terminate msg // was received) - bool process_next_msg_() - { - async_msg incoming_async_msg; - bool dequeued = q_.dequeue_for(incoming_async_msg, std::chrono::seconds(10)); - if (!dequeued) - { - return true; - } - - switch (incoming_async_msg.msg_type) - { - case async_msg_type::log: - { - auto msg = incoming_async_msg.to_log_msg(); - incoming_async_msg.worker_ptr->backend_log_(msg); - return true; - } - case async_msg_type::flush: - { - incoming_async_msg.worker_ptr->backend_flush_(); - return true; - } - - case async_msg_type::terminate: - { - return false; - } - } - assert(false && "Unexpected async_msg_type"); - return true; - } + bool process_next_msg_(); }; } // namespace details } // namespace spdlog + +#ifndef SPDLOG_STATIC_LIB +#include "spdlog/impl/thread_pool.cpp" +#endif \ No newline at end of file diff --git a/include/spdlog/impl/os.cpp b/include/spdlog/impl/os.cpp index e4260dba..ed174cf1 100644 --- a/include/spdlog/impl/os.cpp +++ b/include/spdlog/impl/os.cpp @@ -340,19 +340,19 @@ SPDLOG_INLINE void sleep_for_millis(int milliseconds) SPDLOG_NOEXCEPT // wchar support for windows file names (SPDLOG_WCHAR_FILENAMES must be defined) #if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES) -SPDLOG_INLINE std::string filename_to_str(const filename_t &filename) +SPDLOG_INLINE std::string filename_to_str(const filename_t &filename) SPDLOG_NOEXCEPT { std::wstring_convert, wchar_t> c; return c.to_bytes(filename); } #else -SPDLOG_INLINE std::string filename_to_str(const filename_t &filename) +SPDLOG_INLINE std::string filename_to_str(const filename_t &filename) SPDLOG_NOEXCEPT { return filename; } #endif -SPDLOG_INLINE int pid() +SPDLOG_INLINE int pid() SPDLOG_NOEXCEPT { #ifdef _WIN32 diff --git a/include/spdlog/impl/periodic_worker.cpp b/include/spdlog/impl/periodic_worker.cpp new file mode 100644 index 00000000..6c0e997d --- /dev/null +++ b/include/spdlog/impl/periodic_worker.cpp @@ -0,0 +1,45 @@ +// +// Created by gabi on 5/8/19. +// + +#ifdef SPDLOG_STATIC_LIB +#include "spdlog/details/periodic_worker.h" +#endif + +#include "spdlog/common.h" + +SPDLOG_INLINE spdlog::details::periodic_worker::periodic_worker(const std::function &callback_fun, std::chrono::seconds interval) +{ + active_ = (interval > std::chrono::seconds::zero()); + if (!active_) + { + return; + } + + worker_thread_ = std::thread([this, callback_fun, interval]() { + for (;;) + { + std::unique_lock lock(this->mutex_); + if (this->cv_.wait_for(lock, interval, [this] { return !this->active_; })) + { + return; // active_ == false, so exit this thread + } + callback_fun(); + } + }); +} + +// stop the worker thread and join it +SPDLOG_INLINE spdlog::details::periodic_worker::~periodic_worker() +{ + if (worker_thread_.joinable()) + { + { + std::lock_guard lock(mutex_); + active_ = false; + } + cv_.notify_one(); + worker_thread_.join(); + } +} + diff --git a/include/spdlog/impl/thread_pool.cpp b/include/spdlog/impl/thread_pool.cpp new file mode 100644 index 00000000..66c26fd6 --- /dev/null +++ b/include/spdlog/impl/thread_pool.cpp @@ -0,0 +1,116 @@ +#ifdef SPDLOG_STATIC_LIB +#include "spdlog/async_logger.h" +#include "spdlog/details/thread_pool.h" + +template class spdlog::details::mpmc_blocking_queue; + +#endif + +#include "spdlog/common.h" + +SPDLOG_INLINE spdlog::details::thread_pool::thread_pool(size_t q_max_items, size_t threads_n) : q_(q_max_items) +{ + // std::cout << "thread_pool() q_size_bytes: " << q_size_bytes << + // "\tthreads_n: " << threads_n << std::endl; + if (threads_n == 0 || threads_n > 1000) + { + throw spdlog_ex("spdlog::thread_pool(): invalid threads_n param (valid " + "range is 1-1000)"); + } + for (size_t i = 0; i < threads_n; i++) + { + threads_.emplace_back(&thread_pool::worker_loop_, this); + } +} + +// message all threads to terminate gracefully join them +SPDLOG_INLINE spdlog::details::thread_pool::~thread_pool() +{ + try + { + for (size_t i = 0; i < threads_.size(); i++) + { + post_async_msg_(async_msg(async_msg_type::terminate), async_overflow_policy::block); + } + + for (auto &t : threads_) + { + t.join(); + } + } + catch (...) + { + } +} + +void SPDLOG_INLINE spdlog::details::thread_pool::post_log(async_logger_ptr &&worker_ptr, details::log_msg &msg, async_overflow_policy overflow_policy) +{ + async_msg async_m(std::move(worker_ptr), async_msg_type::log, msg); + post_async_msg_(std::move(async_m), overflow_policy); +} + +void SPDLOG_INLINE spdlog::details::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); +} + +size_t SPDLOG_INLINE spdlog::details::thread_pool::overrun_counter() +{ + return q_.overrun_counter(); +} + +void SPDLOG_INLINE spdlog::details::thread_pool::post_async_msg_(async_msg &&new_msg, async_overflow_policy overflow_policy) +{ + if (overflow_policy == async_overflow_policy::block) + { + q_.enqueue(std::move(new_msg)); + } + else + { + q_.enqueue_nowait(std::move(new_msg)); + } +} + +void SPDLOG_INLINE spdlog::details::thread_pool::worker_loop_() +{ + while (process_next_msg_()) {}; +} + +// process next message in the queue +// return true if this thread should still be active (while no terminate msg +// was received) +bool SPDLOG_INLINE spdlog::details::thread_pool::process_next_msg_() +{ + async_msg incoming_async_msg; + bool dequeued = q_.dequeue_for(incoming_async_msg, std::chrono::seconds(10)); + if (!dequeued) + { + return true; + } + + switch (incoming_async_msg.msg_type) + { + case async_msg_type::log: + { + auto msg = incoming_async_msg.to_log_msg(); + incoming_async_msg.worker_ptr->backend_log_(msg); + return true; + } + case async_msg_type::flush: + { + incoming_async_msg.worker_ptr->backend_flush_(); + return true; + } + + case async_msg_type::terminate: + { + return false; + } + } + assert(false && "Unexpected async_msg_type"); + return true; +} + + + +