mirror of
https://github.com/godotengine/godot.git
synced 2026-01-05 06:11:29 +03:00
Modernize Thread
- Based on C++11's `thread` and `thread_local` - No more need to allocate-deallocate or check for null - No pointer anymore, just a member variable - Platform-specific implementations no longer needed (except for the few cases of non-portable functions) - Simpler for `NO_THREADS` - Thread ids are now the same across platforms (main is 1; others follow)
This commit is contained in:
@@ -30,30 +30,70 @@
|
||||
|
||||
#include "thread.h"
|
||||
|
||||
Thread *(*Thread::create_func)(ThreadCreateCallback, void *, const Settings &) = nullptr;
|
||||
Thread::ID (*Thread::get_thread_id_func)() = nullptr;
|
||||
void (*Thread::wait_to_finish_func)(Thread *) = nullptr;
|
||||
#include "core/object/script_language.h"
|
||||
|
||||
#if !defined(NO_THREADS)
|
||||
|
||||
Error (*Thread::set_name_func)(const String &) = nullptr;
|
||||
void (*Thread::set_priority_func)(Thread::Priority) = nullptr;
|
||||
void (*Thread::init_func)() = nullptr;
|
||||
void (*Thread::term_func)() = nullptr;
|
||||
|
||||
Thread::ID Thread::_main_thread_id = 0;
|
||||
Thread::ID Thread::main_thread_id = 1;
|
||||
Thread::ID Thread::last_thread_id = 1;
|
||||
thread_local Thread::ID Thread::caller_id = 1;
|
||||
|
||||
Thread::ID Thread::get_caller_id() {
|
||||
if (get_thread_id_func) {
|
||||
return get_thread_id_func();
|
||||
}
|
||||
return 0;
|
||||
void Thread::_set_platform_funcs(
|
||||
Error (*p_set_name_func)(const String &),
|
||||
void (*p_set_priority_func)(Thread::Priority),
|
||||
void (*p_init_func)(),
|
||||
void (*p_term_func)()) {
|
||||
Thread::set_name_func = p_set_name_func;
|
||||
Thread::set_priority_func = p_set_priority_func;
|
||||
Thread::init_func = p_init_func;
|
||||
Thread::term_func = p_term_func;
|
||||
}
|
||||
|
||||
Thread *Thread::create(ThreadCreateCallback p_callback, void *p_user, const Settings &p_settings) {
|
||||
if (create_func) {
|
||||
return create_func(p_callback, p_user, p_settings);
|
||||
void Thread::callback(Thread *p_self, const Settings &p_settings, Callback p_callback, void *p_userdata) {
|
||||
Thread::caller_id = p_self->id;
|
||||
if (set_priority_func) {
|
||||
set_priority_func(p_settings.priority);
|
||||
}
|
||||
if (init_func) {
|
||||
init_func();
|
||||
}
|
||||
ScriptServer::thread_enter(); //scripts may need to attach a stack
|
||||
p_callback(p_userdata);
|
||||
ScriptServer::thread_exit();
|
||||
if (term_func) {
|
||||
term_func();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Thread::wait_to_finish(Thread *p_thread) {
|
||||
if (wait_to_finish_func) {
|
||||
wait_to_finish_func(p_thread);
|
||||
void Thread::start(Thread::Callback p_callback, void *p_user, const Settings &p_settings) {
|
||||
if (id != 0) {
|
||||
#ifdef DEBUG_ENABLED
|
||||
WARN_PRINT("A Thread object has been re-started without wait_to_finish() having been called on it. Please do so to ensure correct cleanup of the thread.");
|
||||
#endif
|
||||
thread.detach();
|
||||
std::thread empty_thread;
|
||||
thread.swap(empty_thread);
|
||||
}
|
||||
id = atomic_increment(&last_thread_id);
|
||||
std::thread new_thread(&Thread::callback, this, p_settings, p_callback, p_user);
|
||||
thread.swap(new_thread);
|
||||
}
|
||||
|
||||
bool Thread::is_started() const {
|
||||
return id != 0;
|
||||
}
|
||||
|
||||
void Thread::wait_to_finish() {
|
||||
if (id != 0) {
|
||||
thread.join();
|
||||
std::thread empty_thread;
|
||||
thread.swap(empty_thread);
|
||||
id = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,3 +104,14 @@ Error Thread::set_name(const String &p_name) {
|
||||
|
||||
return ERR_UNAVAILABLE;
|
||||
}
|
||||
|
||||
Thread::~Thread() {
|
||||
if (id != 0) {
|
||||
#ifdef DEBUG_ENABLED
|
||||
WARN_PRINT("A Thread object has been destroyed without wait_to_finish() having been called on it. Please do so to ensure correct cleanup of the thread.");
|
||||
#endif
|
||||
thread.detach();
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user