#include <iostream> #include <vector> #include <thread> #include <queue> #include <functional> #include <condition_variable> #include <atomic> class ThreadPool { public: ThreadPool(size_t numThreads) : stop(false) { for (size_t i = 0; i < numThreads; ++i) { workers.emplace_back([this] { while (true) { std::function<void()> task; // Lock the queue to retrieve the next task { std::unique_lock<std::mutex> lock(queueMutex); condition.wait(lock, [this] { return stop || !tasks.empty(); }); if (stop && tasks.empty()) { return; } // Get the next task from the queue task = std::move(tasks.front()); tasks.pop(); } // Execute the task task(); } }); } } // Submit a task to the thread pool template <typename F> void enqueue(F&& f) { { std::unique_lock<std::mutex> lock(queueMutex); if (stop) { throw std::runtime_error("ThreadPool is stopped"); } tasks.push(std::function<void()>(std::forward<F>(f))); } condition.notify_one(); } // Wait for all threads to finish executing their tasks void wait() { // Block until all tasks have been completed std::unique_lock<std::mutex> lock(queueMutex); condition.wait(lock, [this] { return tasks.empty(); }); } // Destructor: join all threads ~ThreadPool() { { std::unique_lock<std::mutex> lock(queueMutex); stop = true; } condition.notify_all(); for (std::thread& worker : workers) { worker.join(); // Ensure each thread finishes before destruction } } private: std::vector<std::thread> workers; std::queue<std::function<void()>> tasks; std::mutex queueMutex; std::condition_variable condition; bool stop; };