diff --git a/core/object/worker_thread_pool.cpp b/core/object/worker_thread_pool.cpp index d9ff3057679..14a7a6936a1 100644 --- a/core/object/worker_thread_pool.cpp +++ b/core/object/worker_thread_pool.cpp @@ -186,26 +186,34 @@ void WorkerThreadPool::_thread_function(void *p_user) { while (true) { Task *task_to_process = nullptr; { + // Create the lock outside the inner loop so it isn't needlessly unlocked and relocked + // when no task was found to process, and the loop is re-entered. MutexLock lock(thread_data->pool->task_mutex); - bool exit = thread_data->pool->_handle_runlevel(thread_data, lock); - if (unlikely(exit)) { - break; - } + while (true) { + bool exit = thread_data->pool->_handle_runlevel(thread_data, lock); + if (unlikely(exit)) { + return; + } - thread_data->signaled = false; + thread_data->signaled = false; - if (thread_data->pool->task_queue.first()) { + if (!thread_data->pool->task_queue.first()) { + // There wasn't a task available yet. + // Let's wait for the next notification, then recheck. + thread_data->cond_var.wait(lock); + continue; + } + + // Got a task to process! Remove it from the queue, then break into the task handling section. task_to_process = thread_data->pool->task_queue.first()->self(); thread_data->pool->task_queue.remove(thread_data->pool->task_queue.first()); - } else { - thread_data->cond_var.wait(lock); + break; } } - if (task_to_process) { - thread_data->pool->_process_task(task_to_process); - } + DEV_ASSERT(task_to_process); + thread_data->pool->_process_task(task_to_process); } }