/** * @file mcp_thread_pool.h * @brief Simple thread pool implementation */ #ifndef MCP_THREAD_POOL_H #define MCP_THREAD_POOL_H #include #include #include #include #include #include #include #include #include namespace mcp { class thread_pool { public: /** * @brief Constructor * @param num_threads Number of threads in the thread pool */ explicit thread_pool(size_t num_threads = std::thread::hardware_concurrency()) : stop_(false) { for (size_t i = 0; i < num_threads; ++i) { workers_.emplace_back([this] { while (true) { std::function task; { std::unique_lock lock(queue_mutex_); condition_.wait(lock, [this] { return stop_ || !tasks_.empty(); }); if (stop_ && tasks_.empty()) { return; } task = std::move(tasks_.front()); tasks_.pop(); } task(); } }); } } /** * @brief Destructor */ ~thread_pool() { { std::unique_lock lock(queue_mutex_); stop_ = true; } condition_.notify_all(); for (std::thread& worker : workers_) { if (worker.joinable()) { worker.join(); } } } /** * @brief Submit task to thread pool * @param f Task function * @param args Task parameters * @return Task future */ template auto enqueue(F&& f, Args&&... args) -> std::future::type> { using return_type = typename std::invoke_result::type; auto task = std::make_shared>( std::bind(std::forward(f), std::forward(args)...) ); std::future result = task->get_future(); { std::unique_lock lock(queue_mutex_); if (stop_) { throw std::runtime_error("Thread pool stopped, cannot add task"); } tasks_.emplace([task]() { (*task)(); }); } condition_.notify_one(); return result; } private: // Worker threads std::vector workers_; // Task queue std::queue> tasks_; // Mutex and condition variable std::mutex queue_mutex_; std::condition_variable condition_; // Stop flag std::atomic stop_; }; } // namespace mcp #endif // MCP_THREAD_POOL_H