ThreadPool implementation
| 10086 | |
| 10087 | // ThreadPool implementation |
| 10088 | inline ThreadPool::ThreadPool(size_t n, size_t max_n, size_t mqr) |
| 10089 | : base_thread_count_(n), max_queued_requests_(mqr), idle_thread_count_(0), |
| 10090 | shutdown_(false) { |
| 10091 | #ifndef CPPHTTPLIB_NO_EXCEPTIONS |
| 10092 | if (max_n != 0 && max_n < n) { |
| 10093 | std::string msg = "max_threads must be >= base_threads"; |
| 10094 | throw std::invalid_argument(msg); |
| 10095 | } |
| 10096 | #endif |
| 10097 | max_thread_count_ = max_n == 0 ? n : max_n; |
| 10098 | threads_.reserve(base_thread_count_); |
| 10099 | #ifndef CPPHTTPLIB_NO_EXCEPTIONS |
| 10100 | try { |
| 10101 | #endif |
| 10102 | for (size_t i = 0; i < base_thread_count_; i++) { |
| 10103 | threads_.emplace_back(std::thread([this]() { worker(false); })); |
| 10104 | } |
| 10105 | #ifndef CPPHTTPLIB_NO_EXCEPTIONS |
| 10106 | } catch (...) { |
| 10107 | // If thread creation fails partway (e.g., pthread_create returns EAGAIN), |
| 10108 | // signal the workers we already spawned to exit and join them so the |
| 10109 | // vector destructor does not see joinable threads (which would call |
| 10110 | // std::terminate). Then rethrow so the caller learns of the failure. |
| 10111 | { |
| 10112 | std::unique_lock<std::mutex> lock(mutex_); |
| 10113 | shutdown_ = true; |
| 10114 | } |
| 10115 | cond_.notify_all(); |
| 10116 | for (auto &t : threads_) { |
| 10117 | if (t.joinable()) { t.join(); } |
| 10118 | } |
| 10119 | throw; |
| 10120 | } |
| 10121 | #endif |
| 10122 | } |
| 10123 | |
| 10124 | inline bool ThreadPool::enqueue(std::function<void()> fn) { |
| 10125 | { |
nothing calls this directly
no outgoing calls
no test coverage detected