| 
									
										
										
										
											2023-01-05 13:25:55 +01:00
										 |  |  | /**************************************************************************/ | 
					
						
							|  |  |  | /*  thread.cpp                                                            */ | 
					
						
							|  |  |  | /**************************************************************************/ | 
					
						
							|  |  |  | /*                         This file is part of:                          */ | 
					
						
							|  |  |  | /*                             GODOT ENGINE                               */ | 
					
						
							|  |  |  | /*                        https://godotengine.org                         */ | 
					
						
							|  |  |  | /**************************************************************************/ | 
					
						
							|  |  |  | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ | 
					
						
							|  |  |  | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur.                  */ | 
					
						
							|  |  |  | /*                                                                        */ | 
					
						
							|  |  |  | /* Permission is hereby granted, free of charge, to any person obtaining  */ | 
					
						
							|  |  |  | /* a copy of this software and associated documentation files (the        */ | 
					
						
							|  |  |  | /* "Software"), to deal in the Software without restriction, including    */ | 
					
						
							|  |  |  | /* without limitation the rights to use, copy, modify, merge, publish,    */ | 
					
						
							|  |  |  | /* distribute, sublicense, and/or sell copies of the Software, and to     */ | 
					
						
							|  |  |  | /* permit persons to whom the Software is furnished to do so, subject to  */ | 
					
						
							|  |  |  | /* the following conditions:                                              */ | 
					
						
							|  |  |  | /*                                                                        */ | 
					
						
							|  |  |  | /* The above copyright notice and this permission notice shall be         */ | 
					
						
							|  |  |  | /* included in all copies or substantial portions of the Software.        */ | 
					
						
							|  |  |  | /*                                                                        */ | 
					
						
							|  |  |  | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,        */ | 
					
						
							|  |  |  | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF     */ | 
					
						
							|  |  |  | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ | 
					
						
							|  |  |  | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY   */ | 
					
						
							|  |  |  | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,   */ | 
					
						
							|  |  |  | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE      */ | 
					
						
							|  |  |  | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                 */ | 
					
						
							|  |  |  | /**************************************************************************/ | 
					
						
							| 
									
										
										
										
											2018-01-05 00:50:27 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-14 12:36:06 +01:00
										 |  |  | #include "platform_config.h"
 | 
					
						
							| 
									
										
										
										
											2021-09-24 21:23:36 -03:00
										 |  |  | #ifndef PLATFORM_THREAD_OVERRIDE // See details in thread.h
 | 
					
						
							| 
									
										
										
										
											2021-09-15 21:48:04 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | #include "thread.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-19 13:29:41 +01:00
										 |  |  | #include "core/object/script_language.h"
 | 
					
						
							| 
									
										
										
										
											2021-02-10 19:22:13 +01:00
										 |  |  | #include "core/templates/safe_refcount.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-24 11:33:52 +02:00
										 |  |  | Thread::PlatformFunctions Thread::platform_functions; | 
					
						
							| 
									
										
										
										
											2021-01-19 13:29:41 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-22 15:34:16 +02:00
										 |  |  | SafeNumeric<uint64_t> Thread::id_counter(1); // The first value after .increment() is 2, hence by default the main thread ID should be 1.
 | 
					
						
							| 
									
										
										
										
											2021-03-07 00:17:20 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-22 15:34:16 +02:00
										 |  |  | thread_local Thread::ID Thread::caller_id = Thread::UNASSIGNED_ID; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-24 11:33:52 +02:00
										 |  |  | void Thread::_set_platform_functions(const PlatformFunctions &p_functions) { | 
					
						
							|  |  |  | 	platform_functions = p_functions; | 
					
						
							| 
									
										
										
										
											2021-01-19 13:29:41 +01:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-22 16:49:48 -05:00
										 |  |  | void Thread::callback(ID p_caller_id, const Settings &p_settings, Callback p_callback, void *p_userdata) { | 
					
						
							|  |  |  | 	Thread::caller_id = p_caller_id; | 
					
						
							| 
									
										
										
										
											2022-08-24 11:33:52 +02:00
										 |  |  | 	if (platform_functions.set_priority) { | 
					
						
							|  |  |  | 		platform_functions.set_priority(p_settings.priority); | 
					
						
							| 
									
										
										
										
											2021-01-19 13:29:41 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-08-24 11:33:52 +02:00
										 |  |  | 	if (platform_functions.init) { | 
					
						
							|  |  |  | 		platform_functions.init(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	ScriptServer::thread_enter(); // Scripts may need to attach a stack.
 | 
					
						
							|  |  |  | 	if (platform_functions.wrapper) { | 
					
						
							|  |  |  | 		platform_functions.wrapper(p_callback, p_userdata); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		p_callback(p_userdata); | 
					
						
							| 
									
										
										
										
											2021-01-19 13:29:41 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	ScriptServer::thread_exit(); | 
					
						
							| 
									
										
										
										
											2022-08-24 11:33:52 +02:00
										 |  |  | 	if (platform_functions.term) { | 
					
						
							|  |  |  | 		platform_functions.term(); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-05 01:09:18 +01:00
										 |  |  | Thread::ID Thread::start(Thread::Callback p_callback, void *p_user, const Settings &p_settings) { | 
					
						
							|  |  |  | 	ERR_FAIL_COND_V_MSG(id != UNASSIGNED_ID, UNASSIGNED_ID, "A Thread object has been re-started without wait_to_finish() having been called on it."); | 
					
						
							| 
									
										
										
										
											2023-04-22 15:34:16 +02:00
										 |  |  | 	id = id_counter.increment(); | 
					
						
							|  |  |  | 	std::thread new_thread(&Thread::callback, id, p_settings, p_callback, p_user); | 
					
						
							| 
									
										
										
										
											2021-01-19 13:29:41 +01:00
										 |  |  | 	thread.swap(new_thread); | 
					
						
							| 
									
										
										
										
											2023-03-05 01:09:18 +01:00
										 |  |  | 	return id; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-19 13:29:41 +01:00
										 |  |  | bool Thread::is_started() const { | 
					
						
							| 
									
										
										
										
											2023-04-22 15:34:16 +02:00
										 |  |  | 	return id != UNASSIGNED_ID; | 
					
						
							| 
									
										
										
										
											2021-01-19 13:29:41 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Thread::wait_to_finish() { | 
					
						
							| 
									
										
										
										
											2023-04-22 15:34:16 +02:00
										 |  |  | 	ERR_FAIL_COND_MSG(id == UNASSIGNED_ID, "Attempt of waiting to finish on a thread that was never started."); | 
					
						
							|  |  |  | 	ERR_FAIL_COND_MSG(id == get_caller_id(), "Threads can't wait to finish on themselves, another thread must wait."); | 
					
						
							|  |  |  | 	thread.join(); | 
					
						
							|  |  |  | 	std::thread empty_thread; | 
					
						
							|  |  |  | 	thread.swap(empty_thread); | 
					
						
							|  |  |  | 	id = UNASSIGNED_ID; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-17 06:24:27 -03:00
										 |  |  | Error Thread::set_name(const String &p_name) { | 
					
						
							| 
									
										
										
										
											2022-08-24 11:33:52 +02:00
										 |  |  | 	if (platform_functions.set_name) { | 
					
						
							|  |  |  | 		return platform_functions.set_name(p_name); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-01-31 20:22:38 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-17 06:24:27 -03:00
										 |  |  | 	return ERR_UNAVAILABLE; | 
					
						
							| 
									
										
										
										
											2020-05-19 15:46:49 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2021-01-19 13:29:41 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-09 08:40:30 +02:00
										 |  |  | Thread::Thread() { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-19 13:29:41 +01:00
										 |  |  | Thread::~Thread() { | 
					
						
							| 
									
										
										
										
											2023-04-22 15:34:16 +02:00
										 |  |  | 	if (id != UNASSIGNED_ID) { | 
					
						
							| 
									
										
										
										
											2021-01-19 13:29:41 +01:00
										 |  |  | #ifdef DEBUG_ENABLED
 | 
					
						
							| 
									
										
										
										
											2023-01-28 13:34:06 +01:00
										 |  |  | 		WARN_PRINT( | 
					
						
							|  |  |  | 				"A Thread object is being destroyed without its completion having been realized.\n" | 
					
						
							|  |  |  | 				"Please call wait_to_finish() on it to ensure correct cleanup."); | 
					
						
							| 
									
										
										
										
											2021-01-19 13:29:41 +01:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 		thread.detach(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-24 21:23:36 -03:00
										 |  |  | #endif // PLATFORM_THREAD_OVERRIDE
 |