Fix a deadlock in WorkerThreadPool
When the main thread is waiting on a worker thread pool via WorkerThreadPool::wait_for_group_task_completion() the MessageQueue is no longer being serviced. But in ResourceLoader::_load_complete_inner we need to be able to push a callable onto the MessageQueue and we wait until completion. Effectively waiting on the main thread to run our code. If the tasking waiting on completion is in the group the main thread is waiting for then this can never happen. We solve this problem by servicing the MessageQueue in the WorkerThreadPool if main thread is waiting. To avoid busy waiting on the semaphore we sleep for a very brief time to spare battery without impacting latency too much in the waiting case.
This commit is contained in:
@@ -452,7 +452,18 @@ Error WorkerThreadPool::wait_for_task_completion(TaskID p_task_id) {
|
||||
}
|
||||
} else {
|
||||
task_mutex.unlock();
|
||||
task->done_semaphore.wait();
|
||||
if (Thread::is_main_thread()) {
|
||||
// If we are the main thread we can't block the messagequeue
|
||||
while (!task->done_semaphore.try_wait()) {
|
||||
if (MessageQueue::get_singleton()) {
|
||||
MessageQueue::get_singleton()->flush();
|
||||
}
|
||||
|
||||
OS::get_singleton()->delay_usec(100);
|
||||
}
|
||||
} else {
|
||||
task->done_semaphore.wait();
|
||||
}
|
||||
task_mutex.lock();
|
||||
task->waiting_user--;
|
||||
if (task->waiting_pool == 0 && task->waiting_user == 0) {
|
||||
@@ -739,7 +750,18 @@ void WorkerThreadPool::wait_for_group_task_completion(GroupID p_group) {
|
||||
if (this == singleton) {
|
||||
_unlock_unlockable_mutexes();
|
||||
}
|
||||
group->done_semaphore.wait();
|
||||
if (Thread::is_main_thread()) {
|
||||
// If we are the main thread we can't block the messagequeue
|
||||
while (!group->done_semaphore.try_wait()) {
|
||||
if (MessageQueue::get_singleton()) {
|
||||
MessageQueue::get_singleton()->flush();
|
||||
}
|
||||
|
||||
OS::get_singleton()->delay_usec(100);
|
||||
}
|
||||
} else {
|
||||
group->done_semaphore.wait();
|
||||
}
|
||||
if (this == singleton) {
|
||||
_lock_unlockable_mutexes();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user