| bool running; | bool running; | ||||
| std::function<void(void)> func; | std::function<void(void)> func; | ||||
| std::condition_variable cond; | std::condition_variable cond; | ||||
| std::mutex mut; | |||||
| std::thread thread; | std::thread thread; | ||||
| Worker *next_worker; | Worker *next_worker; | ||||
| static int waiting = 0; | static int waiting = 0; | ||||
| static void workerFunc(Worker *w) { | static void workerFunc(Worker *w) { | ||||
| std::unique_lock<std::mutex> lock(w->mut); | |||||
| while (true) { | while (true) { | ||||
| std::unique_lock<std::mutex> lock(workers_mut); | |||||
| w->cond.wait(lock, [w] { return (bool)w->func || !w->running; }); | w->cond.wait(lock, [w] { return (bool)w->func || !w->running; }); | ||||
| if (!w->running) | if (!w->running) | ||||
| break; | break; | ||||
| lock.unlock(); | |||||
| w->func(); | w->func(); | ||||
| lock.lock(); | |||||
| w->func = nullptr; | w->func = nullptr; | ||||
| std::unique_lock<std::mutex> workers_lock(workers_mut); | |||||
| w->next_worker = head; | w->next_worker = head; | ||||
| head = w; | head = w; | ||||
| workers_lock.unlock(); | |||||
| workers_cond.notify_one(); | |||||
| threads_running -= 1; | threads_running -= 1; | ||||
| lock.unlock(); | |||||
| workers_cond.notify_one(); | |||||
| } | } | ||||
| } | } | ||||
| Worker *w = head; | Worker *w = head; | ||||
| while (w) { | while (w) { | ||||
| w->running = false; | w->running = false; | ||||
| lock.unlock(); | |||||
| w->cond.notify_one(); | w->cond.notify_one(); | ||||
| w = w->next_worker; | |||||
| } | |||||
| w = head; | |||||
| while (w) { | |||||
| w->thread.join(); | w->thread.join(); | ||||
| lock.lock(); | |||||
| w = w->next_worker; | w = w->next_worker; | ||||
| } | } | ||||
| head = head->next_worker; | head = head->next_worker; | ||||
| threads_running += 1; | threads_running += 1; | ||||
| waiting -= 1; | waiting -= 1; | ||||
| lock.unlock(); | |||||
| // Launch! | // Launch! | ||||
| w->func = std::move(func); | w->func = std::move(func); | ||||
| lock.unlock(); | |||||
| w->cond.notify_one(); | w->cond.notify_one(); | ||||
| } | } | ||||