| 26 | |
| 27 | template<typename T> |
| 28 | void ThreadPool<T>::run_tasks(std::shared_ptr<WorkerThread> thread) { |
| 29 | thread->is_running_ = true; |
| 30 | while (running_.load()) { |
| 31 | if (UNLIKELY(thread_reduction_count_ > 0)) { |
| 32 | if (--thread_reduction_count_ >= 0) { |
| 33 | deceased_thread_queue_.enqueue(thread); |
| 34 | thread->is_running_ = false; |
| 35 | break; |
| 36 | } else { |
| 37 | thread_reduction_count_++; |
| 38 | } |
| 39 | } |
| 40 | |
| 41 | Worker<T> task; |
| 42 | if (worker_queue_.dequeueWait(task)) { |
| 43 | { |
| 44 | std::unique_lock<std::mutex> lock(worker_queue_mutex_); |
| 45 | if (!task_status_[task.getIdentifier()]) { |
| 46 | continue; |
| 47 | } |
| 48 | } |
| 49 | if (task.run()) { |
| 50 | if (task.getNextExecutionTime() <= std::chrono::steady_clock::now()) { |
| 51 | // it can be rescheduled again as soon as there is a worker available |
| 52 | worker_queue_.enqueue(std::move(task)); |
| 53 | continue; |
| 54 | } |
| 55 | // Task will be put to the delayed queue as next exec time is in the future |
| 56 | std::unique_lock<std::mutex> lock(worker_queue_mutex_); |
| 57 | bool need_to_notify = |
| 58 | delayed_worker_queue_.empty() || |
| 59 | task.getNextExecutionTime() < delayed_worker_queue_.top().getNextExecutionTime(); |
| 60 | |
| 61 | delayed_worker_queue_.push(std::move(task)); |
| 62 | if (need_to_notify) { |
| 63 | delayed_task_available_.notify_all(); |
| 64 | } |
| 65 | } |
| 66 | } else { |
| 67 | // This means that the threadpool is running, but the ConcurrentQueue is stopped -> shouldn't happen during normal conditions |
| 68 | // Might happen during startup or shutdown for a very short time |
| 69 | if (running_.load()) { |
| 70 | std::this_thread::sleep_for(std::chrono::milliseconds(1)); |
| 71 | } |
| 72 | } |
| 73 | } |
| 74 | current_workers_--; |
| 75 | } |
| 76 | |
| 77 | template<typename T> |
| 78 | void ThreadPool<T>::manage_delayed_queue() { |
nothing calls this directly
no test coverage detected