diff options
Diffstat (limited to 'core/os/thread.cpp')
| -rw-r--r-- | core/os/thread.cpp | 96 | 
1 files changed, 79 insertions, 17 deletions
| diff --git a/core/os/thread.cpp b/core/os/thread.cpp index fc0ce3c9b4..73e31bdb3d 100644 --- a/core/os/thread.cpp +++ b/core/os/thread.cpp @@ -5,8 +5,8 @@  /*                           GODOT ENGINE                                */  /*                      https://godotengine.org                          */  /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.                 */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md).   */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */  /*                                                                       */  /* Permission is hereby granted, free of charge, to any person obtaining */  /* a copy of this software and associated documentation files (the       */ @@ -30,30 +30,77 @@  #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) + +#include "core/templates/safe_refcount.h" +  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; + +uint64_t Thread::_thread_id_hash(const std::thread::id &p_t) { +	static std::hash<std::thread::id> hasher; +	return hasher(p_t); +} -Thread::ID Thread::_main_thread_id = 0; +Thread::ID Thread::main_thread_id = _thread_id_hash(std::this_thread::get_id()); +thread_local Thread::ID Thread::caller_id = 0; -Thread::ID Thread::get_caller_id() { -	if (get_thread_id_func) { -		return get_thread_id_func(); +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; +} + +void Thread::callback(Thread *p_self, const Settings &p_settings, Callback p_callback, void *p_userdata) { +	Thread::caller_id = _thread_id_hash(p_self->thread.get_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 0;  } -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::start(Thread::Callback p_callback, void *p_user, const Settings &p_settings) { +	if (id != _thread_id_hash(std::thread::id())) { +#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);  	} -	return nullptr; +	std::thread new_thread(&Thread::callback, this, p_settings, p_callback, p_user); +	thread.swap(new_thread); +	id = _thread_id_hash(thread.get_id());  } -void Thread::wait_to_finish(Thread *p_thread) { -	if (wait_to_finish_func) { -		wait_to_finish_func(p_thread); +bool Thread::is_started() const { +	return id != _thread_id_hash(std::thread::id()); +} + +void Thread::wait_to_finish() { +	if (id != _thread_id_hash(std::thread::id())) { +		ERR_FAIL_COND_MSG(id == get_caller_id(), "A Thread can't wait for itself to finish."); +		thread.join(); +		std::thread empty_thread; +		thread.swap(empty_thread); +		id = _thread_id_hash(std::thread::id());  	}  } @@ -64,3 +111,18 @@ Error Thread::set_name(const String &p_name) {  	return ERR_UNAVAILABLE;  } + +Thread::Thread() { +	caller_id = _thread_id_hash(std::this_thread::get_id()); +} + +Thread::~Thread() { +	if (id != _thread_id_hash(std::thread::id())) { +#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 |