#include "Utils/ThreadPool.hpp" #include "precomp.hpp" namespace Chattr { ThreadPool::ThreadPool() { } ThreadPool::ThreadPool(std::uint32_t numThreads) { init(numThreads); } ThreadPool::~ThreadPool() { terminate(); } void ThreadPool::init(std::uint32_t numThreads) { int numCPU = numThreads; if (numThreads == 0) { #ifdef _WIN32 SYSTEM_INFO sysinfo; GetSystemInfo(&sysinfo); numCPU = sysinfo.dwNumberOfProcessors; #elif __linux__ numCPU = sysconf(_SC_NPROCESSORS_ONLN); #endif spdlog::info("Auto-detected cpu count: {}", numCPU); if (numCPU == 1 || numCPU == 2) { numCPU = 4; spdlog::info("Set ThreadPool Worker count to: {} due to program to oprate concurrently", numCPU); } else { spdlog::info("Set ThreadPool Worker count to: {}", numCPU); } } threadCount = numCPU; workers_.reserve(numCPU); while (numCPU--) workers_.push_back([this]() { this->Worker(); }); } void ThreadPool::terminate() { terminate_ = true; jobQueueCV_.notify_all(); spdlog::debug("waiting for threads to end their jobs..."); for (auto& t : workers_) t.join(); } void ThreadPool::respawnWorker(std::uint32_t numThreads) { terminate(); terminate_ = false; init(numThreads); } void* ThreadPool::Worker() { #ifdef _WIN32 DWORD pid = GetCurrentThreadId(); #elif __linux__ pthread_t pid = pthread_self(); #endif spdlog::debug("ThreadPool Worker : {} up", pid); while (!terminate_) { std::unique_lock lock(jobQueueMutex); jobQueueCV_.wait(lock, [this]() { return !this->jobs_.empty() || terminate_; }); if (this->jobs_.empty() || terminate_) { jobs_ = std::queue>(); break; } if (this->jobs_.empty()) continue; auto job = std::move(jobs_.front()); jobs_.pop(); lock.unlock(); spdlog::debug("ThreadPool Worker : {} Executing a job", pid); job(); } spdlog::debug("ThreadPool Worker : {} down", pid); return nullptr; } }