thread_pool.h 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. // Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
  2. // Distributed under the MIT License (http://opensource.org/licenses/MIT)
  3. #pragma once
  4. #include <spdlog/details/log_msg_buffer.h>
  5. #include <spdlog/details/mpmc_blocking_q.h>
  6. #include <spdlog/details/os.h>
  7. #include <chrono>
  8. #include <functional>
  9. #include <future>
  10. #include <memory>
  11. #include <thread>
  12. #include <vector>
  13. namespace spdlog {
  14. class async_logger;
  15. namespace details {
  16. using async_logger_ptr = std::shared_ptr<spdlog::async_logger>;
  17. enum class async_msg_type { log, flush, terminate };
  18. // Async msg to move to/from the queue
  19. // Movable only. should never be copied
  20. struct async_msg : log_msg_buffer {
  21. async_msg_type msg_type{async_msg_type::log};
  22. async_logger_ptr worker_ptr;
  23. std::promise<void> flush_promise;
  24. async_msg() = default;
  25. ~async_msg() = default;
  26. // should only be moved in or out of the queue..
  27. async_msg(const async_msg &) = delete;
  28. // support for vs2013 move
  29. #if defined(_MSC_VER) && _MSC_VER <= 1800
  30. async_msg(async_msg &&other)
  31. : log_msg_buffer(std::move(other)),
  32. msg_type(other.msg_type),
  33. worker_ptr(std::move(other.worker_ptr)) {}
  34. async_msg &operator=(async_msg &&other) {
  35. *static_cast<log_msg_buffer *>(this) = std::move(other);
  36. msg_type = other.msg_type;
  37. worker_ptr = std::move(other.worker_ptr);
  38. return *this;
  39. }
  40. #else // (_MSC_VER) && _MSC_VER <= 1800
  41. async_msg(async_msg &&) = default;
  42. async_msg &operator=(async_msg &&) = default;
  43. #endif
  44. // construct from log_msg with given type
  45. async_msg(async_logger_ptr &&worker, async_msg_type the_type, const details::log_msg &m)
  46. : log_msg_buffer{m},
  47. msg_type{the_type},
  48. worker_ptr{std::move(worker)},
  49. flush_promise{} {}
  50. async_msg(async_logger_ptr &&worker, async_msg_type the_type)
  51. : log_msg_buffer{},
  52. msg_type{the_type},
  53. worker_ptr{std::move(worker)},
  54. flush_promise{} {}
  55. async_msg(async_logger_ptr &&worker, async_msg_type the_type, std::promise<void> &&promise)
  56. : log_msg_buffer{},
  57. msg_type{the_type},
  58. worker_ptr{std::move(worker)},
  59. flush_promise{std::move(promise)} {}
  60. explicit async_msg(async_msg_type the_type)
  61. : async_msg{nullptr, the_type} {}
  62. };
  63. class SPDLOG_API thread_pool {
  64. public:
  65. using item_type = async_msg;
  66. using q_type = details::mpmc_blocking_queue<item_type>;
  67. thread_pool(size_t q_max_items,
  68. size_t threads_n,
  69. std::function<void()> on_thread_start,
  70. std::function<void()> on_thread_stop);
  71. thread_pool(size_t q_max_items, size_t threads_n, std::function<void()> on_thread_start);
  72. thread_pool(size_t q_max_items, size_t threads_n);
  73. // message all threads to terminate gracefully and join them
  74. ~thread_pool();
  75. thread_pool(const thread_pool &) = delete;
  76. thread_pool &operator=(thread_pool &&) = delete;
  77. void post_log(async_logger_ptr &&worker_ptr,
  78. const details::log_msg &msg,
  79. async_overflow_policy overflow_policy);
  80. std::future<void> post_flush(async_logger_ptr &&worker_ptr,
  81. async_overflow_policy overflow_policy);
  82. size_t overrun_counter();
  83. void reset_overrun_counter();
  84. size_t discard_counter();
  85. void reset_discard_counter();
  86. size_t queue_size();
  87. private:
  88. q_type q_;
  89. std::vector<std::thread> threads_;
  90. void post_async_msg_(async_msg &&new_msg, async_overflow_policy overflow_policy);
  91. void worker_loop_();
  92. // process next message in the queue
  93. // return true if this thread should still be active (while no terminate msg
  94. // was received)
  95. bool process_next_msg_();
  96. };
  97. } // namespace details
  98. } // namespace spdlog
  99. #ifdef SPDLOG_HEADER_ONLY
  100. #include "thread_pool-inl.h"
  101. #endif