Browse Source

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)
Pedro J. Estébanez 4 years ago
parent
commit
6d89f675b1
84 changed files with 367 additions and 1077 deletions
  1. 3 18
      core/bind/core_bind.cpp
  2. 1 1
      core/bind/core_bind.h
  3. 3 5
      core/io/file_access_network.cpp
  4. 1 1
      core/io/file_access_network.h
  5. 6 16
      core/io/ip.cpp
  6. 68 22
      core/os/thread.cpp
  7. 56 20
      core/os/thread.h
  8. 0 41
      core/os/thread_dummy.cpp
  9. 0 48
      core/os/thread_dummy.h
  10. 7 8
      core/os/threaded_array_processor.h
  11. 3 13
      drivers/alsa/audio_driver_alsa.cpp
  12. 1 1
      drivers/alsa/audio_driver_alsa.h
  13. 3 10
      drivers/alsamidi/midi_driver_alsamidi.cpp
  14. 1 1
      drivers/alsamidi/midi_driver_alsamidi.h
  15. 3 12
      drivers/pulseaudio/audio_driver_pulseaudio.cpp
  16. 1 1
      drivers/pulseaudio/audio_driver_pulseaudio.h
  17. 3 5
      drivers/unix/os_unix.cpp
  18. 6 96
      drivers/unix/thread_posix.cpp
  19. 2 37
      drivers/unix/thread_posix.h
  20. 3 10
      drivers/wasapi/audio_driver_wasapi.cpp
  21. 1 1
      drivers/wasapi/audio_driver_wasapi.h
  22. 0 100
      drivers/windows/thread_windows.cpp
  23. 0 68
      drivers/windows/thread_windows.h
  24. 3 11
      drivers/xaudio2/audio_driver_xaudio2.cpp
  25. 1 1
      drivers/xaudio2/audio_driver_xaudio2.h
  26. 6 3
      editor/audio_stream_preview.cpp
  27. 11 20
      editor/editor_file_system.cpp
  28. 2 2
      editor/editor_file_system.h
  29. 2 5
      editor/editor_node.cpp
  30. 1 1
      editor/editor_node.h
  31. 4 7
      editor/editor_resource_preview.cpp
  32. 1 1
      editor/editor_resource_preview.h
  33. 5 7
      editor/fileserver/editor_file_server.cpp
  34. 2 2
      editor/fileserver/editor_file_server.h
  35. 3 3
      main/main.cpp
  36. 3 2
      modules/cvtt/image_compress_cvtt.cpp
  37. 1 1
      modules/gdnative/android/android_gdn.cpp
  38. 3 7
      modules/gdscript/language_server/gdscript_language_server.cpp
  39. 1 1
      modules/gdscript/language_server/gdscript_language_server.h
  40. 3 3
      modules/lightmapper_cpu/lightmapper_cpu.cpp
  41. 9 9
      modules/mono/mono_gd/support/android_support.cpp
  42. 5 11
      modules/opensimplex/noise_texture.cpp
  43. 1 1
      modules/opensimplex/noise_texture.h
  44. 2 5
      modules/theora/video_stream_theora.cpp
  45. 1 1
      modules/theora/video_stream_theora.h
  46. 1 1
      platform/android/api/jni_singleton.h
  47. 4 4
      platform/android/audio_driver_jandroid.cpp
  48. 7 7
      platform/android/dir_access_jandroid.cpp
  49. 3 4
      platform/android/export/export.cpp
  50. 3 3
      platform/android/java_class_wrapper.cpp
  51. 15 15
      platform/android/java_godot_io_wrapper.cpp
  52. 4 4
      platform/android/java_godot_lib_jni.cpp
  53. 19 19
      platform/android/java_godot_wrapper.cpp
  54. 3 3
      platform/android/net_socket_android.cpp
  55. 2 2
      platform/android/string_android.h
  56. 14 112
      platform/android/thread_jandroid.cpp
  57. 5 38
      platform/android/thread_jandroid.h
  58. 3 4
      platform/iphone/export/export.cpp
  59. 2 4
      platform/javascript/audio_driver_javascript.cpp
  60. 1 1
      platform/javascript/audio_driver_javascript.h
  61. 3 4
      platform/javascript/export/export.cpp
  62. 2 2
      platform/uwp/app.h
  63. 0 3
      platform/uwp/os_uwp.cpp
  64. 0 73
      platform/uwp/thread_uwp.cpp
  65. 0 60
      platform/uwp/thread_uwp.h
  66. 0 3
      platform/windows/os_windows.cpp
  67. 2 3
      platform/x11/joypad_linux.cpp
  68. 1 1
      platform/x11/joypad_linux.h
  69. 2 4
      platform/x11/os_x11.cpp
  70. 1 1
      platform/x11/os_x11.h
  71. 2 6
      scene/main/http_request.cpp
  72. 1 1
      scene/main/http_request.h
  73. 6 11
      scene/resources/sky.cpp
  74. 1 1
      scene/resources/sky.h
  75. 3 14
      servers/audio/audio_driver_dummy.cpp
  76. 1 1
      servers/audio/audio_driver_dummy.h
  77. 2 2
      servers/audio/effects/audio_effect_record.cpp
  78. 1 1
      servers/audio/effects/audio_effect_record.h
  79. 3 9
      servers/physics_2d/physics_2d_server_wrap_mt.cpp
  80. 1 1
      servers/physics_2d/physics_2d_server_wrap_mt.h
  81. 2 7
      servers/visual/visual_server_scene.cpp
  82. 1 1
      servers/visual/visual_server_scene.h
  83. 3 7
      servers/visual/visual_server_wrap_mt.cpp
  84. 1 1
      servers/visual/visual_server_wrap_mt.h

+ 3 - 18
core/bind/core_bind.cpp

@@ -2787,24 +2787,14 @@ Error _Thread::start(Object *p_instance, const StringName &p_method, const Varia
 
 
 	Thread::Settings s;
 	Thread::Settings s;
 	s.priority = (Thread::Priority)p_priority;
 	s.priority = (Thread::Priority)p_priority;
-	thread = Thread::create(_start_func, ud, s);
-	if (!thread) {
-		active = false;
-		target_method = StringName();
-		target_instance = NULL;
-		userdata = Variant();
-		return ERR_CANT_CREATE;
-	}
+	thread.start(_start_func, ud, s);
 
 
 	return OK;
 	return OK;
 }
 }
 
 
 String _Thread::get_id() const {
 String _Thread::get_id() const {
 
 
-	if (!thread)
-		return String();
-
-	return itos(thread->get_id());
+	return itos(thread.get_id());
 }
 }
 
 
 bool _Thread::is_active() const {
 bool _Thread::is_active() const {
@@ -2813,17 +2803,13 @@ bool _Thread::is_active() const {
 }
 }
 Variant _Thread::wait_to_finish() {
 Variant _Thread::wait_to_finish() {
 
 
-	ERR_FAIL_COND_V_MSG(!thread, Variant(), "Thread must exist to wait for its completion.");
 	ERR_FAIL_COND_V_MSG(!active, Variant(), "Thread must be active to wait for its completion.");
 	ERR_FAIL_COND_V_MSG(!active, Variant(), "Thread must be active to wait for its completion.");
-	Thread::wait_to_finish(thread);
+	thread.wait_to_finish();
 	Variant r = ret;
 	Variant r = ret;
 	active = false;
 	active = false;
 	target_method = StringName();
 	target_method = StringName();
 	target_instance = NULL;
 	target_instance = NULL;
 	userdata = Variant();
 	userdata = Variant();
-	if (thread)
-		memdelete(thread);
-	thread = NULL;
 
 
 	return r;
 	return r;
 }
 }
@@ -2842,7 +2828,6 @@ void _Thread::_bind_methods() {
 _Thread::_Thread() {
 _Thread::_Thread() {
 
 
 	active = false;
 	active = false;
-	thread = NULL;
 	target_instance = NULL;
 	target_instance = NULL;
 }
 }
 
 

+ 1 - 1
core/bind/core_bind.h

@@ -684,7 +684,7 @@ protected:
 	volatile bool active;
 	volatile bool active;
 	Object *target_instance;
 	Object *target_instance;
 	StringName target_method;
 	StringName target_method;
-	Thread *thread;
+	Thread thread;
 	static void _bind_methods();
 	static void _bind_methods();
 	static void _start_func(void *ud);
 	static void _start_func(void *ud);
 
 

+ 3 - 5
core/io/file_access_network.cpp

@@ -213,7 +213,7 @@ Error FileAccessNetworkClient::connect(const String &p_host, int p_port, const S
 		return ERR_INVALID_PARAMETER;
 		return ERR_INVALID_PARAMETER;
 	}
 	}
 
 
-	thread = Thread::create(_thread_func, this);
+	thread.start(_thread_func, this);
 
 
 	return OK;
 	return OK;
 }
 }
@@ -222,7 +222,6 @@ FileAccessNetworkClient *FileAccessNetworkClient::singleton = NULL;
 
 
 FileAccessNetworkClient::FileAccessNetworkClient() {
 FileAccessNetworkClient::FileAccessNetworkClient() {
 
 
-	thread = NULL;
 	quit = false;
 	quit = false;
 	singleton = this;
 	singleton = this;
 	last_id = 0;
 	last_id = 0;
@@ -232,11 +231,10 @@ FileAccessNetworkClient::FileAccessNetworkClient() {
 
 
 FileAccessNetworkClient::~FileAccessNetworkClient() {
 FileAccessNetworkClient::~FileAccessNetworkClient() {
 
 
-	if (thread) {
+	if (thread.is_started()) {
 		quit = true;
 		quit = true;
 		sem.post();
 		sem.post();
-		Thread::wait_to_finish(thread);
-		memdelete(thread);
+		thread.wait_to_finish();
 	}
 	}
 }
 }
 
 

+ 1 - 1
core/io/file_access_network.h

@@ -50,7 +50,7 @@ class FileAccessNetworkClient {
 	List<BlockRequest> block_requests;
 	List<BlockRequest> block_requests;
 
 
 	Semaphore sem;
 	Semaphore sem;
-	Thread *thread;
+	Thread thread;
 	bool quit;
 	bool quit;
 	Mutex mutex;
 	Mutex mutex;
 	Mutex blockrequest_mutex;
 	Mutex blockrequest_mutex;

+ 6 - 16
core/io/ip.cpp

@@ -73,7 +73,7 @@ struct _IP_ResolverPrivate {
 	Mutex mutex;
 	Mutex mutex;
 	Semaphore sem;
 	Semaphore sem;
 
 
-	Thread *thread;
+	Thread thread;
 	//Semaphore* semaphore;
 	//Semaphore* semaphore;
 	bool thread_abort;
 	bool thread_abort;
 
 
@@ -151,7 +151,7 @@ IP::ResolverID IP::resolve_hostname_queue_item(const String &p_hostname, IP::Typ
 	} else {
 	} else {
 		resolver->queue[id].response = IP_Address();
 		resolver->queue[id].response = IP_Address();
 		resolver->queue[id].status = IP::RESOLVER_STATUS_WAITING;
 		resolver->queue[id].status = IP::RESOLVER_STATUS_WAITING;
-		if (resolver->thread)
+		if (resolver->thread.is_started())
 			resolver->sem.post();
 			resolver->sem.post();
 		else
 		else
 			resolver->resolve_queues();
 			resolver->resolve_queues();
@@ -315,25 +315,15 @@ IP::IP() {
 	singleton = this;
 	singleton = this;
 	resolver = memnew(_IP_ResolverPrivate);
 	resolver = memnew(_IP_ResolverPrivate);
 
 
-#ifndef NO_THREADS
 	resolver->thread_abort = false;
 	resolver->thread_abort = false;
-	resolver->thread = Thread::create(_IP_ResolverPrivate::_thread_function, resolver);
-#else
-	resolver->thread = NULL;
-#endif
+	resolver->thread.start(_IP_ResolverPrivate::_thread_function, resolver);
 }
 }
 
 
 IP::~IP() {
 IP::~IP() {
 
 
-#ifndef NO_THREADS
-	if (resolver->thread) {
-		resolver->thread_abort = true;
-		resolver->sem.post();
-		Thread::wait_to_finish(resolver->thread);
-		memdelete(resolver->thread);
-	}
-
-#endif
+	resolver->thread_abort = true;
+	resolver->sem.post();
+	resolver->thread.wait_to_finish();
 
 
 	memdelete(resolver);
 	memdelete(resolver);
 }
 }

+ 68 - 22
core/os/thread.cpp

@@ -30,45 +30,91 @@
 
 
 #include "thread.h"
 #include "thread.h"
 
 
-Thread *(*Thread::create_func)(ThreadCreateCallback, void *, const Settings &) = NULL;
-Thread::ID (*Thread::get_thread_id_func)() = NULL;
-void (*Thread::wait_to_finish_func)(Thread *) = NULL;
-Error (*Thread::set_name_func)(const String &) = NULL;
+#include "core/script_language.h"
 
 
-Thread::ID Thread::_main_thread_id = 0;
+#if !defined(NO_THREADS)
 
 
-Thread::ID Thread::get_caller_id() {
+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;
 
 
-	if (get_thread_id_func)
-		return get_thread_id_func();
-	return 0;
-}
+Thread::ID Thread::main_thread_id = 1;
+Thread::ID Thread::last_thread_id = 1;
+thread_local Thread::ID Thread::caller_id = 1;
 
 
-Thread *Thread::create(ThreadCreateCallback p_callback, void *p_user, const Settings &p_settings) {
+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;
+}
 
 
-	if (create_func) {
+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 create_func(p_callback, p_user, p_settings);
+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);
 	}
 	}
-	return NULL;
+	id = atomic_increment(&last_thread_id);
+	std::thread new_thread(&Thread::callback, this, p_settings, p_callback, p_user);
+	thread.swap(new_thread);
 }
 }
 
 
-void Thread::wait_to_finish(Thread *p_thread) {
+bool Thread::is_started() const {
+	return id != 0;
+}
 
 
-	if (wait_to_finish_func)
-		wait_to_finish_func(p_thread);
+void Thread::wait_to_finish() {
+	if (id != 0) {
+		thread.join();
+		std::thread empty_thread;
+		thread.swap(empty_thread);
+		id = 0;
+	}
 }
 }
 
 
 Error Thread::set_name(const String &p_name) {
 Error Thread::set_name(const String &p_name) {
-
-	if (set_name_func)
+	if (set_name_func) {
 		return set_name_func(p_name);
 		return set_name_func(p_name);
+	}
 
 
 	return ERR_UNAVAILABLE;
 	return ERR_UNAVAILABLE;
-};
-
-Thread::Thread() {
 }
 }
 
 
+Thread::Thread() :
+		id(0) {}
+
 Thread::~Thread() {
 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

+ 56 - 20
core/os/thread.h

@@ -32,49 +32,85 @@
 #define THREAD_H
 #define THREAD_H
 
 
 #include "core/typedefs.h"
 #include "core/typedefs.h"
-#include "core/ustring.h"
 
 
-typedef void (*ThreadCreateCallback)(void *p_userdata);
+#if !defined(NO_THREADS)
+#include <thread>
+#endif
+
+class String;
 
 
 class Thread {
 class Thread {
 public:
 public:
-	enum Priority {
+	typedef void (*Callback)(void *p_userdata);
+
+	typedef uint64_t ID;
 
 
+	enum Priority {
 		PRIORITY_LOW,
 		PRIORITY_LOW,
 		PRIORITY_NORMAL,
 		PRIORITY_NORMAL,
 		PRIORITY_HIGH
 		PRIORITY_HIGH
 	};
 	};
 
 
 	struct Settings {
 	struct Settings {
-
 		Priority priority;
 		Priority priority;
 		Settings() { priority = PRIORITY_NORMAL; }
 		Settings() { priority = PRIORITY_NORMAL; }
 	};
 	};
 
 
-	typedef uint64_t ID;
+private:
+#if !defined(NO_THREADS)
+	friend class Main;
 
 
-protected:
-	static Thread *(*create_func)(ThreadCreateCallback p_callback, void *, const Settings &);
-	static ID (*get_thread_id_func)();
-	static void (*wait_to_finish_func)(Thread *);
-	static Error (*set_name_func)(const String &);
+	static ID main_thread_id;
+	static ID last_thread_id;
 
 
-	friend class Main;
+	ID id;
+	static thread_local ID caller_id;
+	std::thread thread;
 
 
-	static ID _main_thread_id;
+	static void callback(Thread *p_self, const Settings &p_settings, Thread::Callback p_callback, void *p_userdata);
 
 
-	Thread();
+	static Error (*set_name_func)(const String &);
+	static void (*set_priority_func)(Thread::Priority);
+	static void (*init_func)();
+	static void (*term_func)();
+#endif
 
 
 public:
 public:
-	virtual ID get_id() const = 0;
+	static void _set_platform_funcs(
+			Error (*p_set_name_func)(const String &),
+			void (*p_set_priority_func)(Thread::Priority),
+			void (*p_init_func)() = nullptr,
+			void (*p_term_func)() = nullptr);
+
+#if !defined(NO_THREADS)
+	_FORCE_INLINE_ ID get_id() const { return id; }
+	// get the ID of the caller thread
+	_FORCE_INLINE_ static ID get_caller_id() { return caller_id; }
+	// get the ID of the main thread
+	_FORCE_INLINE_ static ID get_main_id() { return main_thread_id; }
 
 
 	static Error set_name(const String &p_name);
 	static Error set_name(const String &p_name);
-	_FORCE_INLINE_ static ID get_main_id() { return _main_thread_id; } ///< get the ID of the main thread
-	static ID get_caller_id(); ///< get the ID of the caller function ID
-	static void wait_to_finish(Thread *p_thread); ///< waits until thread is finished
-	static Thread *create(ThreadCreateCallback p_callback, void *p_user, const Settings &p_settings = Settings()); ///< Static function to create a thread, will call p_callback
 
 
-	virtual ~Thread();
-};
+	void start(Thread::Callback p_callback, void *p_user, const Settings &p_settings = Settings());
+	bool is_started() const;
+	///< waits until thread is finished, and deallocates it.
+	void wait_to_finish();
 
 
+	Thread();
+	~Thread();
+#else
+	_FORCE_INLINE_ ID get_id() const { return 0; }
+	// get the ID of the caller thread
+	_FORCE_INLINE_ static ID get_caller_id() { return 0; }
+	// get the ID of the main thread
+	_FORCE_INLINE_ static ID get_main_id() { return 0; }
+
+	static Error set_name(const String &p_name) { return ERR_UNAVAILABLE; }
+
+	void start(Thread::Callback p_callback, void *p_user, const Settings &p_settings = Settings()) {}
+	bool is_started() const { return false; }
+	void wait_to_finish() {}
 #endif
 #endif
+};
+
+#endif // THREAD_H

+ 0 - 41
core/os/thread_dummy.cpp

@@ -1,41 +0,0 @@
-/*************************************************************************/
-/*  thread_dummy.cpp                                                     */
-/*************************************************************************/
-/*                       This file is part of:                           */
-/*                           GODOT ENGINE                                */
-/*                      https://godotengine.org                          */
-/*************************************************************************/
-/* 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       */
-/* "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.                */
-/*************************************************************************/
-
-#include "thread_dummy.h"
-
-#include "core/os/memory.h"
-
-Thread *ThreadDummy::create(ThreadCreateCallback p_callback, void *p_user, const Thread::Settings &p_settings) {
-	return memnew(ThreadDummy);
-};
-
-void ThreadDummy::make_default() {
-	Thread::create_func = &ThreadDummy::create;
-};

+ 0 - 48
core/os/thread_dummy.h

@@ -1,48 +0,0 @@
-/*************************************************************************/
-/*  thread_dummy.h                                                       */
-/*************************************************************************/
-/*                       This file is part of:                           */
-/*                           GODOT ENGINE                                */
-/*                      https://godotengine.org                          */
-/*************************************************************************/
-/* 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       */
-/* "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.                */
-/*************************************************************************/
-
-#ifndef THREAD_DUMMY_H
-#define THREAD_DUMMY_H
-
-#include "core/os/mutex.h"
-#include "core/os/semaphore.h"
-#include "core/os/thread.h"
-
-class ThreadDummy : public Thread {
-
-	static Thread *create(ThreadCreateCallback p_callback, void *p_user, const Settings &p_settings = Settings());
-
-public:
-	virtual ID get_id() const { return 0; };
-
-	static void make_default();
-};
-
-#endif

+ 7 - 8
core/os/threaded_array_processor.h

@@ -75,18 +75,17 @@ void thread_process_array(uint32_t p_elements, C *p_instance, M p_method, U p_us
 	data.elements = p_elements;
 	data.elements = p_elements;
 	data.process(data.index); //process first, let threads increment for next
 	data.process(data.index); //process first, let threads increment for next
 
 
-	Vector<Thread *> threads;
+	int thread_count = OS::get_singleton()->get_processor_count();
+	Thread *threads = memnew_arr(Thread, thread_count);
 
 
-	threads.resize(OS::get_singleton()->get_processor_count());
-
-	for (int i = 0; i < threads.size(); i++) {
-		threads.write[i] = Thread::create(process_array_thread<ThreadArrayProcessData<C, U> >, &data);
+	for (int i = 0; i < thread_count; i++) {
+		threads[i].start(process_array_thread<ThreadArrayProcessData<C, U> >, &data);
 	}
 	}
 
 
-	for (int i = 0; i < threads.size(); i++) {
-		Thread::wait_to_finish(threads[i]);
-		memdelete(threads[i]);
+	for (int i = 0; i < thread_count; i++) {
+		threads[i].wait_to_finish();
 	}
 	}
+	memdelete_arr(threads);
 }
 }
 
 
 #else
 #else

+ 3 - 13
drivers/alsa/audio_driver_alsa.cpp

@@ -169,7 +169,7 @@ Error AudioDriverALSA::init() {
 
 
 	Error err = init_device();
 	Error err = init_device();
 	if (err == OK) {
 	if (err == OK) {
-		thread = Thread::create(AudioDriverALSA::thread_func, this);
+		thread.start(AudioDriverALSA::thread_func, this);
 	}
 	}
 
 
 	return err;
 	return err;
@@ -313,15 +313,11 @@ void AudioDriverALSA::set_device(String device) {
 
 
 void AudioDriverALSA::lock() {
 void AudioDriverALSA::lock() {
 
 
-	if (!thread)
-		return;
 	mutex.lock();
 	mutex.lock();
 }
 }
 
 
 void AudioDriverALSA::unlock() {
 void AudioDriverALSA::unlock() {
 
 
-	if (!thread)
-		return;
 	mutex.unlock();
 	mutex.unlock();
 }
 }
 
 
@@ -335,19 +331,13 @@ void AudioDriverALSA::finish_device() {
 
 
 void AudioDriverALSA::finish() {
 void AudioDriverALSA::finish() {
 
 
-	if (thread) {
-		exit_thread = true;
-		Thread::wait_to_finish(thread);
-
-		memdelete(thread);
-		thread = NULL;
-	}
+	exit_thread = true;
+	thread.wait_to_finish();
 
 
 	finish_device();
 	finish_device();
 }
 }
 
 
 AudioDriverALSA::AudioDriverALSA() :
 AudioDriverALSA::AudioDriverALSA() :
-		thread(NULL),
 		pcm_handle(NULL),
 		pcm_handle(NULL),
 		device_name("Default"),
 		device_name("Default"),
 		new_device("Default") {
 		new_device("Default") {

+ 1 - 1
drivers/alsa/audio_driver_alsa.h

@@ -41,7 +41,7 @@
 
 
 class AudioDriverALSA : public AudioDriver {
 class AudioDriverALSA : public AudioDriver {
 
 
-	Thread *thread;
+	Thread thread;
 	Mutex mutex;
 	Mutex mutex;
 
 
 	snd_pcm_t *pcm_handle;
 	snd_pcm_t *pcm_handle;

+ 3 - 10
drivers/alsamidi/midi_driver_alsamidi.cpp

@@ -149,20 +149,15 @@ Error MIDIDriverALSAMidi::open() {
 	snd_device_name_free_hint(hints);
 	snd_device_name_free_hint(hints);
 
 
 	exit_thread = false;
 	exit_thread = false;
-	thread = Thread::create(MIDIDriverALSAMidi::thread_func, this);
+	thread.start(MIDIDriverALSAMidi::thread_func, this);
 
 
 	return OK;
 	return OK;
 }
 }
 
 
 void MIDIDriverALSAMidi::close() {
 void MIDIDriverALSAMidi::close() {
 
 
-	if (thread) {
-		exit_thread = true;
-		Thread::wait_to_finish(thread);
-
-		memdelete(thread);
-		thread = NULL;
-	}
+	exit_thread = true;
+	thread.wait_to_finish();
 
 
 	for (int i = 0; i < connected_inputs.size(); i++) {
 	for (int i = 0; i < connected_inputs.size(); i++) {
 		snd_rawmidi_t *midi_in = connected_inputs[i];
 		snd_rawmidi_t *midi_in = connected_inputs[i];
@@ -202,8 +197,6 @@ PoolStringArray MIDIDriverALSAMidi::get_connected_inputs() {
 
 
 MIDIDriverALSAMidi::MIDIDriverALSAMidi() {
 MIDIDriverALSAMidi::MIDIDriverALSAMidi() {
 
 
-	thread = NULL;
-
 	exit_thread = false;
 	exit_thread = false;
 }
 }
 
 

+ 1 - 1
drivers/alsamidi/midi_driver_alsamidi.h

@@ -43,7 +43,7 @@
 
 
 class MIDIDriverALSAMidi : public MIDIDriver {
 class MIDIDriverALSAMidi : public MIDIDriver {
 
 
-	Thread *thread;
+	Thread thread;
 	Mutex mutex;
 	Mutex mutex;
 
 
 	Vector<snd_rawmidi_t *> connected_inputs;
 	Vector<snd_rawmidi_t *> connected_inputs;

+ 3 - 12
drivers/pulseaudio/audio_driver_pulseaudio.cpp

@@ -294,7 +294,7 @@ Error AudioDriverPulseAudio::init() {
 
 
 	Error err = init_device();
 	Error err = init_device();
 	if (err == OK) {
 	if (err == OK) {
-		thread = Thread::create(AudioDriverPulseAudio::thread_func, this);
+		thread.start(AudioDriverPulseAudio::thread_func, this);
 	}
 	}
 
 
 	return OK;
 	return OK;
@@ -599,15 +599,11 @@ void AudioDriverPulseAudio::set_device(String device) {
 
 
 void AudioDriverPulseAudio::lock() {
 void AudioDriverPulseAudio::lock() {
 
 
-	if (!thread)
-		return;
 	mutex.lock();
 	mutex.lock();
 }
 }
 
 
 void AudioDriverPulseAudio::unlock() {
 void AudioDriverPulseAudio::unlock() {
 
 
-	if (!thread)
-		return;
 	mutex.unlock();
 	mutex.unlock();
 }
 }
 
 
@@ -622,11 +618,11 @@ void AudioDriverPulseAudio::finish_device() {
 
 
 void AudioDriverPulseAudio::finish() {
 void AudioDriverPulseAudio::finish() {
 
 
-	if (!thread)
+	if (!thread.is_started())
 		return;
 		return;
 
 
 	exit_thread = true;
 	exit_thread = true;
-	Thread::wait_to_finish(thread);
+	thread.wait_to_finish();
 
 
 	finish_device();
 	finish_device();
 
 
@@ -640,10 +636,6 @@ void AudioDriverPulseAudio::finish() {
 		pa_mainloop_free(pa_ml);
 		pa_mainloop_free(pa_ml);
 		pa_ml = NULL;
 		pa_ml = NULL;
 	}
 	}
-
-	memdelete(thread);
-
-	thread = NULL;
 }
 }
 
 
 Error AudioDriverPulseAudio::capture_init_device() {
 Error AudioDriverPulseAudio::capture_init_device() {
@@ -797,7 +789,6 @@ String AudioDriverPulseAudio::capture_get_device() {
 }
 }
 
 
 AudioDriverPulseAudio::AudioDriverPulseAudio() :
 AudioDriverPulseAudio::AudioDriverPulseAudio() :
-		thread(NULL),
 		pa_ml(NULL),
 		pa_ml(NULL),
 		pa_ctx(NULL),
 		pa_ctx(NULL),
 		pa_str(NULL),
 		pa_str(NULL),

+ 1 - 1
drivers/pulseaudio/audio_driver_pulseaudio.h

@@ -41,7 +41,7 @@
 
 
 class AudioDriverPulseAudio : public AudioDriver {
 class AudioDriverPulseAudio : public AudioDriver {
 
 
-	Thread *thread;
+	Thread thread;
 	Mutex mutex;
 	Mutex mutex;
 
 
 	pa_mainloop *pa_ml;
 	pa_mainloop *pa_ml;

+ 3 - 5
drivers/unix/os_unix.cpp

@@ -32,7 +32,6 @@
 
 
 #ifdef UNIX_ENABLED
 #ifdef UNIX_ENABLED
 
 
-#include "core/os/thread_dummy.h"
 #include "core/project_settings.h"
 #include "core/project_settings.h"
 #include "drivers/unix/dir_access_unix.h"
 #include "drivers/unix/dir_access_unix.h"
 #include "drivers/unix/file_access_unix.h"
 #include "drivers/unix/file_access_unix.h"
@@ -118,11 +117,10 @@ int OS_Unix::unix_initialize_audio(int p_audio_driver) {
 
 
 void OS_Unix::initialize_core() {
 void OS_Unix::initialize_core() {
 
 
-#ifdef NO_THREADS
-	ThreadDummy::make_default();
-#else
-	ThreadPosix::make_default();
+#if !defined(NO_THREADS)
+	init_thread_posix();
 #endif
 #endif
+
 	FileAccess::make_default<FileAccessUnix>(FileAccess::ACCESS_RESOURCES);
 	FileAccess::make_default<FileAccessUnix>(FileAccess::ACCESS_RESOURCES);
 	FileAccess::make_default<FileAccessUnix>(FileAccess::ACCESS_USERDATA);
 	FileAccess::make_default<FileAccessUnix>(FileAccess::ACCESS_USERDATA);
 	FileAccess::make_default<FileAccessUnix>(FileAccess::ACCESS_FILESYSTEM);
 	FileAccess::make_default<FileAccessUnix>(FileAccess::ACCESS_FILESYSTEM);

+ 6 - 96
drivers/unix/thread_posix.cpp

@@ -28,92 +28,14 @@
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /*************************************************************************/
 /*************************************************************************/
 
 
-#include "thread_posix.h"
-
 #if (defined(UNIX_ENABLED) || defined(PTHREAD_ENABLED)) && !defined(NO_THREADS)
 #if (defined(UNIX_ENABLED) || defined(PTHREAD_ENABLED)) && !defined(NO_THREADS)
 
 
-#include "core/os/memory.h"
-#include "core/safe_refcount.h"
-#include "core/script_language.h"
-
-#ifdef PTHREAD_BSD_SET_NAME
-#include <pthread_np.h>
-#endif
-
-static void _thread_id_key_destr_callback(void *p_value) {
-	memdelete(static_cast<Thread::ID *>(p_value));
-}
-
-static pthread_key_t _create_thread_id_key() {
-	pthread_key_t key;
-	pthread_key_create(&key, &_thread_id_key_destr_callback);
-	return key;
-}
-
-pthread_key_t ThreadPosix::thread_id_key = _create_thread_id_key();
-Thread::ID ThreadPosix::next_thread_id = 0;
-
-Thread::ID ThreadPosix::get_id() const {
-
-	return id;
-}
-
-Thread *ThreadPosix::create_thread_posix() {
-
-	return memnew(ThreadPosix);
-}
-
-void *ThreadPosix::thread_callback(void *userdata) {
-
-	ThreadPosix *t = reinterpret_cast<ThreadPosix *>(userdata);
-	t->id = atomic_increment(&next_thread_id);
-	pthread_setspecific(thread_id_key, (void *)memnew(ID(t->id)));
-
-	ScriptServer::thread_enter(); //scripts may need to attach a stack
-
-	t->callback(t->user);
-
-	ScriptServer::thread_exit();
-
-	return NULL;
-}
-
-Thread *ThreadPosix::create_func_posix(ThreadCreateCallback p_callback, void *p_user, const Settings &) {
-
-	ThreadPosix *tr = memnew(ThreadPosix);
-	tr->callback = p_callback;
-	tr->user = p_user;
-	pthread_attr_init(&tr->pthread_attr);
-	pthread_attr_setdetachstate(&tr->pthread_attr, PTHREAD_CREATE_JOINABLE);
-	pthread_attr_setstacksize(&tr->pthread_attr, 256 * 1024);
-
-	pthread_create(&tr->pthread, &tr->pthread_attr, thread_callback, tr);
-
-	return tr;
-}
-Thread::ID ThreadPosix::get_thread_id_func_posix() {
-
-	void *value = pthread_getspecific(thread_id_key);
-
-	if (value)
-		return *static_cast<ID *>(value);
-
-	ID new_id = atomic_increment(&next_thread_id);
-	pthread_setspecific(thread_id_key, (void *)memnew(ID(new_id)));
-	return new_id;
-}
-void ThreadPosix::wait_to_finish_func_posix(Thread *p_thread) {
-
-	ThreadPosix *tp = static_cast<ThreadPosix *>(p_thread);
-	ERR_FAIL_COND(!tp);
-	ERR_FAIL_COND(tp->pthread == 0);
-
-	pthread_join(tp->pthread, NULL);
-	tp->pthread = 0;
-}
+#include "thread_posix.h"
 
 
-Error ThreadPosix::set_name_func_posix(const String &p_name) {
+#include "core/os/thread.h"
+#include "core/ustring.h"
 
 
+static Error set_name(const String &p_name) {
 #ifdef PTHREAD_NO_RENAME
 #ifdef PTHREAD_NO_RENAME
 	return ERR_UNAVAILABLE;
 	return ERR_UNAVAILABLE;
 
 
@@ -141,22 +63,10 @@ Error ThreadPosix::set_name_func_posix(const String &p_name) {
 	return err == 0 ? OK : ERR_INVALID_PARAMETER;
 	return err == 0 ? OK : ERR_INVALID_PARAMETER;
 
 
 #endif // PTHREAD_NO_RENAME
 #endif // PTHREAD_NO_RENAME
-};
-
-void ThreadPosix::make_default() {
-
-	create_func = create_func_posix;
-	get_thread_id_func = get_thread_id_func_posix;
-	wait_to_finish_func = wait_to_finish_func_posix;
-	set_name_func = set_name_func_posix;
-}
-
-ThreadPosix::ThreadPosix() {
-
-	pthread = 0;
 }
 }
 
 
-ThreadPosix::~ThreadPosix() {
+void init_thread_posix() {
+	Thread::_set_platform_funcs(&set_name, nullptr);
 }
 }
 
 
 #endif
 #endif

+ 2 - 37
drivers/unix/thread_posix.h

@@ -31,43 +31,8 @@
 #ifndef THREAD_POSIX_H
 #ifndef THREAD_POSIX_H
 #define THREAD_POSIX_H
 #define THREAD_POSIX_H
 
 
-#if (defined(UNIX_ENABLED) || defined(PTHREAD_ENABLED)) && !defined(NO_THREADS)
-
-#include "core/os/thread.h"
-#include <pthread.h>
-#include <sys/types.h>
-
-class ThreadPosix : public Thread {
-
-	static pthread_key_t thread_id_key;
-	static ID next_thread_id;
-
-	pthread_t pthread;
-	pthread_attr_t pthread_attr;
-	ThreadCreateCallback callback;
-	void *user;
-	ID id;
-
-	static Thread *create_thread_posix();
-
-	static void *thread_callback(void *userdata);
-
-	static Thread *create_func_posix(ThreadCreateCallback p_callback, void *, const Settings &);
-	static ID get_thread_id_func_posix();
-	static void wait_to_finish_func_posix(Thread *p_thread);
-
-	static Error set_name_func_posix(const String &p_name);
-
-	ThreadPosix();
-
-public:
-	virtual ID get_id() const;
-
-	static void make_default();
-
-	~ThreadPosix();
-};
-
+#if !defined(NO_THREADS)
+void init_thread_posix();
 #endif
 #endif
 
 
 #endif
 #endif

+ 3 - 10
drivers/wasapi/audio_driver_wasapi.cpp

@@ -406,7 +406,7 @@ Error AudioDriverWASAPI::init() {
 	exit_thread = false;
 	exit_thread = false;
 	thread_exited = false;
 	thread_exited = false;
 
 
-	thread = Thread::create(thread_func, this);
+	thread.start(thread_func, this);
 
 
 	return OK;
 	return OK;
 }
 }
@@ -791,13 +791,8 @@ void AudioDriverWASAPI::unlock() {
 
 
 void AudioDriverWASAPI::finish() {
 void AudioDriverWASAPI::finish() {
 
 
-	if (thread) {
-		exit_thread = true;
-		Thread::wait_to_finish(thread);
-
-		memdelete(thread);
-		thread = NULL;
-	}
+	exit_thread = true;
+	thread.wait_to_finish();
 
 
 	finish_capture_device();
 	finish_capture_device();
 	finish_render_device();
 	finish_render_device();
@@ -855,8 +850,6 @@ String AudioDriverWASAPI::capture_get_device() {
 
 
 AudioDriverWASAPI::AudioDriverWASAPI() {
 AudioDriverWASAPI::AudioDriverWASAPI() {
 
 
-	thread = NULL;
-
 	samples_in.clear();
 	samples_in.clear();
 
 
 	channels = 0;
 	channels = 0;

+ 1 - 1
drivers/wasapi/audio_driver_wasapi.h

@@ -76,7 +76,7 @@ class AudioDriverWASAPI : public AudioDriver {
 	AudioDeviceWASAPI audio_output;
 	AudioDeviceWASAPI audio_output;
 
 
 	Mutex mutex;
 	Mutex mutex;
-	Thread *thread;
+	Thread thread;
 
 
 	Vector<int32_t> samples_in;
 	Vector<int32_t> samples_in;
 
 

+ 0 - 100
drivers/windows/thread_windows.cpp

@@ -1,100 +0,0 @@
-/*************************************************************************/
-/*  thread_windows.cpp                                                   */
-/*************************************************************************/
-/*                       This file is part of:                           */
-/*                           GODOT ENGINE                                */
-/*                      https://godotengine.org                          */
-/*************************************************************************/
-/* 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       */
-/* "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.                */
-/*************************************************************************/
-
-#include "thread_windows.h"
-
-#if defined(WINDOWS_ENABLED) && !defined(UWP_ENABLED)
-
-#include "core/os/memory.h"
-
-Thread::ID ThreadWindows::get_id() const {
-
-	return id;
-}
-
-Thread *ThreadWindows::create_thread_windows() {
-
-	return memnew(ThreadWindows);
-}
-
-DWORD ThreadWindows::thread_callback(LPVOID userdata) {
-
-	ThreadWindows *t = reinterpret_cast<ThreadWindows *>(userdata);
-
-	ScriptServer::thread_enter(); //scripts may need to attach a stack
-
-	t->id = (ID)GetCurrentThreadId(); // must implement
-	t->callback(t->user);
-	SetEvent(t->handle);
-
-	ScriptServer::thread_exit();
-
-	return 0;
-}
-
-Thread *ThreadWindows::create_func_windows(ThreadCreateCallback p_callback, void *p_user, const Settings &) {
-
-	ThreadWindows *tr = memnew(ThreadWindows);
-	tr->callback = p_callback;
-	tr->user = p_user;
-	tr->handle = CreateEvent(NULL, TRUE, FALSE, NULL);
-
-	QueueUserWorkItem(thread_callback, tr, WT_EXECUTELONGFUNCTION);
-
-	return tr;
-}
-Thread::ID ThreadWindows::get_thread_id_func_windows() {
-
-	return (ID)GetCurrentThreadId(); //must implement
-}
-void ThreadWindows::wait_to_finish_func_windows(Thread *p_thread) {
-
-	ThreadWindows *tp = static_cast<ThreadWindows *>(p_thread);
-	ERR_FAIL_COND(!tp);
-	WaitForSingleObject(tp->handle, INFINITE);
-	CloseHandle(tp->handle);
-	//`memdelete(tp);
-}
-
-void ThreadWindows::make_default() {
-
-	create_func = create_func_windows;
-	get_thread_id_func = get_thread_id_func_windows;
-	wait_to_finish_func = wait_to_finish_func_windows;
-}
-
-ThreadWindows::ThreadWindows() :
-		handle(NULL) {
-}
-
-ThreadWindows::~ThreadWindows() {
-}
-
-#endif

+ 0 - 68
drivers/windows/thread_windows.h

@@ -1,68 +0,0 @@
-/*************************************************************************/
-/*  thread_windows.h                                                     */
-/*************************************************************************/
-/*                       This file is part of:                           */
-/*                           GODOT ENGINE                                */
-/*                      https://godotengine.org                          */
-/*************************************************************************/
-/* 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       */
-/* "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.                */
-/*************************************************************************/
-
-#ifndef THREAD_WINDOWS_H
-#define THREAD_WINDOWS_H
-
-#ifdef WINDOWS_ENABLED
-
-#include "core/os/thread.h"
-#include "core/script_language.h"
-
-#include <windows.h>
-
-class ThreadWindows : public Thread {
-
-	ThreadCreateCallback callback;
-	void *user;
-	ID id;
-	HANDLE handle;
-
-	static Thread *create_thread_windows();
-
-	static DWORD WINAPI thread_callback(LPVOID userdata);
-
-	static Thread *create_func_windows(ThreadCreateCallback p_callback, void *, const Settings &);
-	static ID get_thread_id_func_windows();
-	static void wait_to_finish_func_windows(Thread *p_thread);
-
-	ThreadWindows();
-
-public:
-	virtual ID get_id() const;
-
-	static void make_default();
-
-	~ThreadWindows();
-};
-
-#endif
-
-#endif

+ 3 - 11
drivers/xaudio2/audio_driver_xaudio2.cpp

@@ -79,7 +79,7 @@ Error AudioDriverXAudio2::init() {
 	hr = xaudio->CreateSourceVoice(&source_voice, &wave_format, 0, XAUDIO2_MAX_FREQ_RATIO, &voice_callback);
 	hr = xaudio->CreateSourceVoice(&source_voice, &wave_format, 0, XAUDIO2_MAX_FREQ_RATIO, &voice_callback);
 	ERR_FAIL_COND_V_MSG(hr != S_OK, ERR_UNAVAILABLE, "Error creating XAudio2 source voice. Error code: " + itos(hr) + ".");
 	ERR_FAIL_COND_V_MSG(hr != S_OK, ERR_UNAVAILABLE, "Error creating XAudio2 source voice. Error code: " + itos(hr) + ".");
 
 
-	thread = Thread::create(AudioDriverXAudio2::thread_func, this);
+	thread.start(AudioDriverXAudio2::thread_func, this);
 
 
 	return OK;
 	return OK;
 }
 }
@@ -157,24 +157,20 @@ float AudioDriverXAudio2::get_latency() {
 
 
 void AudioDriverXAudio2::lock() {
 void AudioDriverXAudio2::lock() {
 
 
-	if (!thread)
-		return;
 	mutex.lock();
 	mutex.lock();
 }
 }
 void AudioDriverXAudio2::unlock() {
 void AudioDriverXAudio2::unlock() {
 
 
-	if (!thread)
-		return;
 	mutex.unlock();
 	mutex.unlock();
 }
 }
 
 
 void AudioDriverXAudio2::finish() {
 void AudioDriverXAudio2::finish() {
 
 
-	if (!thread)
+	if (!thread.is_started())
 		return;
 		return;
 
 
 	exit_thread = true;
 	exit_thread = true;
-	Thread::wait_to_finish(thread);
+	thread.wait_to_finish();
 
 
 	if (source_voice) {
 	if (source_voice) {
 		source_voice->Stop(0);
 		source_voice->Stop(0);
@@ -191,13 +187,9 @@ void AudioDriverXAudio2::finish() {
 	}
 	}
 
 
 	mastering_voice->DestroyVoice();
 	mastering_voice->DestroyVoice();
-
-	memdelete(thread);
-	thread = NULL;
 }
 }
 
 
 AudioDriverXAudio2::AudioDriverXAudio2() :
 AudioDriverXAudio2::AudioDriverXAudio2() :
-		thread(NULL),
 		current_buffer(0) {
 		current_buffer(0) {
 	wave_format = { 0 };
 	wave_format = { 0 };
 	for (int i = 0; i < AUDIO_BUFFERS; i++) {
 	for (int i = 0; i < AUDIO_BUFFERS; i++) {

+ 1 - 1
drivers/xaudio2/audio_driver_xaudio2.h

@@ -64,7 +64,7 @@ class AudioDriverXAudio2 : public AudioDriver {
 		void STDMETHODCALLTYPE OnVoiceError(void *pBufferContext, HRESULT Error) {}
 		void STDMETHODCALLTYPE OnVoiceError(void *pBufferContext, HRESULT Error) {}
 	};
 	};
 
 
-	Thread *thread;
+	Thread thread;
 	Mutex mutex;
 	Mutex mutex;
 
 
 	int32_t *samples_in;
 	int32_t *samples_in;

+ 6 - 3
editor/audio_stream_preview.cpp

@@ -199,8 +199,10 @@ Ref<AudioStreamPreview> AudioStreamPreviewGenerator::generate_preview(const Ref<
 	preview->preview->preview = maxmin;
 	preview->preview->preview = maxmin;
 	preview->preview->length = len_s;
 	preview->preview->length = len_s;
 
 
-	if (preview->playback.is_valid())
-		preview->thread = Thread::create(_preview_thread, preview);
+	if (preview->playback.is_valid()) {
+		preview->thread = memnew(Thread);
+		preview->thread->start(_preview_thread, preview);
+	}
 
 
 	return preview->preview;
 	return preview->preview;
 }
 }
@@ -220,7 +222,8 @@ void AudioStreamPreviewGenerator::_notification(int p_what) {
 		for (Map<ObjectID, Preview>::Element *E = previews.front(); E; E = E->next()) {
 		for (Map<ObjectID, Preview>::Element *E = previews.front(); E; E = E->next()) {
 			if (!E->get().generating) {
 			if (!E->get().generating) {
 				if (E->get().thread) {
 				if (E->get().thread) {
-					Thread::wait_to_finish(E->get().thread);
+					E->get().thread->wait_to_finish();
+					memdelete(E->get().thread);
 					E->get().thread = NULL;
 					E->get().thread = NULL;
 				}
 				}
 				if (!ObjectDB::get_instance(E->key())) { //no longer in use, get rid of preview
 				if (!ObjectDB::get_instance(E->key())) { //no longer in use, get rid of preview

+ 11 - 20
editor/editor_file_system.cpp

@@ -609,7 +609,7 @@ void EditorFileSystem::scan() {
 	if (false /*&& bool(Globals::get_singleton()->get("debug/disable_scan"))*/)
 	if (false /*&& bool(Globals::get_singleton()->get("debug/disable_scan"))*/)
 		return;
 		return;
 
 
-	if (scanning || scanning_changes || thread)
+	if (scanning || scanning_changes || thread.is_started())
 		return;
 		return;
 
 
 	_update_extensions();
 	_update_extensions();
@@ -632,13 +632,13 @@ void EditorFileSystem::scan() {
 		first_scan = false;
 		first_scan = false;
 	} else {
 	} else {
 
 
-		ERR_FAIL_COND(thread);
+		ERR_FAIL_COND(thread.is_started());
 		set_process(true);
 		set_process(true);
 		Thread::Settings s;
 		Thread::Settings s;
 		scanning = true;
 		scanning = true;
 		scan_total = 0;
 		scan_total = 0;
 		s.priority = Thread::PRIORITY_LOW;
 		s.priority = Thread::PRIORITY_LOW;
-		thread = Thread::create(_thread_func, this, s);
+		thread.start(_thread_func, this, s);
 		//tree->hide();
 		//tree->hide();
 		//progress->show();
 		//progress->show();
 	}
 	}
@@ -1067,7 +1067,7 @@ void EditorFileSystem::get_changed_sources(List<String> *r_changed) {
 void EditorFileSystem::scan_changes() {
 void EditorFileSystem::scan_changes() {
 
 
 	if (first_scan || // Prevent a premature changes scan from inhibiting the first full scan
 	if (first_scan || // Prevent a premature changes scan from inhibiting the first full scan
-			scanning || scanning_changes || thread) {
+			scanning || scanning_changes || thread.is_started()) {
 		scan_changes_pending = true;
 		scan_changes_pending = true;
 		set_process(true);
 		set_process(true);
 		return;
 		return;
@@ -1097,12 +1097,12 @@ void EditorFileSystem::scan_changes() {
 		emit_signal("sources_changed", sources_changed.size() > 0);
 		emit_signal("sources_changed", sources_changed.size() > 0);
 	} else {
 	} else {
 
 
-		ERR_FAIL_COND(thread_sources);
+		ERR_FAIL_COND(thread_sources.is_started());
 		set_process(true);
 		set_process(true);
 		scan_total = 0;
 		scan_total = 0;
 		Thread::Settings s;
 		Thread::Settings s;
 		s.priority = Thread::PRIORITY_LOW;
 		s.priority = Thread::PRIORITY_LOW;
-		thread_sources = Thread::create(_thread_func_sources, this, s);
+		thread_sources.start(_thread_func_sources, this, s);
 	}
 	}
 }
 }
 
 
@@ -1116,17 +1116,14 @@ void EditorFileSystem::_notification(int p_what) {
 
 
 		} break;
 		} break;
 		case NOTIFICATION_EXIT_TREE: {
 		case NOTIFICATION_EXIT_TREE: {
-			Thread *active_thread = thread ? thread : thread_sources;
-			if (use_threads && active_thread) {
+			Thread &active_thread = thread.is_started() ? thread : thread_sources;
+			if (use_threads && active_thread.is_started()) {
 				//abort thread if in progress
 				//abort thread if in progress
 				abort_scan = true;
 				abort_scan = true;
 				while (scanning) {
 				while (scanning) {
 					OS::get_singleton()->delay_usec(1000);
 					OS::get_singleton()->delay_usec(1000);
 				}
 				}
-				Thread::wait_to_finish(active_thread);
-				memdelete(active_thread);
-				thread = NULL;
-				thread_sources = NULL;
+				active_thread.wait_to_finish();
 				WARN_PRINT("Scan thread aborted...");
 				WARN_PRINT("Scan thread aborted...");
 				set_process(false);
 				set_process(false);
 			}
 			}
@@ -1151,9 +1148,7 @@ void EditorFileSystem::_notification(int p_what) {
 
 
 						set_process(false);
 						set_process(false);
 
 
-						Thread::wait_to_finish(thread_sources);
-						memdelete(thread_sources);
-						thread_sources = NULL;
+						thread_sources.wait_to_finish();
 						if (_update_scan_actions())
 						if (_update_scan_actions())
 							emit_signal("filesystem_changed");
 							emit_signal("filesystem_changed");
 						emit_signal("sources_changed", sources_changed.size() > 0);
 						emit_signal("sources_changed", sources_changed.size() > 0);
@@ -1168,9 +1163,7 @@ void EditorFileSystem::_notification(int p_what) {
 						memdelete(filesystem);
 						memdelete(filesystem);
 					filesystem = new_filesystem;
 					filesystem = new_filesystem;
 					new_filesystem = NULL;
 					new_filesystem = NULL;
-					Thread::wait_to_finish(thread);
-					memdelete(thread);
-					thread = NULL;
+					thread.wait_to_finish();
 					_update_scan_actions();
 					_update_scan_actions();
 					emit_signal("filesystem_changed");
 					emit_signal("filesystem_changed");
 					emit_signal("sources_changed", sources_changed.size() > 0);
 					emit_signal("sources_changed", sources_changed.size() > 0);
@@ -2135,11 +2128,9 @@ EditorFileSystem::EditorFileSystem() {
 	filesystem = memnew(EditorFileSystemDirectory); //like, empty
 	filesystem = memnew(EditorFileSystemDirectory); //like, empty
 	filesystem->parent = NULL;
 	filesystem->parent = NULL;
 
 
-	thread = NULL;
 	scanning = false;
 	scanning = false;
 	importing = false;
 	importing = false;
 	use_threads = true;
 	use_threads = true;
-	thread_sources = NULL;
 	new_filesystem = NULL;
 	new_filesystem = NULL;
 
 
 	abort_scan = false;
 	abort_scan = false;

+ 2 - 2
editor/editor_file_system.h

@@ -136,7 +136,7 @@ class EditorFileSystem : public Node {
 	};
 	};
 
 
 	bool use_threads;
 	bool use_threads;
-	Thread *thread;
+	Thread thread;
 	static void _thread_func(void *_userdata);
 	static void _thread_func(void *_userdata);
 
 
 	EditorFileSystemDirectory *new_filesystem;
 	EditorFileSystemDirectory *new_filesystem;
@@ -200,7 +200,7 @@ class EditorFileSystem : public Node {
 
 
 	void _scan_new_dir(EditorFileSystemDirectory *p_dir, DirAccess *da, const ScanProgress &p_progress);
 	void _scan_new_dir(EditorFileSystemDirectory *p_dir, DirAccess *da, const ScanProgress &p_progress);
 
 
-	Thread *thread_sources;
+	Thread thread_sources;
 	bool scanning_changes;
 	bool scanning_changes;
 	bool scanning_changes_done;
 	bool scanning_changes_done;
 
 

+ 2 - 5
editor/editor_node.cpp

@@ -5761,9 +5761,7 @@ int EditorNode::execute_and_show_output(const String &p_title, const String &p_p
 
 
 	int prev_len = 0;
 	int prev_len = 0;
 
 
-	eta.execute_output_thread = Thread::create(_execute_thread, &eta);
-
-	ERR_FAIL_COND_V(!eta.execute_output_thread, 0);
+	eta.execute_output_thread.start(_execute_thread, &eta);
 
 
 	while (!eta.done) {
 	while (!eta.done) {
 		eta.execute_output_mutex.lock();
 		eta.execute_output_mutex.lock();
@@ -5777,8 +5775,7 @@ int EditorNode::execute_and_show_output(const String &p_title, const String &p_p
 		OS::get_singleton()->delay_usec(1000);
 		OS::get_singleton()->delay_usec(1000);
 	}
 	}
 
 
-	Thread::wait_to_finish(eta.execute_output_thread);
-	memdelete(eta.execute_output_thread);
+	eta.execute_output_thread.wait_to_finish();
 	execute_outputs->add_text("\nExit Code: " + itos(eta.exitcode));
 	execute_outputs->add_text("\nExit Code: " + itos(eta.exitcode));
 
 
 	if (p_close_on_errors && eta.exitcode != 0) {
 	if (p_close_on_errors && eta.exitcode != 0) {

+ 1 - 1
editor/editor_node.h

@@ -106,7 +106,7 @@ public:
 		String path;
 		String path;
 		List<String> args;
 		List<String> args;
 		String output;
 		String output;
-		Thread *execute_output_thread;
+		Thread execute_output_thread;
 		Mutex execute_output_mutex;
 		Mutex execute_output_mutex;
 		int exitcode;
 		int exitcode;
 		volatile bool done;
 		volatile bool done;

+ 4 - 7
editor/editor_resource_preview.cpp

@@ -456,26 +456,23 @@ void EditorResourcePreview::check_for_invalidation(const String &p_path) {
 }
 }
 
 
 void EditorResourcePreview::start() {
 void EditorResourcePreview::start() {
-	ERR_FAIL_COND_MSG(thread, "Thread already started.");
-	thread = Thread::create(_thread_func, this);
+	ERR_FAIL_COND_MSG(thread.is_started(), "Thread already started.");
+	thread.start(_thread_func, this);
 }
 }
 
 
 void EditorResourcePreview::stop() {
 void EditorResourcePreview::stop() {
-	if (thread) {
+	if (thread.is_started()) {
 		exit = true;
 		exit = true;
 		preview_sem.post();
 		preview_sem.post();
 		while (!exited) {
 		while (!exited) {
 			OS::get_singleton()->delay_usec(10000);
 			OS::get_singleton()->delay_usec(10000);
 			VisualServer::get_singleton()->sync(); //sync pending stuff, as thread may be blocked on visual server
 			VisualServer::get_singleton()->sync(); //sync pending stuff, as thread may be blocked on visual server
 		}
 		}
-		Thread::wait_to_finish(thread);
-		memdelete(thread);
-		thread = NULL;
+		thread.wait_to_finish();
 	}
 	}
 }
 }
 
 
 EditorResourcePreview::EditorResourcePreview() {
 EditorResourcePreview::EditorResourcePreview() {
-	thread = NULL;
 	singleton = this;
 	singleton = this;
 	order = 0;
 	order = 0;
 	exit = false;
 	exit = false;

+ 1 - 1
editor/editor_resource_preview.h

@@ -72,7 +72,7 @@ class EditorResourcePreview : public Node {
 
 
 	Mutex preview_mutex;
 	Mutex preview_mutex;
 	Semaphore preview_sem;
 	Semaphore preview_sem;
-	Thread *thread;
+	Thread thread;
 	volatile bool exit;
 	volatile bool exit;
 	volatile bool exited;
 	volatile bool exited;
 
 

+ 5 - 7
editor/fileserver/editor_file_server.cpp

@@ -43,7 +43,7 @@ void EditorFileServer::_close_client(ClientData *cd) {
 
 
 	cd->connection->disconnect_from_host();
 	cd->connection->disconnect_from_host();
 	cd->efs->wait_mutex.lock();
 	cd->efs->wait_mutex.lock();
-	cd->efs->to_wait.insert(cd->thread);
+	cd->efs->to_wait.insert(&cd->thread);
 	cd->efs->wait_mutex.unlock();
 	cd->efs->wait_mutex.unlock();
 	while (cd->files.size()) {
 	while (cd->files.size()) {
 		memdelete(cd->files.front()->get());
 		memdelete(cd->files.front()->get());
@@ -291,7 +291,7 @@ void EditorFileServer::_thread_start(void *s) {
 				cd->connection = self->server->take_connection();
 				cd->connection = self->server->take_connection();
 				cd->efs = self;
 				cd->efs = self;
 				cd->quit = false;
 				cd->quit = false;
-				cd->thread = Thread::create(_subthread_start, cd);
+				cd->thread.start(_subthread_start, cd);
 			}
 			}
 		}
 		}
 
 
@@ -300,8 +300,7 @@ void EditorFileServer::_thread_start(void *s) {
 			Thread *w = self->to_wait.front()->get();
 			Thread *w = self->to_wait.front()->get();
 			self->to_wait.erase(w);
 			self->to_wait.erase(w);
 			self->wait_mutex.unlock();
 			self->wait_mutex.unlock();
-			Thread::wait_to_finish(w);
-			memdelete(w);
+			w->wait_to_finish();
 			self->wait_mutex.lock();
 			self->wait_mutex.lock();
 		}
 		}
 		self->wait_mutex.unlock();
 		self->wait_mutex.unlock();
@@ -334,7 +333,7 @@ EditorFileServer::EditorFileServer() {
 	quit = false;
 	quit = false;
 	active = false;
 	active = false;
 	cmd = CMD_NONE;
 	cmd = CMD_NONE;
-	thread = Thread::create(_thread_start, this);
+	thread.start(_thread_start, this);
 
 
 	EDITOR_DEF("filesystem/file_server/port", 6010);
 	EDITOR_DEF("filesystem/file_server/port", 6010);
 	EDITOR_DEF("filesystem/file_server/password", "");
 	EDITOR_DEF("filesystem/file_server/password", "");
@@ -343,6 +342,5 @@ EditorFileServer::EditorFileServer() {
 EditorFileServer::~EditorFileServer() {
 EditorFileServer::~EditorFileServer() {
 
 
 	quit = true;
 	quit = true;
-	Thread::wait_to_finish(thread);
-	memdelete(thread);
+	thread.wait_to_finish();
 }
 }

+ 2 - 2
editor/fileserver/editor_file_server.h

@@ -49,7 +49,7 @@ class EditorFileServer : public Object {
 
 
 	struct ClientData {
 	struct ClientData {
 
 
-		Thread *thread;
+		Thread thread;
 		Ref<StreamPeerTCP> connection;
 		Ref<StreamPeerTCP> connection;
 		Map<int, FileAccess *> files;
 		Map<int, FileAccess *> files;
 		EditorFileServer *efs;
 		EditorFileServer *efs;
@@ -63,7 +63,7 @@ class EditorFileServer : public Object {
 	static void _subthread_start(void *s);
 	static void _subthread_start(void *s);
 
 
 	Mutex wait_mutex;
 	Mutex wait_mutex;
-	Thread *thread;
+	Thread thread;
 	static void _thread_start(void *);
 	static void _thread_start(void *);
 	bool quit;
 	bool quit;
 	Command cmd;
 	Command cmd;

+ 3 - 3
main/main.cpp

@@ -359,8 +359,6 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
 
 
 	MAIN_PRINT("Main: Initialize Globals");
 	MAIN_PRINT("Main: Initialize Globals");
 
 
-	Thread::_main_thread_id = Thread::get_caller_id();
-
 	globals = memnew(ProjectSettings);
 	globals = memnew(ProjectSettings);
 	input_map = memnew(InputMap);
 	input_map = memnew(InputMap);
 
 
@@ -1275,9 +1273,11 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
 	// Print engine name and version
 	// Print engine name and version
 	print_line(String(VERSION_NAME) + " v" + get_full_version_string() + " - " + String(VERSION_WEBSITE));
 	print_line(String(VERSION_NAME) + " v" + get_full_version_string() + " - " + String(VERSION_WEBSITE));
 
 
+#if !defined(NO_THREADS)
 	if (p_main_tid_override) {
 	if (p_main_tid_override) {
-		Thread::_main_thread_id = p_main_tid_override;
+		Thread::main_thread_id = p_main_tid_override;
 	}
 	}
+#endif
 
 
 	Error err = OS::get_singleton()->initialize(video_mode, video_driver_idx, audio_driver_idx);
 	Error err = OS::get_singleton()->initialize(video_mode, video_driver_idx, audio_driver_idx);
 	if (err != OK) {
 	if (err != OK) {

+ 3 - 2
modules/cvtt/image_compress_cvtt.cpp

@@ -267,12 +267,13 @@ void image_compress_cvtt(Image *p_image, float p_lossy_quality, Image::CompressS
 		job_queue.num_tasks = static_cast<uint32_t>(tasks.size());
 		job_queue.num_tasks = static_cast<uint32_t>(tasks.size());
 
 
 		for (int i = 0; i < num_job_threads; i++) {
 		for (int i = 0; i < num_job_threads; i++) {
-			threads_wb[i] = Thread::create(_digest_job_queue, &job_queue);
+			threads_wb[i] = memnew(Thread);
+			threads_wb[i]->start(_digest_job_queue, &job_queue);
 		}
 		}
 		_digest_job_queue(&job_queue);
 		_digest_job_queue(&job_queue);
 
 
 		for (int i = 0; i < num_job_threads; i++) {
 		for (int i = 0; i < num_job_threads; i++) {
-			Thread::wait_to_finish(threads_wb[i]);
+			threads_wb[i]->wait_to_finish();
 			memdelete(threads_wb[i]);
 			memdelete(threads_wb[i]);
 		}
 		}
 	}
 	}

+ 1 - 1
modules/gdnative/android/android_gdn.cpp

@@ -48,7 +48,7 @@ extern "C" {
 
 
 JNIEnv *GDAPI godot_android_get_env() {
 JNIEnv *GDAPI godot_android_get_env() {
 #ifdef __ANDROID__
 #ifdef __ANDROID__
-	return ThreadAndroid::get_env();
+	return get_jni_env();
 #else
 #else
 	return NULL;
 	return NULL;
 #endif
 #endif

+ 3 - 7
modules/gdscript/language_server/gdscript_language_server.cpp

@@ -36,7 +36,6 @@
 #include "editor/editor_node.h"
 #include "editor/editor_node.h"
 
 
 GDScriptLanguageServer::GDScriptLanguageServer() {
 GDScriptLanguageServer::GDScriptLanguageServer() {
-	thread = NULL;
 	thread_running = false;
 	thread_running = false;
 	started = false;
 	started = false;
 
 
@@ -88,9 +87,8 @@ void GDScriptLanguageServer::start() {
 	if (protocol.start(port, IP_Address("127.0.0.1")) == OK) {
 	if (protocol.start(port, IP_Address("127.0.0.1")) == OK) {
 		EditorNode::get_log()->add_message("--- GDScript language server started ---", EditorLog::MSG_TYPE_EDITOR);
 		EditorNode::get_log()->add_message("--- GDScript language server started ---", EditorLog::MSG_TYPE_EDITOR);
 		if (use_thread) {
 		if (use_thread) {
-			ERR_FAIL_COND(thread != NULL);
 			thread_running = true;
 			thread_running = true;
-			thread = Thread::create(GDScriptLanguageServer::thread_main, this);
+			thread.start(GDScriptLanguageServer::thread_main, this);
 		}
 		}
 		set_process_internal(!use_thread);
 		set_process_internal(!use_thread);
 		started = true;
 		started = true;
@@ -99,11 +97,9 @@ void GDScriptLanguageServer::start() {
 
 
 void GDScriptLanguageServer::stop() {
 void GDScriptLanguageServer::stop() {
 	if (use_thread) {
 	if (use_thread) {
-		ERR_FAIL_COND(NULL == thread);
+		ERR_FAIL_COND(!thread.is_started());
 		thread_running = false;
 		thread_running = false;
-		Thread::wait_to_finish(thread);
-		memdelete(thread);
-		thread = NULL;
+		thread.wait_to_finish();
 	}
 	}
 	protocol.stop();
 	protocol.stop();
 	started = false;
 	started = false;

+ 1 - 1
modules/gdscript/language_server/gdscript_language_server.h

@@ -40,7 +40,7 @@ class GDScriptLanguageServer : public EditorPlugin {
 
 
 	GDScriptLanguageProtocol protocol;
 	GDScriptLanguageProtocol protocol;
 
 
-	Thread *thread;
+	Thread thread;
 	bool thread_running;
 	bool thread_running;
 	bool started;
 	bool started;
 	bool use_thread;
 	bool use_thread;

+ 3 - 3
modules/lightmapper_cpu/lightmapper_cpu.cpp

@@ -251,7 +251,8 @@ bool LightmapperCPU::_parallel_run(int p_count, const String &p_description, Bak
 	td.count = p_count;
 	td.count = p_count;
 	td.thread_func = p_thread_func;
 	td.thread_func = p_thread_func;
 	td.userdata = p_userdata;
 	td.userdata = p_userdata;
-	Thread *runner_thread = Thread::create(_thread_func_callback, &td);
+	Thread runner_thread;
+	runner_thread.start(_thread_func_callback, &td);
 
 
 	int progress = thread_progress;
 	int progress = thread_progress;
 
 
@@ -263,8 +264,7 @@ bool LightmapperCPU::_parallel_run(int p_count, const String &p_description, Bak
 		progress = thread_progress;
 		progress = thread_progress;
 	}
 	}
 	thread_cancelled = cancelled;
 	thread_cancelled = cancelled;
-	Thread::wait_to_finish(runner_thread);
-	memdelete(runner_thread);
+	runner_thread.wait_to_finish();
 #endif
 #endif
 
 
 	thread_cancelled = false;
 	thread_cancelled = false;

+ 9 - 9
modules/mono/mono_gd/support/android_support.cpp

@@ -109,7 +109,7 @@ bool jni_exception_check(JNIEnv *p_env) {
 String app_native_lib_dir_cache;
 String app_native_lib_dir_cache;
 
 
 String determine_app_native_lib_dir() {
 String determine_app_native_lib_dir() {
-	JNIEnv *env = ThreadAndroid::get_env();
+	JNIEnv *env = get_jni_env();
 
 
 	ScopedLocalRef<jclass> activityThreadClass(env, env->FindClass("android/app/ActivityThread"));
 	ScopedLocalRef<jclass> activityThreadClass(env, env->FindClass("android/app/ActivityThread"));
 	jmethodID currentActivityThread = env->GetStaticMethodID(activityThreadClass, "currentActivityThread", "()Landroid/app/ActivityThread;");
 	jmethodID currentActivityThread = env->GetStaticMethodID(activityThreadClass, "currentActivityThread", "()Landroid/app/ActivityThread;");
@@ -253,7 +253,7 @@ int32_t get_build_version_sdk_int() {
 	// android.os.Build.VERSION.SDK_INT
 	// android.os.Build.VERSION.SDK_INT
 
 
 	if (build_version_sdk_int == 0) {
 	if (build_version_sdk_int == 0) {
-		JNIEnv *env = ThreadAndroid::get_env();
+		JNIEnv *env = get_jni_env();
 
 
 		jclass versionClass = env->FindClass("android/os/Build$VERSION");
 		jclass versionClass = env->FindClass("android/os/Build$VERSION");
 		ERR_FAIL_NULL_V(versionClass, 0);
 		ERR_FAIL_NULL_V(versionClass, 0);
@@ -281,7 +281,7 @@ MonoBoolean _gd_mono_init_cert_store() {
 	//	return false;
 	//	return false;
 	// }
 	// }
 
 
-	JNIEnv *env = ThreadAndroid::get_env();
+	JNIEnv *env = get_jni_env();
 
 
 	ScopedLocalRef<jclass> keyStoreClass(env, env->FindClass("java/security/KeyStore"));
 	ScopedLocalRef<jclass> keyStoreClass(env, env->FindClass("java/security/KeyStore"));
 
 
@@ -322,7 +322,7 @@ MonoArray *_gd_mono_android_cert_store_lookup(MonoString *p_alias) {
 		return NULL;
 		return NULL;
 	}
 	}
 
 
-	JNIEnv *env = ThreadAndroid::get_env();
+	JNIEnv *env = get_jni_env();
 
 
 	ScopedLocalRef<jstring> js_alias(env, env->NewStringUTF(alias_utf8));
 	ScopedLocalRef<jstring> js_alias(env, env->NewStringUTF(alias_utf8));
 	mono_free(alias_utf8);
 	mono_free(alias_utf8);
@@ -380,7 +380,7 @@ void cleanup() {
 	if (godot_dl_handle)
 	if (godot_dl_handle)
 		gd_mono_android_dlclose(godot_dl_handle, NULL);
 		gd_mono_android_dlclose(godot_dl_handle, NULL);
 
 
-	JNIEnv *env = ThreadAndroid::get_env();
+	JNIEnv *env = get_jni_env();
 
 
 	if (certStore) {
 	if (certStore) {
 		env->DeleteGlobalRef(certStore);
 		env->DeleteGlobalRef(certStore);
@@ -438,7 +438,7 @@ GD_PINVOKE_EXPORT mono_bool _monodroid_get_network_interface_up_state(const char
 
 
 	*r_is_up = 0;
 	*r_is_up = 0;
 
 
-	JNIEnv *env = ThreadAndroid::get_env();
+	JNIEnv *env = get_jni_env();
 
 
 	jclass networkInterfaceClass = env->FindClass("java/net/NetworkInterface");
 	jclass networkInterfaceClass = env->FindClass("java/net/NetworkInterface");
 	ERR_FAIL_NULL_V(networkInterfaceClass, 0);
 	ERR_FAIL_NULL_V(networkInterfaceClass, 0);
@@ -470,7 +470,7 @@ GD_PINVOKE_EXPORT mono_bool _monodroid_get_network_interface_supports_multicast(
 
 
 	*r_supports_multicast = 0;
 	*r_supports_multicast = 0;
 
 
-	JNIEnv *env = ThreadAndroid::get_env();
+	JNIEnv *env = get_jni_env();
 
 
 	jclass networkInterfaceClass = env->FindClass("java/net/NetworkInterface");
 	jclass networkInterfaceClass = env->FindClass("java/net/NetworkInterface");
 	ERR_FAIL_NULL_V(networkInterfaceClass, 0);
 	ERR_FAIL_NULL_V(networkInterfaceClass, 0);
@@ -508,7 +508,7 @@ static void interop_get_active_network_dns_servers(char **r_dns_servers, int *dn
 	CRASH_COND(get_build_version_sdk_int() < 23);
 	CRASH_COND(get_build_version_sdk_int() < 23);
 #endif
 #endif
 
 
-	JNIEnv *env = ThreadAndroid::get_env();
+	JNIEnv *env = get_jni_env();
 
 
 	GodotJavaWrapper *godot_java = ((OS_Android *)OS::get_singleton())->get_godot_java();
 	GodotJavaWrapper *godot_java = ((OS_Android *)OS::get_singleton())->get_godot_java();
 	jobject activity = godot_java->get_activity();
 	jobject activity = godot_java->get_activity();
@@ -649,7 +649,7 @@ GD_PINVOKE_EXPORT const char *_monodroid_timezone_get_default_id() {
 	//
 	//
 	// TimeZone.getDefault().getID()
 	// TimeZone.getDefault().getID()
 
 
-	JNIEnv *env = ThreadAndroid::get_env();
+	JNIEnv *env = get_jni_env();
 
 
 	ScopedLocalRef<jclass> timeZoneClass(env, env->FindClass("java/util/TimeZone"));
 	ScopedLocalRef<jclass> timeZoneClass(env, env->FindClass("java/util/TimeZone"));
 	ERR_FAIL_NULL_V(timeZoneClass, NULL);
 	ERR_FAIL_NULL_V(timeZoneClass, NULL);

+ 5 - 11
modules/opensimplex/noise_texture.cpp

@@ -34,7 +34,6 @@
 
 
 NoiseTexture::NoiseTexture() {
 NoiseTexture::NoiseTexture() {
 	update_queued = false;
 	update_queued = false;
-	noise_thread = NULL;
 	regen_queued = false;
 	regen_queued = false;
 	first_time = true;
 	first_time = true;
 
 
@@ -53,10 +52,7 @@ NoiseTexture::NoiseTexture() {
 
 
 NoiseTexture::~NoiseTexture() {
 NoiseTexture::~NoiseTexture() {
 	VS::get_singleton()->free(texture);
 	VS::get_singleton()->free(texture);
-	if (noise_thread) {
-		Thread::wait_to_finish(noise_thread);
-		memdelete(noise_thread);
-	}
+	noise_thread.wait_to_finish();
 }
 }
 
 
 void NoiseTexture::_bind_methods() {
 void NoiseTexture::_bind_methods() {
@@ -110,11 +106,9 @@ void NoiseTexture::_set_texture_data(const Ref<Image> &p_image) {
 void NoiseTexture::_thread_done(const Ref<Image> &p_image) {
 void NoiseTexture::_thread_done(const Ref<Image> &p_image) {
 
 
 	_set_texture_data(p_image);
 	_set_texture_data(p_image);
-	Thread::wait_to_finish(noise_thread);
-	memdelete(noise_thread);
-	noise_thread = NULL;
+	noise_thread.wait_to_finish();
 	if (regen_queued) {
 	if (regen_queued) {
-		noise_thread = Thread::create(_thread_function, this);
+		noise_thread.start(_thread_function, this);
 		regen_queued = false;
 		regen_queued = false;
 	}
 	}
 }
 }
@@ -168,8 +162,8 @@ void NoiseTexture::_update_texture() {
 #endif
 #endif
 	if (use_thread) {
 	if (use_thread) {
 
 
-		if (!noise_thread) {
-			noise_thread = Thread::create(_thread_function, this);
+		if (noise_thread.is_started()) {
+			noise_thread.start(_thread_function, this);
 			regen_queued = false;
 			regen_queued = false;
 		} else {
 		} else {
 			regen_queued = true;
 			regen_queued = true;

+ 1 - 1
modules/opensimplex/noise_texture.h

@@ -45,7 +45,7 @@ class NoiseTexture : public Texture {
 private:
 private:
 	Ref<Image> data;
 	Ref<Image> data;
 
 
-	Thread *noise_thread;
+	Thread noise_thread;
 
 
 	bool first_time;
 	bool first_time;
 	bool update_queued;
 	bool update_queued;

+ 2 - 5
modules/theora/video_stream_theora.cpp

@@ -142,9 +142,7 @@ void VideoStreamPlaybackTheora::clear() {
 #ifdef THEORA_USE_THREAD_STREAMING
 #ifdef THEORA_USE_THREAD_STREAMING
 	thread_exit = true;
 	thread_exit = true;
 	thread_sem.post(); //just in case
 	thread_sem.post(); //just in case
-	Thread::wait_to_finish(thread);
-	memdelete(thread);
-	thread = NULL;
+	thread.wait_to_finish();
 	ring_buffer.clear();
 	ring_buffer.clear();
 #endif
 #endif
 
 
@@ -184,7 +182,7 @@ void VideoStreamPlaybackTheora::set_file(const String &p_file) {
 	int read = file->get_buffer(read_buffer.ptr(), to_read);
 	int read = file->get_buffer(read_buffer.ptr(), to_read);
 	ring_buffer.write(read_buffer.ptr(), read);
 	ring_buffer.write(read_buffer.ptr(), read);
 
 
-	thread = Thread::create(_streaming_thread, this);
+	thread.start(_streaming_thread, this);
 
 
 #endif
 #endif
 
 
@@ -693,7 +691,6 @@ VideoStreamPlaybackTheora::VideoStreamPlaybackTheora() {
 	int rb_power = nearest_shift(RB_SIZE_KB * 1024);
 	int rb_power = nearest_shift(RB_SIZE_KB * 1024);
 	ring_buffer.resize(rb_power);
 	ring_buffer.resize(rb_power);
 	read_buffer.resize(RB_SIZE_KB * 1024);
 	read_buffer.resize(RB_SIZE_KB * 1024);
-	thread = NULL;
 	thread_exit = false;
 	thread_exit = false;
 	thread_eof = false;
 	thread_eof = false;
 
 

+ 1 - 1
modules/theora/video_stream_theora.h

@@ -113,7 +113,7 @@ class VideoStreamPlaybackTheora : public VideoStreamPlayback {
 	Vector<uint8_t> read_buffer;
 	Vector<uint8_t> read_buffer;
 	bool thread_eof;
 	bool thread_eof;
 	Semaphore thread_sem;
 	Semaphore thread_sem;
-	Thread *thread;
+	Thread thread;
 	volatile bool thread_exit;
 	volatile bool thread_exit;
 
 
 	static void _streaming_thread(void *ud);
 	static void _streaming_thread(void *ud);

+ 1 - 1
platform/android/api/jni_singleton.h

@@ -87,7 +87,7 @@ public:
 			v = (jvalue *)alloca(sizeof(jvalue) * p_argcount);
 			v = (jvalue *)alloca(sizeof(jvalue) * p_argcount);
 		}
 		}
 
 
-		JNIEnv *env = ThreadAndroid::get_env();
+		JNIEnv *env = get_jni_env();
 
 
 		int res = env->PushLocalFrame(16);
 		int res = env->PushLocalFrame(16);
 
 

+ 4 - 4
platform/android/audio_driver_jandroid.cpp

@@ -74,7 +74,7 @@ Error AudioDriverAndroid::init() {
 
 
 	//        __android_log_print(ANDROID_LOG_VERBOSE, "SDL", "SDL audio: opening device");
 	//        __android_log_print(ANDROID_LOG_VERBOSE, "SDL", "SDL audio: opening device");
 
 
-	JNIEnv *env = ThreadAndroid::get_env();
+	JNIEnv *env = get_jni_env();
 	int mix_rate = GLOBAL_GET("audio/mix_rate");
 	int mix_rate = GLOBAL_GET("audio/mix_rate");
 
 
 	int latency = GLOBAL_GET("audio/output_latency");
 	int latency = GLOBAL_GET("audio/output_latency");
@@ -101,7 +101,7 @@ void AudioDriverAndroid::start() {
 
 
 void AudioDriverAndroid::setup(jobject p_io) {
 void AudioDriverAndroid::setup(jobject p_io) {
 
 
-	JNIEnv *env = ThreadAndroid::get_env();
+	JNIEnv *env = get_jni_env();
 	io = p_io;
 	io = p_io;
 
 
 	jclass c = env->GetObjectClass(io);
 	jclass c = env->GetObjectClass(io);
@@ -176,7 +176,7 @@ void AudioDriverAndroid::unlock() {
 
 
 void AudioDriverAndroid::finish() {
 void AudioDriverAndroid::finish() {
 
 
-	JNIEnv *env = ThreadAndroid::get_env();
+	JNIEnv *env = get_jni_env();
 	env->CallVoidMethod(io, _quit);
 	env->CallVoidMethod(io, _quit);
 
 
 	if (audioBuffer) {
 	if (audioBuffer) {
@@ -190,7 +190,7 @@ void AudioDriverAndroid::finish() {
 
 
 void AudioDriverAndroid::set_pause(bool p_pause) {
 void AudioDriverAndroid::set_pause(bool p_pause) {
 
 
-	JNIEnv *env = ThreadAndroid::get_env();
+	JNIEnv *env = get_jni_env();
 	env->CallVoidMethod(io, _pause, p_pause);
 	env->CallVoidMethod(io, _pause, p_pause);
 }
 }
 
 

+ 7 - 7
platform/android/dir_access_jandroid.cpp

@@ -49,7 +49,7 @@ DirAccess *DirAccessJAndroid::create_fs() {
 Error DirAccessJAndroid::list_dir_begin() {
 Error DirAccessJAndroid::list_dir_begin() {
 
 
 	list_dir_end();
 	list_dir_end();
-	JNIEnv *env = ThreadAndroid::get_env();
+	JNIEnv *env = get_jni_env();
 
 
 	jstring js = env->NewStringUTF(current_dir.utf8().get_data());
 	jstring js = env->NewStringUTF(current_dir.utf8().get_data());
 	int res = env->CallIntMethod(io, _dir_open, js);
 	int res = env->CallIntMethod(io, _dir_open, js);
@@ -65,7 +65,7 @@ String DirAccessJAndroid::get_next() {
 
 
 	ERR_FAIL_COND_V(id == 0, "");
 	ERR_FAIL_COND_V(id == 0, "");
 
 
-	JNIEnv *env = ThreadAndroid::get_env();
+	JNIEnv *env = get_jni_env();
 	jstring str = (jstring)env->CallObjectMethod(io, _dir_next, id);
 	jstring str = (jstring)env->CallObjectMethod(io, _dir_next, id);
 	if (!str)
 	if (!str)
 		return "";
 		return "";
@@ -77,7 +77,7 @@ String DirAccessJAndroid::get_next() {
 
 
 bool DirAccessJAndroid::current_is_dir() const {
 bool DirAccessJAndroid::current_is_dir() const {
 
 
-	JNIEnv *env = ThreadAndroid::get_env();
+	JNIEnv *env = get_jni_env();
 
 
 	return env->CallBooleanMethod(io, _dir_is_dir, id);
 	return env->CallBooleanMethod(io, _dir_is_dir, id);
 }
 }
@@ -92,7 +92,7 @@ void DirAccessJAndroid::list_dir_end() {
 	if (id == 0)
 	if (id == 0)
 		return;
 		return;
 
 
-	JNIEnv *env = ThreadAndroid::get_env();
+	JNIEnv *env = get_jni_env();
 	env->CallVoidMethod(io, _dir_close, id);
 	env->CallVoidMethod(io, _dir_close, id);
 	id = 0;
 	id = 0;
 }
 }
@@ -109,7 +109,7 @@ String DirAccessJAndroid::get_drive(int p_drive) {
 
 
 Error DirAccessJAndroid::change_dir(String p_dir) {
 Error DirAccessJAndroid::change_dir(String p_dir) {
 
 
-	JNIEnv *env = ThreadAndroid::get_env();
+	JNIEnv *env = get_jni_env();
 
 
 	if (p_dir == "" || p_dir == "." || (p_dir == ".." && current_dir == ""))
 	if (p_dir == "" || p_dir == "." || (p_dir == ".." && current_dir == ""))
 		return OK;
 		return OK;
@@ -166,7 +166,7 @@ bool DirAccessJAndroid::file_exists(String p_file) {
 
 
 bool DirAccessJAndroid::dir_exists(String p_dir) {
 bool DirAccessJAndroid::dir_exists(String p_dir) {
 
 
-	JNIEnv *env = ThreadAndroid::get_env();
+	JNIEnv *env = get_jni_env();
 
 
 	String sd;
 	String sd;
 
 
@@ -225,7 +225,7 @@ size_t DirAccessJAndroid::get_space_left() {
 
 
 void DirAccessJAndroid::setup(jobject p_io) {
 void DirAccessJAndroid::setup(jobject p_io) {
 
 
-	JNIEnv *env = ThreadAndroid::get_env();
+	JNIEnv *env = get_jni_env();
 	io = p_io;
 	io = p_io;
 
 
 	jclass c = env->GetObjectClass(io);
 	jclass c = env->GetObjectClass(io);

+ 3 - 4
platform/android/export/export.cpp

@@ -272,7 +272,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
 	Vector<Device> devices;
 	Vector<Device> devices;
 	volatile bool devices_changed;
 	volatile bool devices_changed;
 	Mutex device_lock;
 	Mutex device_lock;
-	Thread *check_for_changes_thread;
+	Thread check_for_changes_thread;
 	volatile bool quit_request;
 	volatile bool quit_request;
 
 
 	static void _check_for_changes_poll_thread(void *ud) {
 	static void _check_for_changes_poll_thread(void *ud) {
@@ -3284,13 +3284,12 @@ public:
 
 
 		plugins_changed = true;
 		plugins_changed = true;
 		quit_request = false;
 		quit_request = false;
-		check_for_changes_thread = Thread::create(_check_for_changes_poll_thread, this);
+		check_for_changes_thread.start(_check_for_changes_poll_thread, this);
 	}
 	}
 
 
 	~EditorExportPlatformAndroid() {
 	~EditorExportPlatformAndroid() {
 		quit_request = true;
 		quit_request = true;
-		Thread::wait_to_finish(check_for_changes_thread);
-		memdelete(check_for_changes_thread);
+		check_for_changes_thread.wait_to_finish();
 	}
 	}
 };
 };
 
 

+ 3 - 3
platform/android/java_class_wrapper.cpp

@@ -38,7 +38,7 @@ bool JavaClass::_call_method(JavaObject *p_instance, const StringName &p_method,
 	if (!M)
 	if (!M)
 		return false;
 		return false;
 
 
-	JNIEnv *env = ThreadAndroid::get_env();
+	JNIEnv *env = get_jni_env();
 
 
 	MethodInfo *method = NULL;
 	MethodInfo *method = NULL;
 	for (List<MethodInfo>::Element *E = M->get().front(); E; E = E->next()) {
 	for (List<MethodInfo>::Element *E = M->get().front(); E; E = E->next()) {
@@ -1048,7 +1048,7 @@ Ref<JavaClass> JavaClassWrapper::wrap(const String &p_class) {
 	if (class_cache.has(p_class))
 	if (class_cache.has(p_class))
 		return class_cache[p_class];
 		return class_cache[p_class];
 
 
-	JNIEnv *env = ThreadAndroid::get_env();
+	JNIEnv *env = get_jni_env();
 
 
 	jclass bclass = env->FindClass(p_class.utf8().get_data());
 	jclass bclass = env->FindClass(p_class.utf8().get_data());
 	ERR_FAIL_COND_V(!bclass, Ref<JavaClass>());
 	ERR_FAIL_COND_V(!bclass, Ref<JavaClass>());
@@ -1242,7 +1242,7 @@ JavaClassWrapper::JavaClassWrapper(jobject p_activity) {
 
 
 	singleton = this;
 	singleton = this;
 
 
-	JNIEnv *env = ThreadAndroid::get_env();
+	JNIEnv *env = get_jni_env();
 
 
 	jclass activityClass = env->FindClass("android/app/Activity");
 	jclass activityClass = env->FindClass("android/app/Activity");
 	jmethodID getClassLoader = env->GetMethodID(activityClass, "getClassLoader", "()Ljava/lang/ClassLoader;");
 	jmethodID getClassLoader = env->GetMethodID(activityClass, "getClassLoader", "()Ljava/lang/ClassLoader;");

+ 15 - 15
platform/android/java_godot_io_wrapper.cpp

@@ -76,7 +76,7 @@ jobject GodotIOJavaWrapper::get_instance() {
 
 
 Error GodotIOJavaWrapper::open_uri(const String &p_uri) {
 Error GodotIOJavaWrapper::open_uri(const String &p_uri) {
 	if (_open_URI) {
 	if (_open_URI) {
-		JNIEnv *env = ThreadAndroid::get_env();
+		JNIEnv *env = get_jni_env();
 		jstring jStr = env->NewStringUTF(p_uri.utf8().get_data());
 		jstring jStr = env->NewStringUTF(p_uri.utf8().get_data());
 		return env->CallIntMethod(godot_io_instance, _open_URI, jStr) ? ERR_CANT_OPEN : OK;
 		return env->CallIntMethod(godot_io_instance, _open_URI, jStr) ? ERR_CANT_OPEN : OK;
 	} else {
 	} else {
@@ -86,7 +86,7 @@ Error GodotIOJavaWrapper::open_uri(const String &p_uri) {
 
 
 String GodotIOJavaWrapper::get_user_data_dir() {
 String GodotIOJavaWrapper::get_user_data_dir() {
 	if (_get_data_dir) {
 	if (_get_data_dir) {
-		JNIEnv *env = ThreadAndroid::get_env();
+		JNIEnv *env = get_jni_env();
 		jstring s = (jstring)env->CallObjectMethod(godot_io_instance, _get_data_dir);
 		jstring s = (jstring)env->CallObjectMethod(godot_io_instance, _get_data_dir);
 		return jstring_to_string(s, env);
 		return jstring_to_string(s, env);
 	} else {
 	} else {
@@ -96,7 +96,7 @@ String GodotIOJavaWrapper::get_user_data_dir() {
 
 
 String GodotIOJavaWrapper::get_locale() {
 String GodotIOJavaWrapper::get_locale() {
 	if (_get_locale) {
 	if (_get_locale) {
-		JNIEnv *env = ThreadAndroid::get_env();
+		JNIEnv *env = get_jni_env();
 		jstring s = (jstring)env->CallObjectMethod(godot_io_instance, _get_locale);
 		jstring s = (jstring)env->CallObjectMethod(godot_io_instance, _get_locale);
 		return jstring_to_string(s, env);
 		return jstring_to_string(s, env);
 	} else {
 	} else {
@@ -106,7 +106,7 @@ String GodotIOJavaWrapper::get_locale() {
 
 
 String GodotIOJavaWrapper::get_model() {
 String GodotIOJavaWrapper::get_model() {
 	if (_get_model) {
 	if (_get_model) {
-		JNIEnv *env = ThreadAndroid::get_env();
+		JNIEnv *env = get_jni_env();
 		jstring s = (jstring)env->CallObjectMethod(godot_io_instance, _get_model);
 		jstring s = (jstring)env->CallObjectMethod(godot_io_instance, _get_model);
 		return jstring_to_string(s, env);
 		return jstring_to_string(s, env);
 	} else {
 	} else {
@@ -116,7 +116,7 @@ String GodotIOJavaWrapper::get_model() {
 
 
 int GodotIOJavaWrapper::get_screen_dpi() {
 int GodotIOJavaWrapper::get_screen_dpi() {
 	if (_get_screen_DPI) {
 	if (_get_screen_DPI) {
-		JNIEnv *env = ThreadAndroid::get_env();
+		JNIEnv *env = get_jni_env();
 		return env->CallIntMethod(godot_io_instance, _get_screen_DPI);
 		return env->CallIntMethod(godot_io_instance, _get_screen_DPI);
 	} else {
 	} else {
 		return 160;
 		return 160;
@@ -125,7 +125,7 @@ int GodotIOJavaWrapper::get_screen_dpi() {
 
 
 void GodotIOJavaWrapper::get_window_safe_area(int (&p_rect_xywh)[4]) {
 void GodotIOJavaWrapper::get_window_safe_area(int (&p_rect_xywh)[4]) {
 	if (_get_window_safe_area) {
 	if (_get_window_safe_area) {
-		JNIEnv *env = ThreadAndroid::get_env();
+		JNIEnv *env = get_jni_env();
 		jintArray returnArray = (jintArray)env->CallObjectMethod(godot_io_instance, _get_window_safe_area);
 		jintArray returnArray = (jintArray)env->CallObjectMethod(godot_io_instance, _get_window_safe_area);
 		ERR_FAIL_COND(env->GetArrayLength(returnArray) != 4);
 		ERR_FAIL_COND(env->GetArrayLength(returnArray) != 4);
 		jint *arrayBody = env->GetIntArrayElements(returnArray, JNI_FALSE);
 		jint *arrayBody = env->GetIntArrayElements(returnArray, JNI_FALSE);
@@ -138,7 +138,7 @@ void GodotIOJavaWrapper::get_window_safe_area(int (&p_rect_xywh)[4]) {
 
 
 String GodotIOJavaWrapper::get_unique_id() {
 String GodotIOJavaWrapper::get_unique_id() {
 	if (_get_unique_id) {
 	if (_get_unique_id) {
-		JNIEnv *env = ThreadAndroid::get_env();
+		JNIEnv *env = get_jni_env();
 		jstring s = (jstring)env->CallObjectMethod(godot_io_instance, _get_unique_id);
 		jstring s = (jstring)env->CallObjectMethod(godot_io_instance, _get_unique_id);
 		return jstring_to_string(s, env);
 		return jstring_to_string(s, env);
 	} else {
 	} else {
@@ -152,7 +152,7 @@ bool GodotIOJavaWrapper::has_vk() {
 
 
 void GodotIOJavaWrapper::show_vk(const String &p_existing, bool p_multiline, int p_max_input_length, int p_cursor_start, int p_cursor_end) {
 void GodotIOJavaWrapper::show_vk(const String &p_existing, bool p_multiline, int p_max_input_length, int p_cursor_start, int p_cursor_end) {
 	if (_show_keyboard) {
 	if (_show_keyboard) {
-		JNIEnv *env = ThreadAndroid::get_env();
+		JNIEnv *env = get_jni_env();
 		jstring jStr = env->NewStringUTF(p_existing.utf8().get_data());
 		jstring jStr = env->NewStringUTF(p_existing.utf8().get_data());
 		env->CallVoidMethod(godot_io_instance, _show_keyboard, jStr, p_multiline, p_max_input_length, p_cursor_start, p_cursor_end);
 		env->CallVoidMethod(godot_io_instance, _show_keyboard, jStr, p_multiline, p_max_input_length, p_cursor_start, p_cursor_end);
 	}
 	}
@@ -160,21 +160,21 @@ void GodotIOJavaWrapper::show_vk(const String &p_existing, bool p_multiline, int
 
 
 void GodotIOJavaWrapper::hide_vk() {
 void GodotIOJavaWrapper::hide_vk() {
 	if (_hide_keyboard) {
 	if (_hide_keyboard) {
-		JNIEnv *env = ThreadAndroid::get_env();
+		JNIEnv *env = get_jni_env();
 		env->CallVoidMethod(godot_io_instance, _hide_keyboard);
 		env->CallVoidMethod(godot_io_instance, _hide_keyboard);
 	}
 	}
 }
 }
 
 
 void GodotIOJavaWrapper::set_screen_orientation(int p_orient) {
 void GodotIOJavaWrapper::set_screen_orientation(int p_orient) {
 	if (_set_screen_orientation) {
 	if (_set_screen_orientation) {
-		JNIEnv *env = ThreadAndroid::get_env();
+		JNIEnv *env = get_jni_env();
 		env->CallVoidMethod(godot_io_instance, _set_screen_orientation, p_orient);
 		env->CallVoidMethod(godot_io_instance, _set_screen_orientation, p_orient);
 	}
 	}
 }
 }
 
 
 int GodotIOJavaWrapper::get_screen_orientation() const {
 int GodotIOJavaWrapper::get_screen_orientation() const {
 	if (_get_screen_orientation) {
 	if (_get_screen_orientation) {
-		JNIEnv *env = ThreadAndroid::get_env();
+		JNIEnv *env = get_jni_env();
 		return env->CallIntMethod(godot_io_instance, _get_screen_orientation);
 		return env->CallIntMethod(godot_io_instance, _get_screen_orientation);
 	} else {
 	} else {
 		return 0;
 		return 0;
@@ -183,7 +183,7 @@ int GodotIOJavaWrapper::get_screen_orientation() const {
 
 
 String GodotIOJavaWrapper::get_system_dir(int p_dir) {
 String GodotIOJavaWrapper::get_system_dir(int p_dir) {
 	if (_get_system_dir) {
 	if (_get_system_dir) {
-		JNIEnv *env = ThreadAndroid::get_env();
+		JNIEnv *env = get_jni_env();
 		jstring s = (jstring)env->CallObjectMethod(godot_io_instance, _get_system_dir, p_dir);
 		jstring s = (jstring)env->CallObjectMethod(godot_io_instance, _get_system_dir, p_dir);
 		return jstring_to_string(s, env);
 		return jstring_to_string(s, env);
 	} else {
 	} else {
@@ -197,7 +197,7 @@ void GodotIOJavaWrapper::play_video(const String &p_path) {
 
 
 bool GodotIOJavaWrapper::is_video_playing() {
 bool GodotIOJavaWrapper::is_video_playing() {
 	if (_is_video_playing) {
 	if (_is_video_playing) {
-		JNIEnv *env = ThreadAndroid::get_env();
+		JNIEnv *env = get_jni_env();
 		return env->CallBooleanMethod(godot_io_instance, _is_video_playing);
 		return env->CallBooleanMethod(godot_io_instance, _is_video_playing);
 	} else {
 	} else {
 		return false;
 		return false;
@@ -206,14 +206,14 @@ bool GodotIOJavaWrapper::is_video_playing() {
 
 
 void GodotIOJavaWrapper::pause_video() {
 void GodotIOJavaWrapper::pause_video() {
 	if (_pause_video) {
 	if (_pause_video) {
-		JNIEnv *env = ThreadAndroid::get_env();
+		JNIEnv *env = get_jni_env();
 		env->CallVoidMethod(godot_io_instance, _pause_video);
 		env->CallVoidMethod(godot_io_instance, _pause_video);
 	}
 	}
 }
 }
 
 
 void GodotIOJavaWrapper::stop_video() {
 void GodotIOJavaWrapper::stop_video() {
 	if (_stop_video) {
 	if (_stop_video) {
-		JNIEnv *env = ThreadAndroid::get_env();
+		JNIEnv *env = get_jni_env();
 		env->CallVoidMethod(godot_io_instance, _stop_video);
 		env->CallVoidMethod(godot_io_instance, _stop_video);
 	}
 	}
 }
 }

+ 4 - 4
platform/android/java_godot_lib_jni.cpp

@@ -84,7 +84,7 @@ static void _initialize_java_modules() {
 
 
 		// TODO create wrapper for class loader
 		// TODO create wrapper for class loader
 
 
-		JNIEnv *env = ThreadAndroid::get_env();
+		JNIEnv *env = get_jni_env();
 		jclass classLoader = env->FindClass("java/lang/ClassLoader");
 		jclass classLoader = env->FindClass("java/lang/ClassLoader");
 		jmethodID findClass = env->GetMethodID(classLoader, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;");
 		jmethodID findClass = env->GetMethodID(classLoader, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;");
 
 
@@ -132,7 +132,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv *en
 	godot_java = new GodotJavaWrapper(env, activity, godot_instance);
 	godot_java = new GodotJavaWrapper(env, activity, godot_instance);
 	godot_io_java = new GodotIOJavaWrapper(env, godot_java->get_member_object("io", "Lorg/godotengine/godot/GodotIO;", env));
 	godot_io_java = new GodotIOJavaWrapper(env, godot_java->get_member_object("io", "Lorg/godotengine/godot/GodotIO;", env));
 
 
-	ThreadAndroid::make_default(jvm);
+	init_thread_jandroid(jvm, env);
 
 
 	jobject amgr = env->NewGlobalRef(p_asset_manager);
 	jobject amgr = env->NewGlobalRef(p_asset_manager);
 
 
@@ -164,7 +164,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_ondestroy(JNIEnv *env
 }
 }
 
 
 JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setup(JNIEnv *env, jclass clazz, jobjectArray p_cmdline) {
 JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setup(JNIEnv *env, jclass clazz, jobjectArray p_cmdline) {
-	ThreadAndroid::setup_thread();
+	setup_android_thread();
 
 
 	const char **cmdline = NULL;
 	const char **cmdline = NULL;
 	jstring *j_cmdline = NULL;
 	jstring *j_cmdline = NULL;
@@ -422,7 +422,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_focusout(JNIEnv *env,
 
 
 JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_audio(JNIEnv *env, jclass clazz) {
 JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_audio(JNIEnv *env, jclass clazz) {
 
 
-	ThreadAndroid::setup_thread();
+	setup_android_thread();
 	AudioDriverAndroid::thread_func(env);
 	AudioDriverAndroid::thread_func(env);
 }
 }
 
 

+ 19 - 19
platform/android/java_godot_wrapper.cpp

@@ -91,7 +91,7 @@ jobject GodotJavaWrapper::get_activity() {
 jobject GodotJavaWrapper::get_member_object(const char *p_name, const char *p_class, JNIEnv *p_env) {
 jobject GodotJavaWrapper::get_member_object(const char *p_name, const char *p_class, JNIEnv *p_env) {
 	if (godot_class) {
 	if (godot_class) {
 		if (p_env == NULL)
 		if (p_env == NULL)
-			p_env = ThreadAndroid::get_env();
+			p_env = get_jni_env();
 
 
 		jfieldID fid = p_env->GetStaticFieldID(godot_class, p_name, p_class);
 		jfieldID fid = p_env->GetStaticFieldID(godot_class, p_name, p_class);
 		return p_env->GetStaticObjectField(godot_class, fid);
 		return p_env->GetStaticObjectField(godot_class, fid);
@@ -102,7 +102,7 @@ jobject GodotJavaWrapper::get_member_object(const char *p_name, const char *p_cl
 
 
 jobject GodotJavaWrapper::get_class_loader() {
 jobject GodotJavaWrapper::get_class_loader() {
 	if (_get_class_loader) {
 	if (_get_class_loader) {
-		JNIEnv *env = ThreadAndroid::get_env();
+		JNIEnv *env = get_jni_env();
 		return env->CallObjectMethod(activity, _get_class_loader);
 		return env->CallObjectMethod(activity, _get_class_loader);
 	} else {
 	} else {
 		return NULL;
 		return NULL;
@@ -119,7 +119,7 @@ void GodotJavaWrapper::gfx_init(bool gl2) {
 void GodotJavaWrapper::on_video_init(JNIEnv *p_env) {
 void GodotJavaWrapper::on_video_init(JNIEnv *p_env) {
 	if (_on_video_init)
 	if (_on_video_init)
 		if (p_env == NULL)
 		if (p_env == NULL)
-			p_env = ThreadAndroid::get_env();
+			p_env = get_jni_env();
 
 
 	p_env->CallVoidMethod(godot_instance, _on_video_init);
 	p_env->CallVoidMethod(godot_instance, _on_video_init);
 }
 }
@@ -127,7 +127,7 @@ void GodotJavaWrapper::on_video_init(JNIEnv *p_env) {
 void GodotJavaWrapper::on_godot_main_loop_started(JNIEnv *p_env) {
 void GodotJavaWrapper::on_godot_main_loop_started(JNIEnv *p_env) {
 	if (_on_godot_main_loop_started) {
 	if (_on_godot_main_loop_started) {
 		if (p_env == NULL) {
 		if (p_env == NULL) {
-			p_env = ThreadAndroid::get_env();
+			p_env = get_jni_env();
 		}
 		}
 	}
 	}
 	p_env->CallVoidMethod(godot_instance, _on_godot_main_loop_started);
 	p_env->CallVoidMethod(godot_instance, _on_godot_main_loop_started);
@@ -136,7 +136,7 @@ void GodotJavaWrapper::on_godot_main_loop_started(JNIEnv *p_env) {
 void GodotJavaWrapper::restart(JNIEnv *p_env) {
 void GodotJavaWrapper::restart(JNIEnv *p_env) {
 	if (_restart)
 	if (_restart)
 		if (p_env == NULL)
 		if (p_env == NULL)
-			p_env = ThreadAndroid::get_env();
+			p_env = get_jni_env();
 
 
 	p_env->CallVoidMethod(godot_instance, _restart);
 	p_env->CallVoidMethod(godot_instance, _restart);
 }
 }
@@ -144,21 +144,21 @@ void GodotJavaWrapper::restart(JNIEnv *p_env) {
 void GodotJavaWrapper::force_quit(JNIEnv *p_env) {
 void GodotJavaWrapper::force_quit(JNIEnv *p_env) {
 	if (_finish)
 	if (_finish)
 		if (p_env == NULL)
 		if (p_env == NULL)
-			p_env = ThreadAndroid::get_env();
+			p_env = get_jni_env();
 
 
 	p_env->CallVoidMethod(godot_instance, _finish);
 	p_env->CallVoidMethod(godot_instance, _finish);
 }
 }
 
 
 void GodotJavaWrapper::set_keep_screen_on(bool p_enabled) {
 void GodotJavaWrapper::set_keep_screen_on(bool p_enabled) {
 	if (_set_keep_screen_on) {
 	if (_set_keep_screen_on) {
-		JNIEnv *env = ThreadAndroid::get_env();
+		JNIEnv *env = get_jni_env();
 		env->CallVoidMethod(godot_instance, _set_keep_screen_on, p_enabled);
 		env->CallVoidMethod(godot_instance, _set_keep_screen_on, p_enabled);
 	}
 	}
 }
 }
 
 
 void GodotJavaWrapper::alert(const String &p_message, const String &p_title) {
 void GodotJavaWrapper::alert(const String &p_message, const String &p_title) {
 	if (_alert) {
 	if (_alert) {
-		JNIEnv *env = ThreadAndroid::get_env();
+		JNIEnv *env = get_jni_env();
 		jstring jStrMessage = env->NewStringUTF(p_message.utf8().get_data());
 		jstring jStrMessage = env->NewStringUTF(p_message.utf8().get_data());
 		jstring jStrTitle = env->NewStringUTF(p_title.utf8().get_data());
 		jstring jStrTitle = env->NewStringUTF(p_title.utf8().get_data());
 		env->CallVoidMethod(godot_instance, _alert, jStrMessage, jStrTitle);
 		env->CallVoidMethod(godot_instance, _alert, jStrMessage, jStrTitle);
@@ -166,7 +166,7 @@ void GodotJavaWrapper::alert(const String &p_message, const String &p_title) {
 }
 }
 
 
 int GodotJavaWrapper::get_gles_version_code() {
 int GodotJavaWrapper::get_gles_version_code() {
-	JNIEnv *env = ThreadAndroid::get_env();
+	JNIEnv *env = get_jni_env();
 	if (_get_GLES_version_code) {
 	if (_get_GLES_version_code) {
 		return env->CallIntMethod(godot_instance, _get_GLES_version_code);
 		return env->CallIntMethod(godot_instance, _get_GLES_version_code);
 	}
 	}
@@ -180,7 +180,7 @@ bool GodotJavaWrapper::has_get_clipboard() {
 
 
 String GodotJavaWrapper::get_clipboard() {
 String GodotJavaWrapper::get_clipboard() {
 	if (_get_clipboard) {
 	if (_get_clipboard) {
-		JNIEnv *env = ThreadAndroid::get_env();
+		JNIEnv *env = get_jni_env();
 		jstring s = (jstring)env->CallObjectMethod(godot_instance, _get_clipboard);
 		jstring s = (jstring)env->CallObjectMethod(godot_instance, _get_clipboard);
 		return jstring_to_string(s, env);
 		return jstring_to_string(s, env);
 	} else {
 	} else {
@@ -190,7 +190,7 @@ String GodotJavaWrapper::get_clipboard() {
 
 
 String GodotJavaWrapper::get_input_fallback_mapping() {
 String GodotJavaWrapper::get_input_fallback_mapping() {
 	if (_get_input_fallback_mapping) {
 	if (_get_input_fallback_mapping) {
-		JNIEnv *env = ThreadAndroid::get_env();
+		JNIEnv *env = get_jni_env();
 		jstring fallback_mapping = (jstring)env->CallObjectMethod(godot_instance, _get_input_fallback_mapping);
 		jstring fallback_mapping = (jstring)env->CallObjectMethod(godot_instance, _get_input_fallback_mapping);
 		return jstring_to_string(fallback_mapping, env);
 		return jstring_to_string(fallback_mapping, env);
 	} else {
 	} else {
@@ -204,7 +204,7 @@ bool GodotJavaWrapper::has_set_clipboard() {
 
 
 void GodotJavaWrapper::set_clipboard(const String &p_text) {
 void GodotJavaWrapper::set_clipboard(const String &p_text) {
 	if (_set_clipboard) {
 	if (_set_clipboard) {
-		JNIEnv *env = ThreadAndroid::get_env();
+		JNIEnv *env = get_jni_env();
 		jstring jStr = env->NewStringUTF(p_text.utf8().get_data());
 		jstring jStr = env->NewStringUTF(p_text.utf8().get_data());
 		env->CallVoidMethod(godot_instance, _set_clipboard, jStr);
 		env->CallVoidMethod(godot_instance, _set_clipboard, jStr);
 	}
 	}
@@ -212,7 +212,7 @@ void GodotJavaWrapper::set_clipboard(const String &p_text) {
 
 
 bool GodotJavaWrapper::request_permission(const String &p_name) {
 bool GodotJavaWrapper::request_permission(const String &p_name) {
 	if (_request_permission) {
 	if (_request_permission) {
-		JNIEnv *env = ThreadAndroid::get_env();
+		JNIEnv *env = get_jni_env();
 		jstring jStrName = env->NewStringUTF(p_name.utf8().get_data());
 		jstring jStrName = env->NewStringUTF(p_name.utf8().get_data());
 		return env->CallBooleanMethod(godot_instance, _request_permission, jStrName);
 		return env->CallBooleanMethod(godot_instance, _request_permission, jStrName);
 	} else {
 	} else {
@@ -222,7 +222,7 @@ bool GodotJavaWrapper::request_permission(const String &p_name) {
 
 
 bool GodotJavaWrapper::request_permissions() {
 bool GodotJavaWrapper::request_permissions() {
 	if (_request_permissions) {
 	if (_request_permissions) {
-		JNIEnv *env = ThreadAndroid::get_env();
+		JNIEnv *env = get_jni_env();
 		return env->CallBooleanMethod(godot_instance, _request_permissions);
 		return env->CallBooleanMethod(godot_instance, _request_permissions);
 	} else {
 	} else {
 		return false;
 		return false;
@@ -232,7 +232,7 @@ bool GodotJavaWrapper::request_permissions() {
 Vector<String> GodotJavaWrapper::get_granted_permissions() const {
 Vector<String> GodotJavaWrapper::get_granted_permissions() const {
 	Vector<String> permissions_list;
 	Vector<String> permissions_list;
 	if (_get_granted_permissions) {
 	if (_get_granted_permissions) {
-		JNIEnv *env = ThreadAndroid::get_env();
+		JNIEnv *env = get_jni_env();
 		jobject permissions_object = env->CallObjectMethod(godot_instance, _get_granted_permissions);
 		jobject permissions_object = env->CallObjectMethod(godot_instance, _get_granted_permissions);
 		jobjectArray *arr = reinterpret_cast<jobjectArray *>(&permissions_object);
 		jobjectArray *arr = reinterpret_cast<jobjectArray *>(&permissions_object);
 
 
@@ -250,14 +250,14 @@ Vector<String> GodotJavaWrapper::get_granted_permissions() const {
 
 
 void GodotJavaWrapper::init_input_devices() {
 void GodotJavaWrapper::init_input_devices() {
 	if (_init_input_devices) {
 	if (_init_input_devices) {
-		JNIEnv *env = ThreadAndroid::get_env();
+		JNIEnv *env = get_jni_env();
 		env->CallVoidMethod(godot_instance, _init_input_devices);
 		env->CallVoidMethod(godot_instance, _init_input_devices);
 	}
 	}
 }
 }
 
 
 jobject GodotJavaWrapper::get_surface() {
 jobject GodotJavaWrapper::get_surface() {
 	if (_get_surface) {
 	if (_get_surface) {
-		JNIEnv *env = ThreadAndroid::get_env();
+		JNIEnv *env = get_jni_env();
 		return env->CallObjectMethod(godot_instance, _get_surface);
 		return env->CallObjectMethod(godot_instance, _get_surface);
 	} else {
 	} else {
 		return NULL;
 		return NULL;
@@ -266,7 +266,7 @@ jobject GodotJavaWrapper::get_surface() {
 
 
 bool GodotJavaWrapper::is_activity_resumed() {
 bool GodotJavaWrapper::is_activity_resumed() {
 	if (_is_activity_resumed) {
 	if (_is_activity_resumed) {
-		JNIEnv *env = ThreadAndroid::get_env();
+		JNIEnv *env = get_jni_env();
 		return env->CallBooleanMethod(godot_instance, _is_activity_resumed);
 		return env->CallBooleanMethod(godot_instance, _is_activity_resumed);
 	} else {
 	} else {
 		return false;
 		return false;
@@ -275,7 +275,7 @@ bool GodotJavaWrapper::is_activity_resumed() {
 
 
 void GodotJavaWrapper::vibrate(int p_duration_ms) {
 void GodotJavaWrapper::vibrate(int p_duration_ms) {
 	if (_vibrate) {
 	if (_vibrate) {
-		JNIEnv *env = ThreadAndroid::get_env();
+		JNIEnv *env = get_jni_env();
 		env->CallVoidMethod(godot_instance, _vibrate, p_duration_ms);
 		env->CallVoidMethod(godot_instance, _vibrate, p_duration_ms);
 	}
 	}
 }
 }

+ 3 - 3
platform/android/net_socket_android.cpp

@@ -39,7 +39,7 @@ jmethodID NetSocketAndroid::_multicast_lock_release = 0;
 
 
 void NetSocketAndroid::setup(jobject p_net_utils) {
 void NetSocketAndroid::setup(jobject p_net_utils) {
 
 
-	JNIEnv *env = ThreadAndroid::get_env();
+	JNIEnv *env = get_jni_env();
 
 
 	net_utils = env->NewGlobalRef(p_net_utils);
 	net_utils = env->NewGlobalRef(p_net_utils);
 
 
@@ -52,14 +52,14 @@ void NetSocketAndroid::setup(jobject p_net_utils) {
 
 
 void NetSocketAndroid::multicast_lock_acquire() {
 void NetSocketAndroid::multicast_lock_acquire() {
 	if (_multicast_lock_acquire) {
 	if (_multicast_lock_acquire) {
-		JNIEnv *env = ThreadAndroid::get_env();
+		JNIEnv *env = get_jni_env();
 		env->CallVoidMethod(net_utils, _multicast_lock_acquire);
 		env->CallVoidMethod(net_utils, _multicast_lock_acquire);
 	}
 	}
 }
 }
 
 
 void NetSocketAndroid::multicast_lock_release() {
 void NetSocketAndroid::multicast_lock_release() {
 	if (_multicast_lock_release) {
 	if (_multicast_lock_release) {
-		JNIEnv *env = ThreadAndroid::get_env();
+		JNIEnv *env = get_jni_env();
 		env->CallVoidMethod(net_utils, _multicast_lock_release);
 		env->CallVoidMethod(net_utils, _multicast_lock_release);
 	}
 	}
 }
 }

+ 2 - 2
platform/android/string_android.h

@@ -37,14 +37,14 @@
 /**
 /**
  * Converts JNI jstring to Godot String.
  * Converts JNI jstring to Godot String.
  * @param source Source JNI string. If null an empty string is returned.
  * @param source Source JNI string. If null an empty string is returned.
- * @param env JNI environment instance. If null obtained by ThreadAndroid::get_env().
+ * @param env JNI environment instance. If null obtained by get_jni_env().
  * @return Godot string instance.
  * @return Godot string instance.
  */
  */
 static inline String jstring_to_string(jstring source, JNIEnv *env = NULL) {
 static inline String jstring_to_string(jstring source, JNIEnv *env = NULL) {
 	String result;
 	String result;
 	if (source) {
 	if (source) {
 		if (!env) {
 		if (!env) {
-			env = ThreadAndroid::get_env();
+			env = get_jni_env();
 		}
 		}
 		const char *const source_utf8 = env->GetStringUTFChars(source, NULL);
 		const char *const source_utf8 = env->GetStringUTFChars(source, NULL);
 		if (source_utf8) {
 		if (source_utf8) {

+ 14 - 112
platform/android/thread_jandroid.cpp

@@ -30,127 +30,29 @@
 
 
 #include "thread_jandroid.h"
 #include "thread_jandroid.h"
 
 
-#include "core/os/memory.h"
-#include "core/safe_refcount.h"
-#include "core/script_language.h"
+#include "core/os/thread.h"
 
 
-static void _thread_id_key_destr_callback(void *p_value) {
-	memdelete(static_cast<Thread::ID *>(p_value));
-}
-
-static pthread_key_t _create_thread_id_key() {
-	pthread_key_t key;
-	pthread_key_create(&key, &_thread_id_key_destr_callback);
-	return key;
-}
-
-pthread_key_t ThreadAndroid::thread_id_key = _create_thread_id_key();
-Thread::ID ThreadAndroid::next_thread_id = 0;
-
-Thread::ID ThreadAndroid::get_id() const {
-
-	return id;
-}
-
-Thread *ThreadAndroid::create_thread_jandroid() {
-
-	return memnew(ThreadAndroid);
-}
-
-void *ThreadAndroid::thread_callback(void *userdata) {
-
-	ThreadAndroid *t = reinterpret_cast<ThreadAndroid *>(userdata);
-	setup_thread();
-	ScriptServer::thread_enter(); //scripts may need to attach a stack
-	t->id = atomic_increment(&next_thread_id);
-	pthread_setspecific(thread_id_key, (void *)memnew(ID(t->id)));
-	t->callback(t->user);
-	ScriptServer::thread_exit();
-	return NULL;
-}
-
-Thread *ThreadAndroid::create_func_jandroid(ThreadCreateCallback p_callback, void *p_user, const Settings &) {
-
-	ThreadAndroid *tr = memnew(ThreadAndroid);
-	tr->callback = p_callback;
-	tr->user = p_user;
-	pthread_attr_init(&tr->pthread_attr);
-	pthread_attr_setdetachstate(&tr->pthread_attr, PTHREAD_CREATE_JOINABLE);
-
-	pthread_create(&tr->pthread, &tr->pthread_attr, thread_callback, tr);
-
-	return tr;
-}
+static JavaVM *java_vm = nullptr;
+static thread_local JNIEnv *env = nullptr;
 
 
-Thread::ID ThreadAndroid::get_thread_id_func_jandroid() {
-
-	void *value = pthread_getspecific(thread_id_key);
-
-	if (value)
-		return *static_cast<ID *>(value);
-
-	ID new_id = atomic_increment(&next_thread_id);
-	pthread_setspecific(thread_id_key, (void *)memnew(ID(new_id)));
-	return new_id;
+static void init_thread() {
+	java_vm->AttachCurrentThread(&env, nullptr);
 }
 }
 
 
-void ThreadAndroid::wait_to_finish_func_jandroid(Thread *p_thread) {
-
-	ThreadAndroid *tp = static_cast<ThreadAndroid *>(p_thread);
-	ERR_FAIL_COND(!tp);
-	ERR_FAIL_COND(tp->pthread == 0);
-
-	pthread_join(tp->pthread, NULL);
-	tp->pthread = 0;
+static void term_thread() {
+	java_vm->DetachCurrentThread();
 }
 }
 
 
-void ThreadAndroid::_thread_destroyed(void *value) {
-
-	/* The thread is being destroyed, detach it from the Java VM and set the mThreadKey value to NULL as required */
-	JNIEnv *env = (JNIEnv *)value;
-	if (env != NULL) {
-		java_vm->DetachCurrentThread();
-		pthread_setspecific(jvm_key, NULL);
-	}
-}
-
-pthread_key_t ThreadAndroid::jvm_key;
-JavaVM *ThreadAndroid::java_vm = NULL;
-
-void ThreadAndroid::setup_thread() {
-
-	if (pthread_getspecific(jvm_key))
-		return; //already setup
-	JNIEnv *env;
-	java_vm->AttachCurrentThread(&env, NULL);
-	pthread_setspecific(jvm_key, (void *)env);
+void init_thread_jandroid(JavaVM *p_jvm, JNIEnv *p_env) {
+	java_vm = p_jvm;
+	env = p_env;
+	Thread::_set_platform_funcs(nullptr, nullptr, &init_thread, &term_thread);
 }
 }
 
 
-void ThreadAndroid::make_default(JavaVM *p_java_vm) {
-
-	java_vm = p_java_vm;
-	create_func = create_func_jandroid;
-	get_thread_id_func = get_thread_id_func_jandroid;
-	wait_to_finish_func = wait_to_finish_func_jandroid;
-	pthread_key_create(&jvm_key, _thread_destroyed);
-	setup_thread();
+void setup_android_thread() {
+	init_thread();
 }
 }
 
 
-JNIEnv *ThreadAndroid::get_env() {
-
-	if (!pthread_getspecific(jvm_key)) {
-		setup_thread();
-	}
-
-	JNIEnv *env = NULL;
-	java_vm->AttachCurrentThread(&env, NULL);
+JNIEnv *get_jni_env() {
 	return env;
 	return env;
 }
 }
-
-ThreadAndroid::ThreadAndroid() {
-
-	pthread = 0;
-}
-
-ThreadAndroid::~ThreadAndroid() {
-}

+ 5 - 38
platform/android/thread_jandroid.h

@@ -28,47 +28,14 @@
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /*************************************************************************/
 /*************************************************************************/
 
 
-#ifndef THREAD_POSIX_H
-#define THREAD_POSIX_H
+#ifndef THREAD_JANDROID_H
+#define THREAD_JANDROID_H
 
 
-#include "core/os/thread.h"
 #include <jni.h>
 #include <jni.h>
-#include <pthread.h>
-#include <sys/types.h>
 
 
-class ThreadAndroid : public Thread {
+void init_thread_jandroid(JavaVM *p_jvm, JNIEnv *p_env);
 
 
-	static pthread_key_t thread_id_key;
-	static ID next_thread_id;
-
-	pthread_t pthread;
-	pthread_attr_t pthread_attr;
-	ThreadCreateCallback callback;
-	void *user;
-	ID id;
-
-	static Thread *create_thread_jandroid();
-
-	static void *thread_callback(void *userdata);
-
-	static Thread *create_func_jandroid(ThreadCreateCallback p_callback, void *, const Settings &);
-	static ID get_thread_id_func_jandroid();
-	static void wait_to_finish_func_jandroid(Thread *p_thread);
-
-	static void _thread_destroyed(void *value);
-	ThreadAndroid();
-
-	static pthread_key_t jvm_key;
-	static JavaVM *java_vm;
-
-public:
-	virtual ID get_id() const;
-
-	static void make_default(JavaVM *p_java_vm);
-	static void setup_thread();
-	static JNIEnv *get_env();
-
-	~ThreadAndroid();
-};
+void setup_android_thread();
+JNIEnv *get_jni_env();
 
 
 #endif
 #endif

+ 3 - 4
platform/iphone/export/export.cpp

@@ -56,7 +56,7 @@ class EditorExportPlatformIOS : public EditorExportPlatform {
 
 
 	// Plugins
 	// Plugins
 	volatile bool plugins_changed;
 	volatile bool plugins_changed;
-	Thread *check_for_changes_thread;
+	Thread check_for_changes_thread;
 	volatile bool quit_request;
 	volatile bool quit_request;
 	Mutex plugins_lock;
 	Mutex plugins_lock;
 	Vector<PluginConfigIOS> plugins;
 	Vector<PluginConfigIOS> plugins;
@@ -1839,13 +1839,12 @@ EditorExportPlatformIOS::EditorExportPlatformIOS() {
 	plugins_changed = true;
 	plugins_changed = true;
 	quit_request = false;
 	quit_request = false;
 
 
-	check_for_changes_thread = Thread::create(_check_for_changes_poll_thread, this);
+	check_for_changes_thread.start(_check_for_changes_poll_thread, this);
 }
 }
 
 
 EditorExportPlatformIOS::~EditorExportPlatformIOS() {
 EditorExportPlatformIOS::~EditorExportPlatformIOS() {
 	quit_request = true;
 	quit_request = true;
-	Thread::wait_to_finish(check_for_changes_thread);
-	memdelete(check_for_changes_thread);
+	check_for_changes_thread.wait_to_finish();
 }
 }
 
 
 void register_iphone_exporter() {
 void register_iphone_exporter() {

+ 2 - 4
platform/javascript/audio_driver_javascript.cpp

@@ -267,7 +267,7 @@ int AudioDriverJavaScript::WorkletNode::create(int p_buffer_size, int p_channels
 
 
 void AudioDriverJavaScript::WorkletNode::start(float *p_out_buf, int p_out_buf_size, float *p_in_buf, int p_in_buf_size) {
 void AudioDriverJavaScript::WorkletNode::start(float *p_out_buf, int p_out_buf_size, float *p_in_buf, int p_in_buf_size) {
 	godot_audio_worklet_start(p_in_buf, p_in_buf_size, p_out_buf, p_out_buf_size, state);
 	godot_audio_worklet_start(p_in_buf, p_in_buf_size, p_out_buf, p_out_buf_size, state);
-	thread = Thread::create(_audio_thread_func, this);
+	thread.start(_audio_thread_func, this);
 }
 }
 
 
 void AudioDriverJavaScript::WorkletNode::lock() {
 void AudioDriverJavaScript::WorkletNode::lock() {
@@ -280,8 +280,6 @@ void AudioDriverJavaScript::WorkletNode::unlock() {
 
 
 void AudioDriverJavaScript::WorkletNode::finish() {
 void AudioDriverJavaScript::WorkletNode::finish() {
 	quit = true; // Ask thread to quit.
 	quit = true; // Ask thread to quit.
-	Thread::wait_to_finish(thread);
-	memdelete(thread);
-	thread = nullptr;
+	thread.wait_to_finish();
 }
 }
 #endif
 #endif

+ 1 - 1
platform/javascript/audio_driver_javascript.h

@@ -59,7 +59,7 @@ public:
 			STATE_MAX,
 			STATE_MAX,
 		};
 		};
 		Mutex mutex;
 		Mutex mutex;
-		Thread *thread = nullptr;
+		Thread thread;
 		bool quit = false;
 		bool quit = false;
 		int32_t state[STATE_MAX] = { 0 };
 		int32_t state[STATE_MAX] = { 0 };
 
 

+ 3 - 4
platform/javascript/export/export.cpp

@@ -213,7 +213,7 @@ class EditorExportPlatformJavaScript : public EditorExportPlatform {
 	Ref<EditorHTTPServer> server;
 	Ref<EditorHTTPServer> server;
 	bool server_quit = false;
 	bool server_quit = false;
 	Mutex server_lock;
 	Mutex server_lock;
-	Thread *server_thread = NULL;
+	Thread server_thread;
 
 
 	enum ExportMode {
 	enum ExportMode {
 		EXPORT_MODE_NORMAL = 0,
 		EXPORT_MODE_NORMAL = 0,
@@ -696,7 +696,7 @@ void EditorExportPlatformJavaScript::_server_thread_poll(void *data) {
 EditorExportPlatformJavaScript::EditorExportPlatformJavaScript() {
 EditorExportPlatformJavaScript::EditorExportPlatformJavaScript() {
 
 
 	server.instance();
 	server.instance();
-	server_thread = Thread::create(_server_thread_poll, this);
+	server_thread.start(_server_thread_poll, this);
 
 
 	Ref<Image> img = memnew(Image(_javascript_logo));
 	Ref<Image> img = memnew(Image(_javascript_logo));
 	logo.instance();
 	logo.instance();
@@ -716,8 +716,7 @@ EditorExportPlatformJavaScript::EditorExportPlatformJavaScript() {
 EditorExportPlatformJavaScript::~EditorExportPlatformJavaScript() {
 EditorExportPlatformJavaScript::~EditorExportPlatformJavaScript() {
 	server->stop();
 	server->stop();
 	server_quit = true;
 	server_quit = true;
-	Thread::wait_to_finish(server_thread);
-	memdelete(server_thread);
+	server_thread.wait_to_finish();
 }
 }
 
 
 void register_javascript_exporter() {
 void register_javascript_exporter() {

+ 2 - 2
platform/uwp/app.h

@@ -78,9 +78,9 @@ namespace GodotUWP
 		void OnMouseMoved(Windows::Devices::Input::MouseDevice^ mouse_device, Windows::Devices::Input::MouseEventArgs^ args);
 		void OnMouseMoved(Windows::Devices::Input::MouseDevice^ mouse_device, Windows::Devices::Input::MouseEventArgs^ args);
 		void OnPointerWheelChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args);
 		void OnPointerWheelChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args);
 
 
-		Windows::System::Threading::Core::SignalNotifier^ mouseChangedNotifier;
+		Windows::System::Thread ing::Core::SignalNotifier^ mouseChangedNotifier;
 		Windows::Foundation::EventRegistrationToken mouseMovedToken;
 		Windows::Foundation::EventRegistrationToken mouseMovedToken;
-		void OnMouseModeChanged(Windows::System::Threading::Core::SignalNotifier^ signalNotifier, bool timedOut);
+		void OnMouseModeChanged(Windows::System::Thread ing::Core::SignalNotifier^ signalNotifier, bool timedOut);
 
 
 		void key_event(Windows::UI::Core::CoreWindow^ sender, bool p_pressed, Windows::UI::Core::KeyEventArgs^ key_args = nullptr, Windows::UI::Core::CharacterReceivedEventArgs^ char_args = nullptr);
 		void key_event(Windows::UI::Core::CoreWindow^ sender, bool p_pressed, Windows::UI::Core::KeyEventArgs^ key_args = nullptr, Windows::UI::Core::CharacterReceivedEventArgs^ char_args = nullptr);
 		void OnKeyDown(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::KeyEventArgs^ args);
 		void OnKeyDown(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::KeyEventArgs^ args);

+ 0 - 3
platform/uwp/os_uwp.cpp

@@ -45,7 +45,6 @@
 #include "servers/audio_server.h"
 #include "servers/audio_server.h"
 #include "servers/visual/visual_server_raster.h"
 #include "servers/visual/visual_server_raster.h"
 #include "servers/visual/visual_server_wrap_mt.h"
 #include "servers/visual/visual_server_wrap_mt.h"
-#include "thread_uwp.h"
 
 
 #include <ppltasks.h>
 #include <ppltasks.h>
 #include <wrl.h>
 #include <wrl.h>
@@ -137,8 +136,6 @@ void OS_UWP::initialize_core() {
 
 
 	//RedirectIOToConsole();
 	//RedirectIOToConsole();
 
 
-	ThreadUWP::make_default();
-
 	FileAccess::make_default<FileAccessWindows>(FileAccess::ACCESS_RESOURCES);
 	FileAccess::make_default<FileAccessWindows>(FileAccess::ACCESS_RESOURCES);
 	FileAccess::make_default<FileAccessWindows>(FileAccess::ACCESS_USERDATA);
 	FileAccess::make_default<FileAccessWindows>(FileAccess::ACCESS_USERDATA);
 	FileAccess::make_default<FileAccessWindows>(FileAccess::ACCESS_FILESYSTEM);
 	FileAccess::make_default<FileAccessWindows>(FileAccess::ACCESS_FILESYSTEM);

+ 0 - 73
platform/uwp/thread_uwp.cpp

@@ -1,73 +0,0 @@
-/*************************************************************************/
-/*  thread_uwp.cpp                                                       */
-/*************************************************************************/
-/*                       This file is part of:                           */
-/*                           GODOT ENGINE                                */
-/*                      https://godotengine.org                          */
-/*************************************************************************/
-/* 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       */
-/* "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.                */
-/*************************************************************************/
-
-#include "thread_uwp.h"
-
-#include "core/os/memory.h"
-
-Thread *ThreadUWP::create_func_uwp(ThreadCreateCallback p_callback, void *p_user, const Settings &) {
-
-	ThreadUWP *thread = memnew(ThreadUWP);
-
-	std::thread new_thread(p_callback, p_user);
-	std::swap(thread->thread, new_thread);
-
-	return thread;
-};
-
-Thread::ID ThreadUWP::get_thread_id_func_uwp() {
-
-	return std::hash<std::thread::id>()(std::this_thread::get_id());
-};
-
-void ThreadUWP::wait_to_finish_func_uwp(Thread *p_thread) {
-
-	ThreadUWP *tp = static_cast<ThreadUWP *>(p_thread);
-	tp->thread.join();
-};
-
-Thread::ID ThreadUWP::get_id() const {
-
-	return std::hash<std::thread::id>()(thread.get_id());
-};
-
-void ThreadUWP::make_default() {
-	create_func = create_func_uwp;
-	get_thread_id_func = get_thread_id_func_uwp;
-	wait_to_finish_func = wait_to_finish_func_uwp;
-};
-
-ThreadUWP::ThreadUWP(){
-
-};
-
-ThreadUWP::~ThreadUWP(){
-
-};

+ 0 - 60
platform/uwp/thread_uwp.h

@@ -1,60 +0,0 @@
-/*************************************************************************/
-/*  thread_uwp.h                                                         */
-/*************************************************************************/
-/*                       This file is part of:                           */
-/*                           GODOT ENGINE                                */
-/*                      https://godotengine.org                          */
-/*************************************************************************/
-/* 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       */
-/* "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.                */
-/*************************************************************************/
-
-#ifndef THREAD_UWP_H
-#define THREAD_UWP_H
-
-#ifdef UWP_ENABLED
-
-#include "core/os/thread.h"
-
-#include <thread>
-
-class ThreadUWP : public Thread {
-
-	std::thread thread;
-
-	static Thread *create_func_uwp(ThreadCreateCallback p_callback, void *, const Settings &);
-	static ID get_thread_id_func_uwp();
-	static void wait_to_finish_func_uwp(Thread *p_thread);
-
-	ThreadUWP();
-
-public:
-	virtual ID get_id() const;
-
-	static void make_default();
-
-	~ThreadUWP();
-};
-
-#endif
-
-#endif

+ 0 - 3
platform/windows/os_windows.cpp

@@ -40,7 +40,6 @@
 #include "drivers/gles3/rasterizer_gles3.h"
 #include "drivers/gles3/rasterizer_gles3.h"
 #include "drivers/windows/dir_access_windows.h"
 #include "drivers/windows/dir_access_windows.h"
 #include "drivers/windows/file_access_windows.h"
 #include "drivers/windows/file_access_windows.h"
-#include "drivers/windows/thread_windows.h"
 #include "joypad_windows.h"
 #include "joypad_windows.h"
 #include "lang_table.h"
 #include "lang_table.h"
 #include "main/main.h"
 #include "main/main.h"
@@ -224,8 +223,6 @@ void OS_Windows::initialize_core() {
 	minimized = false;
 	minimized = false;
 	borderless = false;
 	borderless = false;
 
 
-	ThreadWindows::make_default();
-
 	FileAccess::make_default<FileAccessWindows>(FileAccess::ACCESS_RESOURCES);
 	FileAccess::make_default<FileAccessWindows>(FileAccess::ACCESS_RESOURCES);
 	FileAccess::make_default<FileAccessWindows>(FileAccess::ACCESS_USERDATA);
 	FileAccess::make_default<FileAccessWindows>(FileAccess::ACCESS_USERDATA);
 	FileAccess::make_default<FileAccessWindows>(FileAccess::ACCESS_FILESYSTEM);
 	FileAccess::make_default<FileAccessWindows>(FileAccess::ACCESS_FILESYSTEM);

+ 2 - 3
platform/x11/joypad_linux.cpp

@@ -94,13 +94,12 @@ JoypadLinux::JoypadLinux(InputDefault *in) {
 #endif
 #endif
 	exit_monitor = false;
 	exit_monitor = false;
 	input = in;
 	input = in;
-	joy_thread = Thread::create(joy_thread_func, this);
+	joy_thread.start(joy_thread_func, this);
 }
 }
 
 
 JoypadLinux::~JoypadLinux() {
 JoypadLinux::~JoypadLinux() {
 	exit_monitor = true;
 	exit_monitor = true;
-	Thread::wait_to_finish(joy_thread);
-	memdelete(joy_thread);
+	joy_thread.wait_to_finish();
 	close_joypad();
 	close_joypad();
 }
 }
 
 

+ 1 - 1
platform/x11/joypad_linux.h

@@ -76,7 +76,7 @@ private:
 #endif
 #endif
 	bool exit_monitor;
 	bool exit_monitor;
 	Mutex joy_mutex;
 	Mutex joy_mutex;
-	Thread *joy_thread;
+	Thread joy_thread;
 	InputDefault *input;
 	InputDefault *input;
 	Joypad joypads[JOYPADS_MAX];
 	Joypad joypads[JOYPADS_MAX];
 	Vector<String> attached_devices;
 	Vector<String> attached_devices;

+ 2 - 4
platform/x11/os_x11.cpp

@@ -624,7 +624,7 @@ Error OS_X11::initialize(const VideoMode &p_desired, int p_video_driver, int p_a
 		}
 		}
 	}
 	}
 
 
-	events_thread = Thread::create(_poll_events_thread, this);
+	events_thread.start(_poll_events_thread, this);
 
 
 	update_real_mouse_position();
 	update_real_mouse_position();
 
 
@@ -815,9 +815,7 @@ String OS_X11::get_unique_id() const {
 
 
 void OS_X11::finalize() {
 void OS_X11::finalize() {
 	events_thread_done = true;
 	events_thread_done = true;
-	Thread::wait_to_finish(events_thread);
-	memdelete(events_thread);
-	events_thread = NULL;
+	events_thread.wait_to_finish();
 
 
 	if (main_loop)
 	if (main_loop)
 		memdelete(main_loop);
 		memdelete(main_loop);

+ 1 - 1
platform/x11/os_x11.h

@@ -166,7 +166,7 @@ class OS_X11 : public OS_Unix {
 	void _clipboard_transfer_ownership(Atom p_source, Window x11_window) const;
 	void _clipboard_transfer_ownership(Atom p_source, Window x11_window) const;
 
 
 	mutable Mutex events_mutex;
 	mutable Mutex events_mutex;
-	Thread *events_thread = nullptr;
+	Thread events_thread;
 	bool events_thread_done = false;
 	bool events_thread_done = false;
 	LocalVector<XEvent> polled_events;
 	LocalVector<XEvent> polled_events;
 	static void _poll_events_thread(void *ud);
 	static void _poll_events_thread(void *ud);

+ 2 - 6
scene/main/http_request.cpp

@@ -113,7 +113,7 @@ Error HTTPRequest::request(const String &p_url, const Vector<String> &p_custom_h
 		thread_done = false;
 		thread_done = false;
 		thread_request_quit = false;
 		thread_request_quit = false;
 		client->set_blocking_mode(true);
 		client->set_blocking_mode(true);
-		thread = Thread::create(_thread_func, this);
+		thread.start(_thread_func, this);
 	} else {
 	} else {
 		client->set_blocking_mode(false);
 		client->set_blocking_mode(false);
 		err = _request();
 		err = _request();
@@ -160,9 +160,7 @@ void HTTPRequest::cancel_request() {
 		set_process_internal(false);
 		set_process_internal(false);
 	} else {
 	} else {
 		thread_request_quit = true;
 		thread_request_quit = true;
-		Thread::wait_to_finish(thread);
-		memdelete(thread);
-		thread = NULL;
+		thread.wait_to_finish();
 	}
 	}
 
 
 	if (file) {
 	if (file) {
@@ -568,8 +566,6 @@ void HTTPRequest::_bind_methods() {
 
 
 HTTPRequest::HTTPRequest() {
 HTTPRequest::HTTPRequest() {
 
 
-	thread = NULL;
-
 	port = 80;
 	port = 80;
 	redirections = 0;
 	redirections = 0;
 	max_redirects = 8;
 	max_redirects = 8;

+ 1 - 1
scene/main/http_request.h

@@ -106,7 +106,7 @@ private:
 	volatile bool thread_done;
 	volatile bool thread_done;
 	volatile bool thread_request_quit;
 	volatile bool thread_request_quit;
 
 
-	Thread *thread;
+	Thread thread;
 
 
 	void _request_done(int p_status, int p_code, const PoolStringArray &headers, const PoolByteArray &p_data);
 	void _request_done(int p_status, int p_code, const PoolStringArray &headers, const PoolByteArray &p_data);
 	static void _thread_func(void *p_userdata);
 	static void _thread_func(void *p_userdata);

+ 6 - 11
scene/resources/sky.cpp

@@ -410,8 +410,8 @@ void ProceduralSky::_update_sky() {
 #endif
 #endif
 	if (use_thread) {
 	if (use_thread) {
 
 
-		if (!sky_thread) {
-			sky_thread = Thread::create(_thread_function, this);
+		if (!sky_thread.is_started()) {
+			sky_thread.start(_thread_function, this);
 			regen_queued = false;
 			regen_queued = false;
 		} else {
 		} else {
 			regen_queued = true;
 			regen_queued = true;
@@ -440,11 +440,9 @@ void ProceduralSky::_thread_done(const Ref<Image> &p_image) {
 	VS::get_singleton()->texture_allocate(texture, panorama->get_width(), panorama->get_height(), 0, Image::FORMAT_RGBE9995, VS::TEXTURE_TYPE_2D, VS::TEXTURE_FLAG_FILTER | VS::TEXTURE_FLAG_REPEAT);
 	VS::get_singleton()->texture_allocate(texture, panorama->get_width(), panorama->get_height(), 0, Image::FORMAT_RGBE9995, VS::TEXTURE_TYPE_2D, VS::TEXTURE_FLAG_FILTER | VS::TEXTURE_FLAG_REPEAT);
 	VS::get_singleton()->texture_set_data(texture, panorama);
 	VS::get_singleton()->texture_set_data(texture, panorama);
 	_radiance_changed();
 	_radiance_changed();
-	Thread::wait_to_finish(sky_thread);
-	memdelete(sky_thread);
-	sky_thread = NULL;
+	sky_thread.wait_to_finish();
 	if (regen_queued) {
 	if (regen_queued) {
-		sky_thread = Thread::create(_thread_function, this);
+		sky_thread.start(_thread_function, this);
 		regen_queued = false;
 		regen_queued = false;
 	}
 	}
 }
 }
@@ -572,7 +570,6 @@ ProceduralSky::ProceduralSky(bool p_desaturate) {
 	sun_energy = 1;
 	sun_energy = 1;
 
 
 	texture_size = TEXTURE_SIZE_1024;
 	texture_size = TEXTURE_SIZE_1024;
-	sky_thread = NULL;
 	regen_queued = false;
 	regen_queued = false;
 	first_time = true;
 	first_time = true;
 
 
@@ -581,10 +578,8 @@ ProceduralSky::ProceduralSky(bool p_desaturate) {
 
 
 ProceduralSky::~ProceduralSky() {
 ProceduralSky::~ProceduralSky() {
 
 
-	if (sky_thread) {
-		Thread::wait_to_finish(sky_thread);
-		memdelete(sky_thread);
-		sky_thread = NULL;
+	if (sky_thread.is_started()) {
+		sky_thread.wait_to_finish();
 	}
 	}
 	VS::get_singleton()->free(sky);
 	VS::get_singleton()->free(sky);
 	VS::get_singleton()->free(texture);
 	VS::get_singleton()->free(texture);

+ 1 - 1
scene/resources/sky.h

@@ -99,7 +99,7 @@ public:
 	};
 	};
 
 
 private:
 private:
-	Thread *sky_thread;
+	Thread sky_thread;
 	Color sky_top_color;
 	Color sky_top_color;
 	Color sky_horizon_color;
 	Color sky_horizon_color;
 	float sky_curve;
 	float sky_curve;

+ 3 - 14
servers/audio/audio_driver_dummy.cpp

@@ -49,7 +49,7 @@ Error AudioDriverDummy::init() {
 
 
 	samples_in = memnew_arr(int32_t, buffer_frames * channels);
 	samples_in = memnew_arr(int32_t, buffer_frames * channels);
 
 
-	thread = Thread::create(AudioDriverDummy::thread_func, this);
+	thread.start(AudioDriverDummy::thread_func, this);
 
 
 	return OK;
 	return OK;
 };
 };
@@ -94,37 +94,26 @@ AudioDriver::SpeakerMode AudioDriverDummy::get_speaker_mode() const {
 
 
 void AudioDriverDummy::lock() {
 void AudioDriverDummy::lock() {
 
 
-	if (!thread)
-		return;
 	mutex.lock();
 	mutex.lock();
 };
 };
 
 
 void AudioDriverDummy::unlock() {
 void AudioDriverDummy::unlock() {
 
 
-	if (!thread)
-		return;
 	mutex.unlock();
 	mutex.unlock();
 };
 };
 
 
 void AudioDriverDummy::finish() {
 void AudioDriverDummy::finish() {
 
 
-	if (!thread)
-		return;
-
 	exit_thread = true;
 	exit_thread = true;
-	Thread::wait_to_finish(thread);
+	thread.wait_to_finish();
 
 
 	if (samples_in) {
 	if (samples_in) {
 		memdelete_arr(samples_in);
 		memdelete_arr(samples_in);
 	};
 	};
-
-	memdelete(thread);
-	thread = NULL;
 };
 };
 
 
-AudioDriverDummy::AudioDriverDummy() {
+AudioDriverDummy::AudioDriverDummy(){
 
 
-	thread = NULL;
 };
 };
 
 
 AudioDriverDummy::~AudioDriverDummy(){
 AudioDriverDummy::~AudioDriverDummy(){

+ 1 - 1
servers/audio/audio_driver_dummy.h

@@ -38,7 +38,7 @@
 
 
 class AudioDriverDummy : public AudioDriver {
 class AudioDriverDummy : public AudioDriver {
 
 
-	Thread *thread;
+	Thread thread;
 	Mutex mutex;
 	Mutex mutex;
 
 
 	int32_t *samples_in;
 	int32_t *samples_in;

+ 2 - 2
servers/audio/effects/audio_effect_record.cpp

@@ -119,7 +119,7 @@ void AudioEffectRecordInstance::init() {
 #ifdef NO_THREADS
 #ifdef NO_THREADS
 	AudioServer::get_singleton()->add_update_callback(&AudioEffectRecordInstance::_update, this);
 	AudioServer::get_singleton()->add_update_callback(&AudioEffectRecordInstance::_update, this);
 #else
 #else
-	io_thread = Thread::create(_thread_callback, this);
+	io_thread.start(_thread_callback, this);
 #endif
 #endif
 }
 }
 
 
@@ -129,7 +129,7 @@ void AudioEffectRecordInstance::finish() {
 	AudioServer::get_singleton()->remove_update_callback(&AudioEffectRecordInstance::_update, this);
 	AudioServer::get_singleton()->remove_update_callback(&AudioEffectRecordInstance::_update, this);
 #else
 #else
 	if (thread_active) {
 	if (thread_active) {
-		Thread::wait_to_finish(io_thread);
+		io_thread.wait_to_finish();
 	}
 	}
 #endif
 #endif
 }
 }

+ 1 - 1
servers/audio/effects/audio_effect_record.h

@@ -48,7 +48,7 @@ class AudioEffectRecordInstance : public AudioEffectInstance {
 	Ref<AudioEffectRecord> base;
 	Ref<AudioEffectRecord> base;
 
 
 	bool is_recording;
 	bool is_recording;
-	Thread *io_thread;
+	Thread io_thread;
 	bool thread_active;
 	bool thread_active;
 
 
 	Vector<AudioFrame> ring_buffer;
 	Vector<AudioFrame> ring_buffer;

+ 3 - 9
servers/physics_2d/physics_2d_server_wrap_mt.cpp

@@ -109,9 +109,7 @@ void Physics2DServerWrapMT::init() {
 	if (create_thread) {
 	if (create_thread) {
 
 
 		//OS::get_singleton()->release_rendering_thread();
 		//OS::get_singleton()->release_rendering_thread();
-		if (create_thread) {
-			thread = Thread::create(_thread_callback, this);
-		}
+		thread.start(_thread_callback, this);
 		while (!step_thread_up) {
 		while (!step_thread_up) {
 			OS::get_singleton()->delay_usec(1000);
 			OS::get_singleton()->delay_usec(1000);
 		}
 		}
@@ -123,13 +121,10 @@ void Physics2DServerWrapMT::init() {
 
 
 void Physics2DServerWrapMT::finish() {
 void Physics2DServerWrapMT::finish() {
 
 
-	if (thread) {
+	if (create_thread) {
 
 
 		command_queue.push(this, &Physics2DServerWrapMT::thread_exit);
 		command_queue.push(this, &Physics2DServerWrapMT::thread_exit);
-		Thread::wait_to_finish(thread);
-		memdelete(thread);
-
-		thread = NULL;
+		thread.wait_to_finish();
 	} else {
 	} else {
 		physics_2d_server->finish();
 		physics_2d_server->finish();
 	}
 	}
@@ -153,7 +148,6 @@ Physics2DServerWrapMT::Physics2DServerWrapMT(Physics2DServer *p_contained, bool
 
 
 	physics_2d_server = p_contained;
 	physics_2d_server = p_contained;
 	create_thread = p_create_thread;
 	create_thread = p_create_thread;
-	thread = NULL;
 	step_pending = 0;
 	step_pending = 0;
 	step_thread_up = false;
 	step_thread_up = false;
 
 

+ 1 - 1
servers/physics_2d/physics_2d_server_wrap_mt.h

@@ -54,7 +54,7 @@ class Physics2DServerWrapMT : public Physics2DServer {
 	Thread::ID server_thread;
 	Thread::ID server_thread;
 	Thread::ID main_thread;
 	Thread::ID main_thread;
 	volatile bool exit;
 	volatile bool exit;
-	Thread *thread;
+	Thread thread;
 	volatile bool step_thread_up;
 	volatile bool step_thread_up;
 	bool create_thread;
 	bool create_thread;
 
 

+ 2 - 7
servers/visual/visual_server_scene.cpp

@@ -3682,10 +3682,8 @@ VisualServerScene *VisualServerScene::singleton = NULL;
 
 
 VisualServerScene::VisualServerScene() {
 VisualServerScene::VisualServerScene() {
 
 
-#ifndef NO_THREADS
-	probe_bake_thread = Thread::create(_gi_probe_bake_threads, this);
+	probe_bake_thread.start(_gi_probe_bake_threads, this);
 	probe_bake_thread_exit = false;
 	probe_bake_thread_exit = false;
-#endif
 
 
 	render_pass = 1;
 	render_pass = 1;
 	singleton = this;
 	singleton = this;
@@ -3694,10 +3692,7 @@ VisualServerScene::VisualServerScene() {
 
 
 VisualServerScene::~VisualServerScene() {
 VisualServerScene::~VisualServerScene() {
 
 
-#ifndef NO_THREADS
 	probe_bake_thread_exit = true;
 	probe_bake_thread_exit = true;
 	probe_bake_sem.post();
 	probe_bake_sem.post();
-	Thread::wait_to_finish(probe_bake_thread);
-	memdelete(probe_bake_thread);
-#endif
+	probe_bake_thread.wait_to_finish();
 }
 }

+ 1 - 1
servers/visual/visual_server_scene.h

@@ -592,7 +592,7 @@ public:
 	static void _gi_probe_bake_threads(void *);
 	static void _gi_probe_bake_threads(void *);
 
 
 	volatile bool probe_bake_thread_exit;
 	volatile bool probe_bake_thread_exit;
-	Thread *probe_bake_thread;
+	Thread probe_bake_thread;
 	Semaphore probe_bake_sem;
 	Semaphore probe_bake_sem;
 	Mutex probe_bake_mutex;
 	Mutex probe_bake_mutex;
 	List<Instance *> probe_bake_list;
 	List<Instance *> probe_bake_list;

+ 3 - 7
servers/visual/visual_server_wrap_mt.cpp

@@ -110,7 +110,7 @@ void VisualServerWrapMT::init() {
 		print_verbose("VisualServerWrapMT: Creating render thread");
 		print_verbose("VisualServerWrapMT: Creating render thread");
 		OS::get_singleton()->release_rendering_thread();
 		OS::get_singleton()->release_rendering_thread();
 		if (create_thread) {
 		if (create_thread) {
-			thread = Thread::create(_thread_callback, this);
+			thread.start(_thread_callback, this);
 			print_verbose("VisualServerWrapMT: Starting render thread");
 			print_verbose("VisualServerWrapMT: Starting render thread");
 		}
 		}
 		while (!draw_thread_up) {
 		while (!draw_thread_up) {
@@ -125,13 +125,10 @@ void VisualServerWrapMT::init() {
 
 
 void VisualServerWrapMT::finish() {
 void VisualServerWrapMT::finish() {
 
 
-	if (thread) {
+	if (create_thread) {
 
 
 		command_queue.push(this, &VisualServerWrapMT::thread_exit);
 		command_queue.push(this, &VisualServerWrapMT::thread_exit);
-		Thread::wait_to_finish(thread);
-		memdelete(thread);
-
-		thread = NULL;
+		thread.wait_to_finish();
 	} else {
 	} else {
 		visual_server->finish();
 		visual_server->finish();
 	}
 	}
@@ -177,7 +174,6 @@ VisualServerWrapMT::VisualServerWrapMT(VisualServer *p_contained, bool p_create_
 
 
 	visual_server = p_contained;
 	visual_server = p_contained;
 	create_thread = p_create_thread;
 	create_thread = p_create_thread;
-	thread = NULL;
 	draw_pending = 0;
 	draw_pending = 0;
 	draw_thread_up = false;
 	draw_thread_up = false;
 	pool_max_size = GLOBAL_GET("memory/limits/multithreaded_server/rid_pool_prealloc");
 	pool_max_size = GLOBAL_GET("memory/limits/multithreaded_server/rid_pool_prealloc");

+ 1 - 1
servers/visual/visual_server_wrap_mt.h

@@ -47,7 +47,7 @@ class VisualServerWrapMT : public VisualServer {
 
 
 	Thread::ID server_thread;
 	Thread::ID server_thread;
 	volatile bool exit;
 	volatile bool exit;
-	Thread *thread;
+	Thread thread;
 	volatile bool draw_thread_up;
 	volatile bool draw_thread_up;
 	bool create_thread;
 	bool create_thread;