#pragma once #include #include #include #include #include #include #include #include namespace utils { class ThreadPool { public: ThreadPool(); ThreadPool(std::uint32_t numThreads); ~ThreadPool(); void init(std::uint32_t numThreads); void terminate(); void respawnWorker(std::uint32_t numThreads); template requires( !std::is_void_v>) int enqueueJob(_Callable&& __job, std::invoke_result_t<_Callable, _Args...>& retVal, _Args&&... __args) { if (terminate_) { spdlog::error("Cannot run jobs on threads that terminating..."); return -1; } std::lock_guard lock(jobQueueMutex); auto boundFunc = [this, &retVal, __job, ... __args = std::move(__args)]() mutable { retVal = __job(this, std::move(__args)...); }; auto task = std::packaged_task(std::move(boundFunc)); jobs_.push(std::move(task)); jobQueueCV_.notify_one(); return 0; } template requires std::is_void_v< std::invoke_result_t<_Callable, ThreadPool*, _Args...>> int enqueueJob(_Callable&& __job, _Args&&... __args) { if (terminate_) { spdlog::error("Cannot run jobs on threads that terminating..."); return -1; } std::lock_guard lock(jobQueueMutex); auto boundFunc = [this, __job, ... __args = std::move(__args)]() mutable { __job(this, std::move(__args)...); }; auto task = std::packaged_task(std::move(boundFunc)); jobs_.push(std::move(task)); jobQueueCV_.notify_one(); return 0; } int threadCount = 0; private: void* Worker(); std::condition_variable jobQueueCV_; std::mutex jobQueueMutex; std::queue> jobs_; std::vector workers_; bool terminate_ = false; }; } // namespace Chattr