#include #include #include #include #include #include #include class thread_pool { public: thread_pool(std::size_t size) : stop(false), exit_on_empty(false) { for (std::size_t i = 0; i < size; ++i) { workers.emplace_back([this] { spawn(); }); } } virtual ~thread_pool() { if (!stop) join(); } // template // void post(F&& f, Args&&... args) { void post(std::function f) { { std::unique_lock lock(mutex); tasks.push(f); } condition.notify_one(); } void join() { { std::unique_lock lock(mutex); stop = true; } condition.notify_all(); for (std::size_t i = 0; i < workers.size(); ++i) { workers[i].join(); } } void finish_tasks() { { std::unique_lock lock(mutex); exit_on_empty = true; } while (!tasks.empty()) { condition.notify_all(); std::unique_lock lock(mutex); condition_empty.wait(lock, [this]() { return (tasks.empty()); }); } // BLEJU, BLEJU // while (!tasks.empty()) condition.notify_all(); bool op = true; } private: void spawn() { std::function task; while (!stop && (!exit_on_empty || !tasks.empty())) { std::unique_lock lock(mutex); condition.wait(lock, [this]() { return (!tasks.empty()) || (tasks.empty() && stop); }); if (!tasks.empty()) { task = std::move(tasks.front()); tasks.pop(); task(); } } if (exit_on_empty) { condition_empty.notify_one(); } } public: std::vector workers; std::queue> tasks; std::mutex mutex; std::condition_variable condition; std::condition_variable condition_empty; bool stop; bool exit_on_empty; }; // template // inline void dispatch(thread_pool& pool, F&& f, Args&&... args) { inline void dispatch(thread_pool& pool, std::function f) { pool.post(f); } // int main() { // int cnt = 0; // thread_pool tp{std::thread::hardware_concurrency()}; // std::mutex mutex; // std::cout << "start" << std::endl; // for(int i=0; i<100; i++) { // dispatch(tp, std::function // ([i, &cnt, &mutex]() { // std::cout << "test " << i << std::endl; // { // std::unique_lock lock(mutex); // cnt++; // } // } // )); // } // std::cout << "end" << std::endl; // tp.join(); // std::cout << "cnt:" << cnt << std::endl; // }