浏览代码

Merge pull request #104237 from Ivorforce/optimize-thread-pool-waiting

Optimize thread pools by avoiding needless locks and unlocks of the `task_mutex`.
Rémi Verschelde 5 月之前
父节点
当前提交
1f682b6554
共有 1 个文件被更改,包括 19 次插入11 次删除
  1. 19 11
      core/object/worker_thread_pool.cpp

+ 19 - 11
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()) {
+					// There wasn't a task available yet.
+					// Let's wait for the next notification, then recheck.
+					thread_data->cond_var.wait(lock);
+					continue;
+				}
 
-			if (thread_data->pool->task_queue.first()) {
+				// 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);
 	}
 }