Merge pull request #54486 from ibrahn/thread-work-pool-lazier
This commit is contained in:
commit
e87687a6d0
3 changed files with 22 additions and 14 deletions
|
@ -73,6 +73,7 @@ class ThreadWorkPool {
|
||||||
|
|
||||||
ThreadData *threads = nullptr;
|
ThreadData *threads = nullptr;
|
||||||
uint32_t thread_count = 0;
|
uint32_t thread_count = 0;
|
||||||
|
uint32_t threads_working = 0;
|
||||||
BaseWork *current_work = nullptr;
|
BaseWork *current_work = nullptr;
|
||||||
|
|
||||||
static void _thread_function(void *p_user);
|
static void _thread_function(void *p_user);
|
||||||
|
@ -94,7 +95,9 @@ public:
|
||||||
|
|
||||||
current_work = w;
|
current_work = w;
|
||||||
|
|
||||||
for (uint32_t i = 0; i < thread_count; i++) {
|
threads_working = MIN(p_elements, thread_count);
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < threads_working; i++) {
|
||||||
threads[i].work = w;
|
threads[i].work = w;
|
||||||
threads[i].start.post();
|
threads[i].start.post();
|
||||||
}
|
}
|
||||||
|
@ -117,20 +120,33 @@ public:
|
||||||
|
|
||||||
void end_work() {
|
void end_work() {
|
||||||
ERR_FAIL_COND(current_work == nullptr);
|
ERR_FAIL_COND(current_work == nullptr);
|
||||||
for (uint32_t i = 0; i < thread_count; i++) {
|
for (uint32_t i = 0; i < threads_working; i++) {
|
||||||
threads[i].completed.wait();
|
threads[i].completed.wait();
|
||||||
threads[i].work = nullptr;
|
threads[i].work = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
threads_working = 0;
|
||||||
memdelete(current_work);
|
memdelete(current_work);
|
||||||
current_work = nullptr;
|
current_work = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class C, class M, class U>
|
template <class C, class M, class U>
|
||||||
void do_work(uint32_t p_elements, C *p_instance, M p_method, U p_userdata) {
|
void do_work(uint32_t p_elements, C *p_instance, M p_method, U p_userdata) {
|
||||||
|
switch (p_elements) {
|
||||||
|
case 0:
|
||||||
|
// Nothing to do, so do nothing.
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
// No value in pushing the work to another thread if it's a single job
|
||||||
|
// and we're going to wait for it to finish. Just run it right here.
|
||||||
|
(p_instance->*p_method)(0, p_userdata);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// Multiple jobs to do; commence threaded business.
|
||||||
begin_work(p_elements, p_instance, p_method, p_userdata);
|
begin_work(p_elements, p_instance, p_method, p_userdata);
|
||||||
end_work();
|
end_work();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_FORCE_INLINE_ int get_thread_count() const { return thread_count; }
|
_FORCE_INLINE_ int get_thread_count() const { return thread_count; }
|
||||||
void init(int p_thread_count = -1);
|
void init(int p_thread_count = -1);
|
||||||
|
|
|
@ -255,11 +255,7 @@ void GodotStep2D::step(GodotSpace2D *p_space, real_t p_delta, int p_iterations)
|
||||||
|
|
||||||
// Warning: _solve_island modifies the constraint islands for optimization purpose,
|
// Warning: _solve_island modifies the constraint islands for optimization purpose,
|
||||||
// their content is not reliable after these calls and shouldn't be used anymore.
|
// their content is not reliable after these calls and shouldn't be used anymore.
|
||||||
if (island_count > 1) {
|
|
||||||
work_pool.do_work(island_count, this, &GodotStep2D::_solve_island, nullptr);
|
work_pool.do_work(island_count, this, &GodotStep2D::_solve_island, nullptr);
|
||||||
} else if (island_count > 0) {
|
|
||||||
_solve_island(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
{ //profile
|
{ //profile
|
||||||
profile_endtime = OS::get_singleton()->get_ticks_usec();
|
profile_endtime = OS::get_singleton()->get_ticks_usec();
|
||||||
|
|
|
@ -359,11 +359,7 @@ void GodotStep3D::step(GodotSpace3D *p_space, real_t p_delta, int p_iterations)
|
||||||
|
|
||||||
// Warning: _solve_island modifies the constraint islands for optimization purpose,
|
// Warning: _solve_island modifies the constraint islands for optimization purpose,
|
||||||
// their content is not reliable after these calls and shouldn't be used anymore.
|
// their content is not reliable after these calls and shouldn't be used anymore.
|
||||||
if (island_count > 1) {
|
|
||||||
work_pool.do_work(island_count, this, &GodotStep3D::_solve_island, nullptr);
|
work_pool.do_work(island_count, this, &GodotStep3D::_solve_island, nullptr);
|
||||||
} else if (island_count > 0) {
|
|
||||||
_solve_island(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
{ //profile
|
{ //profile
|
||||||
profile_endtime = OS::get_singleton()->get_ticks_usec();
|
profile_endtime = OS::get_singleton()->get_ticks_usec();
|
||||||
|
|
Loading…
Reference in a new issue