#include #include #include #include #include #include #include #include #include #include template struct ThreadPool { public: using Job = std::packaged_task; ThreadPool(unsigned int nof_threads) : nof_threads(nof_threads), active(0), finished(false), threads(nof_threads) { for (auto& t: threads) { t = std::thread([=]() { process_jobs(); }); } } ~ThreadPool() { { std::unique_lock lock(mutex); finished = true; } cv.notify_all(); for (auto& t: threads) { t.join(); } } template std::future submit(Task task) { Job job(task); auto result = job.get_future(); std::unique_lock lock(mutex); jobs.push_back(std::move(job)); cv.notify_one(); return result; } private: unsigned int nof_threads; unsigned int active; bool finished; std::vector threads; std::mutex mutex; std::condition_variable cv; std::list jobs; void process_jobs() { for(;;) { Job job; /* fetch job */ { std::unique_lock lock(mutex); while (jobs.empty() && (active > 0 || !finished)) { cv.wait(lock); } if (jobs.empty() && active == 0 && finished) break; job = std::move(jobs.front()); jobs.pop_front(); ++active; } /* execute job */ job(); { std::unique_lock lock(mutex); --active; } } /* if one thread finishes, all others have to finish as well */ cv.notify_all(); } }; int main() { ThreadPool pool(2); auto result = pool.submit([&]() -> int { std::printf("Hello!\n"); return 42; }); std::printf("Job returned %d\n", result.get()); }