* A ThreadPool class for managing and dispatching tasks to a number of threads. **/
| 28 | * A ThreadPool class for managing and dispatching tasks to a number of threads. |
| 29 | **/ |
| 30 | class ThreadPool { |
| 31 | public: |
| 32 | /** |
| 33 | * Create "n_threads" workers, each with a dedicated task queue, and execute |
| 34 | * the task as they arrive in the queues. |
| 35 | **/ |
| 36 | ThreadPool(unsigned int n_threads = get_concurrency()) |
| 37 | : m_queues(n_threads), m_count(n_threads) { |
| 38 | assert(n_threads != 0); |
| 39 | auto worker = [&](unsigned int i) { |
| 40 | while (true) { |
| 41 | Proc f; |
| 42 | if (!m_queues[i].pop(f)) break; |
| 43 | f(); |
| 44 | } |
| 45 | }; |
| 46 | for (unsigned int i = 0; i < n_threads; ++i) |
| 47 | m_workers.emplace_back(worker, i); |
| 48 | } |
| 49 | |
| 50 | ~ThreadPool() noexcept { |
| 51 | for (auto& queue : m_queues) queue.done(); |
| 52 | for (auto& worker : m_workers) worker.join(); |
| 53 | } |
| 54 | |
| 55 | /** |
| 56 | * enqueue_task() assigns tasks to worker queues using round robin |
| 57 | *scheduling. |
| 58 | * @returns a std::future object with the result of the task. |
| 59 | **/ |
| 60 | template <typename F, typename... Args> |
| 61 | auto enqueue_task(F&& f, Args&&... args) |
| 62 | -> std::future<typename std::result_of<F(Args...)>::type> { |
| 63 | using return_type = typename std::result_of<F(Args...)>::type; |
| 64 | |
| 65 | auto task = std::make_shared<std::packaged_task<return_type()>>( |
| 66 | std::bind(std::forward<F>(f), std::forward<Args>(args)...)); |
| 67 | std::future<return_type> res = task->get_future(); |
| 68 | auto work = [task]() { (*task)(); }; |
| 69 | |
| 70 | unsigned int i = m_index++; |
| 71 | m_queues[i % m_count].push(work); |
| 72 | |
| 73 | return res; |
| 74 | } |
| 75 | |
| 76 | private: |
| 77 | using Proc = std::function<void(void)>; |
| 78 | |
| 79 | using Queues = std::vector<blocking_queue<Proc>>; |
| 80 | Queues m_queues; |
| 81 | |
| 82 | using Threads = std::vector<std::thread>; |
| 83 | Threads m_workers; |
| 84 | |
| 85 | const unsigned int m_count; |
| 86 | std::atomic_uint m_index = 0; |
| 87 | }; |
nothing calls this directly
no outgoing calls
no test coverage detected