diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp index 94d42a28527..6dbede6d7e5 100644 --- a/core/bind/core_bind.cpp +++ b/core/bind/core_bind.cpp @@ -2787,24 +2787,14 @@ Error _Thread::start(Object *p_instance, const StringName &p_method, const Varia Thread::Settings s; 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; } String _Thread::get_id() const { - if (!thread) - return String(); - - return itos(thread->get_id()); + return itos(thread.get_id()); } bool _Thread::is_active() const { @@ -2813,17 +2803,13 @@ bool _Thread::is_active() const { } 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."); - Thread::wait_to_finish(thread); + thread.wait_to_finish(); Variant r = ret; active = false; target_method = StringName(); target_instance = NULL; userdata = Variant(); - if (thread) - memdelete(thread); - thread = NULL; return r; } @@ -2842,7 +2828,6 @@ void _Thread::_bind_methods() { _Thread::_Thread() { active = false; - thread = NULL; target_instance = NULL; } diff --git a/core/bind/core_bind.h b/core/bind/core_bind.h index 5bb2da076ae..08f6c0b5c8c 100644 --- a/core/bind/core_bind.h +++ b/core/bind/core_bind.h @@ -684,7 +684,7 @@ protected: volatile bool active; Object *target_instance; StringName target_method; - Thread *thread; + Thread thread; static void _bind_methods(); static void _start_func(void *ud); diff --git a/core/io/file_access_network.cpp b/core/io/file_access_network.cpp index d11ba68c72e..b3d37561c6a 100644 --- a/core/io/file_access_network.cpp +++ b/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; } - thread = Thread::create(_thread_func, this); + thread.start(_thread_func, this); return OK; } @@ -222,7 +222,6 @@ FileAccessNetworkClient *FileAccessNetworkClient::singleton = NULL; FileAccessNetworkClient::FileAccessNetworkClient() { - thread = NULL; quit = false; singleton = this; last_id = 0; @@ -232,11 +231,10 @@ FileAccessNetworkClient::FileAccessNetworkClient() { FileAccessNetworkClient::~FileAccessNetworkClient() { - if (thread) { + if (thread.is_started()) { quit = true; sem.post(); - Thread::wait_to_finish(thread); - memdelete(thread); + thread.wait_to_finish(); } } diff --git a/core/io/file_access_network.h b/core/io/file_access_network.h index 05ae24c5642..c8edeaa1198 100644 --- a/core/io/file_access_network.h +++ b/core/io/file_access_network.h @@ -50,7 +50,7 @@ class FileAccessNetworkClient { List block_requests; Semaphore sem; - Thread *thread; + Thread thread; bool quit; Mutex mutex; Mutex blockrequest_mutex; diff --git a/core/io/ip.cpp b/core/io/ip.cpp index a059067a4cb..152776dec40 100644 --- a/core/io/ip.cpp +++ b/core/io/ip.cpp @@ -73,7 +73,7 @@ struct _IP_ResolverPrivate { Mutex mutex; Semaphore sem; - Thread *thread; + Thread thread; //Semaphore* semaphore; bool thread_abort; @@ -151,7 +151,7 @@ IP::ResolverID IP::resolve_hostname_queue_item(const String &p_hostname, IP::Typ } else { resolver->queue[id].response = IP_Address(); resolver->queue[id].status = IP::RESOLVER_STATUS_WAITING; - if (resolver->thread) + if (resolver->thread.is_started()) resolver->sem.post(); else resolver->resolve_queues(); @@ -315,25 +315,15 @@ IP::IP() { singleton = this; resolver = memnew(_IP_ResolverPrivate); -#ifndef NO_THREADS 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() { -#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); } diff --git a/core/os/thread.cpp b/core/os/thread.cpp index 187c409e30b..7ace779da16 100644 --- a/core/os/thread.cpp +++ b/core/os/thread.cpp @@ -30,45 +30,91 @@ #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; + +void Thread::_set_platform_funcs( + Error (*p_set_name_func)(const String &), + void (*p_set_priority_func)(Thread::Priority), + void (*p_init_func)(), + void (*p_term_func)()) { + Thread::set_name_func = p_set_name_func; + Thread::set_priority_func = p_set_priority_func; + Thread::init_func = p_init_func; + Thread::term_func = p_term_func; } -Thread *Thread::create(ThreadCreateCallback p_callback, void *p_user, const Settings &p_settings) { - - if (create_func) { - - return create_func(p_callback, p_user, p_settings); +void Thread::callback(Thread *p_self, const Settings &p_settings, Callback p_callback, void *p_userdata) { + Thread::caller_id = p_self->id; + if (set_priority_func) { + set_priority_func(p_settings.priority); + } + if (init_func) { + init_func(); + } + ScriptServer::thread_enter(); //scripts may need to attach a stack + p_callback(p_userdata); + ScriptServer::thread_exit(); + if (term_func) { + term_func(); } - return NULL; } -void Thread::wait_to_finish(Thread *p_thread) { +void Thread::start(Thread::Callback p_callback, void *p_user, const Settings &p_settings) { + if (id != 0) { +#ifdef DEBUG_ENABLED + WARN_PRINT("A Thread object has been re-started without wait_to_finish() having been called on it. Please do so to ensure correct cleanup of the thread."); +#endif + thread.detach(); + std::thread empty_thread; + thread.swap(empty_thread); + } + id = atomic_increment(&last_thread_id); + std::thread new_thread(&Thread::callback, this, p_settings, p_callback, p_user); + thread.swap(new_thread); +} - if (wait_to_finish_func) - wait_to_finish_func(p_thread); +bool Thread::is_started() const { + return id != 0; +} + +void Thread::wait_to_finish() { + if (id != 0) { + thread.join(); + std::thread empty_thread; + thread.swap(empty_thread); + id = 0; + } } Error Thread::set_name(const String &p_name) { - - if (set_name_func) + if (set_name_func) { return set_name_func(p_name); + } return ERR_UNAVAILABLE; -}; - -Thread::Thread() { } +Thread::Thread() : + id(0) {} + 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 diff --git a/core/os/thread.h b/core/os/thread.h index a0e9b109a46..38861a568bc 100644 --- a/core/os/thread.h +++ b/core/os/thread.h @@ -32,49 +32,85 @@ #define THREAD_H #include "core/typedefs.h" -#include "core/ustring.h" -typedef void (*ThreadCreateCallback)(void *p_userdata); +#if !defined(NO_THREADS) +#include +#endif + +class String; class Thread { public: - enum Priority { + typedef void (*Callback)(void *p_userdata); + typedef uint64_t ID; + + enum Priority { PRIORITY_LOW, PRIORITY_NORMAL, PRIORITY_HIGH }; struct Settings { - Priority priority; Settings() { priority = PRIORITY_NORMAL; } }; - typedef uint64_t ID; - -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 &); - +private: +#if !defined(NO_THREADS) friend class Main; - static ID _main_thread_id; + static ID main_thread_id; + static ID last_thread_id; - Thread(); + ID id; + static thread_local ID caller_id; + std::thread thread; + + static void callback(Thread *p_self, const Settings &p_settings, Thread::Callback p_callback, void *p_userdata); + + static Error (*set_name_func)(const String &); + static void (*set_priority_func)(Thread::Priority); + static void (*init_func)(); + static void (*term_func)(); +#endif 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); - _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 diff --git a/core/os/thread_dummy.cpp b/core/os/thread_dummy.cpp deleted file mode 100644 index 3b2f6438c49..00000000000 --- a/core/os/thread_dummy.cpp +++ /dev/null @@ -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; -}; diff --git a/core/os/thread_dummy.h b/core/os/thread_dummy.h deleted file mode 100644 index f86aaaecd12..00000000000 --- a/core/os/thread_dummy.h +++ /dev/null @@ -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 diff --git a/core/os/threaded_array_processor.h b/core/os/threaded_array_processor.h index 850cddb7dfb..797dcc9b998 100644 --- a/core/os/threaded_array_processor.h +++ b/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.process(data.index); //process first, let threads increment for next - Vector 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 >, &data); + for (int i = 0; i < thread_count; i++) { + threads[i].start(process_array_thread >, &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 diff --git a/drivers/alsa/audio_driver_alsa.cpp b/drivers/alsa/audio_driver_alsa.cpp index 45286d4b669..ea561bc6a73 100644 --- a/drivers/alsa/audio_driver_alsa.cpp +++ b/drivers/alsa/audio_driver_alsa.cpp @@ -169,7 +169,7 @@ Error AudioDriverALSA::init() { Error err = init_device(); if (err == OK) { - thread = Thread::create(AudioDriverALSA::thread_func, this); + thread.start(AudioDriverALSA::thread_func, this); } return err; @@ -313,15 +313,11 @@ void AudioDriverALSA::set_device(String device) { void AudioDriverALSA::lock() { - if (!thread) - return; mutex.lock(); } void AudioDriverALSA::unlock() { - if (!thread) - return; mutex.unlock(); } @@ -335,19 +331,13 @@ void AudioDriverALSA::finish_device() { 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(); } AudioDriverALSA::AudioDriverALSA() : - thread(NULL), pcm_handle(NULL), device_name("Default"), new_device("Default") { diff --git a/drivers/alsa/audio_driver_alsa.h b/drivers/alsa/audio_driver_alsa.h index 7c3752fe6bb..23012fe331d 100644 --- a/drivers/alsa/audio_driver_alsa.h +++ b/drivers/alsa/audio_driver_alsa.h @@ -41,7 +41,7 @@ class AudioDriverALSA : public AudioDriver { - Thread *thread; + Thread thread; Mutex mutex; snd_pcm_t *pcm_handle; diff --git a/drivers/alsamidi/midi_driver_alsamidi.cpp b/drivers/alsamidi/midi_driver_alsamidi.cpp index 21d38695e6c..43c333ecdc3 100644 --- a/drivers/alsamidi/midi_driver_alsamidi.cpp +++ b/drivers/alsamidi/midi_driver_alsamidi.cpp @@ -149,20 +149,15 @@ Error MIDIDriverALSAMidi::open() { snd_device_name_free_hint(hints); exit_thread = false; - thread = Thread::create(MIDIDriverALSAMidi::thread_func, this); + thread.start(MIDIDriverALSAMidi::thread_func, this); return OK; } 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++) { snd_rawmidi_t *midi_in = connected_inputs[i]; @@ -202,8 +197,6 @@ PoolStringArray MIDIDriverALSAMidi::get_connected_inputs() { MIDIDriverALSAMidi::MIDIDriverALSAMidi() { - thread = NULL; - exit_thread = false; } diff --git a/drivers/alsamidi/midi_driver_alsamidi.h b/drivers/alsamidi/midi_driver_alsamidi.h index 138a89ed26e..60f3dc56780 100644 --- a/drivers/alsamidi/midi_driver_alsamidi.h +++ b/drivers/alsamidi/midi_driver_alsamidi.h @@ -43,7 +43,7 @@ class MIDIDriverALSAMidi : public MIDIDriver { - Thread *thread; + Thread thread; Mutex mutex; Vector connected_inputs; diff --git a/drivers/pulseaudio/audio_driver_pulseaudio.cpp b/drivers/pulseaudio/audio_driver_pulseaudio.cpp index 5c57f9ee975..39ca601c5e1 100644 --- a/drivers/pulseaudio/audio_driver_pulseaudio.cpp +++ b/drivers/pulseaudio/audio_driver_pulseaudio.cpp @@ -294,7 +294,7 @@ Error AudioDriverPulseAudio::init() { Error err = init_device(); if (err == OK) { - thread = Thread::create(AudioDriverPulseAudio::thread_func, this); + thread.start(AudioDriverPulseAudio::thread_func, this); } return OK; @@ -599,15 +599,11 @@ void AudioDriverPulseAudio::set_device(String device) { void AudioDriverPulseAudio::lock() { - if (!thread) - return; mutex.lock(); } void AudioDriverPulseAudio::unlock() { - if (!thread) - return; mutex.unlock(); } @@ -622,11 +618,11 @@ void AudioDriverPulseAudio::finish_device() { void AudioDriverPulseAudio::finish() { - if (!thread) + if (!thread.is_started()) return; exit_thread = true; - Thread::wait_to_finish(thread); + thread.wait_to_finish(); finish_device(); @@ -640,10 +636,6 @@ void AudioDriverPulseAudio::finish() { pa_mainloop_free(pa_ml); pa_ml = NULL; } - - memdelete(thread); - - thread = NULL; } Error AudioDriverPulseAudio::capture_init_device() { @@ -797,7 +789,6 @@ String AudioDriverPulseAudio::capture_get_device() { } AudioDriverPulseAudio::AudioDriverPulseAudio() : - thread(NULL), pa_ml(NULL), pa_ctx(NULL), pa_str(NULL), diff --git a/drivers/pulseaudio/audio_driver_pulseaudio.h b/drivers/pulseaudio/audio_driver_pulseaudio.h index 27a2b1ede8e..20c4e6cd6ca 100644 --- a/drivers/pulseaudio/audio_driver_pulseaudio.h +++ b/drivers/pulseaudio/audio_driver_pulseaudio.h @@ -41,7 +41,7 @@ class AudioDriverPulseAudio : public AudioDriver { - Thread *thread; + Thread thread; Mutex mutex; pa_mainloop *pa_ml; diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp index 32a4e0425f6..ac233889028 100644 --- a/drivers/unix/os_unix.cpp +++ b/drivers/unix/os_unix.cpp @@ -32,7 +32,6 @@ #ifdef UNIX_ENABLED -#include "core/os/thread_dummy.h" #include "core/project_settings.h" #include "drivers/unix/dir_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() { -#ifdef NO_THREADS - ThreadDummy::make_default(); -#else - ThreadPosix::make_default(); +#if !defined(NO_THREADS) + init_thread_posix(); #endif + FileAccess::make_default(FileAccess::ACCESS_RESOURCES); FileAccess::make_default(FileAccess::ACCESS_USERDATA); FileAccess::make_default(FileAccess::ACCESS_FILESYSTEM); diff --git a/drivers/unix/thread_posix.cpp b/drivers/unix/thread_posix.cpp index 1854778d2d6..ff340480020 100644 --- a/drivers/unix/thread_posix.cpp +++ b/drivers/unix/thread_posix.cpp @@ -28,92 +28,14 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "thread_posix.h" - #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" +#include "thread_posix.h" -#ifdef PTHREAD_BSD_SET_NAME -#include -#endif - -static void _thread_id_key_destr_callback(void *p_value) { - memdelete(static_cast(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(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(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(p_thread); - ERR_FAIL_COND(!tp); - ERR_FAIL_COND(tp->pthread == 0); - - pthread_join(tp->pthread, NULL); - tp->pthread = 0; -} - -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 return ERR_UNAVAILABLE; @@ -141,22 +63,10 @@ Error ThreadPosix::set_name_func_posix(const String &p_name) { return err == 0 ? OK : ERR_INVALID_PARAMETER; #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 diff --git a/drivers/unix/thread_posix.h b/drivers/unix/thread_posix.h index d97e5629755..8b8a736bf01 100644 --- a/drivers/unix/thread_posix.h +++ b/drivers/unix/thread_posix.h @@ -31,43 +31,8 @@ #ifndef THREAD_POSIX_H #define THREAD_POSIX_H -#if (defined(UNIX_ENABLED) || defined(PTHREAD_ENABLED)) && !defined(NO_THREADS) - -#include "core/os/thread.h" -#include -#include - -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 diff --git a/drivers/wasapi/audio_driver_wasapi.cpp b/drivers/wasapi/audio_driver_wasapi.cpp index a0d1458aec2..6cd474e1a7e 100644 --- a/drivers/wasapi/audio_driver_wasapi.cpp +++ b/drivers/wasapi/audio_driver_wasapi.cpp @@ -406,7 +406,7 @@ Error AudioDriverWASAPI::init() { exit_thread = false; thread_exited = false; - thread = Thread::create(thread_func, this); + thread.start(thread_func, this); return OK; } @@ -791,13 +791,8 @@ void AudioDriverWASAPI::unlock() { 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_render_device(); @@ -855,8 +850,6 @@ String AudioDriverWASAPI::capture_get_device() { AudioDriverWASAPI::AudioDriverWASAPI() { - thread = NULL; - samples_in.clear(); channels = 0; diff --git a/drivers/wasapi/audio_driver_wasapi.h b/drivers/wasapi/audio_driver_wasapi.h index a49257bb52e..9fd731dcf86 100644 --- a/drivers/wasapi/audio_driver_wasapi.h +++ b/drivers/wasapi/audio_driver_wasapi.h @@ -76,7 +76,7 @@ class AudioDriverWASAPI : public AudioDriver { AudioDeviceWASAPI audio_output; Mutex mutex; - Thread *thread; + Thread thread; Vector samples_in; diff --git a/drivers/windows/thread_windows.cpp b/drivers/windows/thread_windows.cpp deleted file mode 100644 index ec5ccbd3b5c..00000000000 --- a/drivers/windows/thread_windows.cpp +++ /dev/null @@ -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(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(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 diff --git a/drivers/windows/thread_windows.h b/drivers/windows/thread_windows.h deleted file mode 100644 index 0018bb4bde2..00000000000 --- a/drivers/windows/thread_windows.h +++ /dev/null @@ -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 - -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 diff --git a/drivers/xaudio2/audio_driver_xaudio2.cpp b/drivers/xaudio2/audio_driver_xaudio2.cpp index 6888f0a4d67..7da2d04f18a 100644 --- a/drivers/xaudio2/audio_driver_xaudio2.cpp +++ b/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); 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; } @@ -157,24 +157,20 @@ float AudioDriverXAudio2::get_latency() { void AudioDriverXAudio2::lock() { - if (!thread) - return; mutex.lock(); } void AudioDriverXAudio2::unlock() { - if (!thread) - return; mutex.unlock(); } void AudioDriverXAudio2::finish() { - if (!thread) + if (!thread.is_started()) return; exit_thread = true; - Thread::wait_to_finish(thread); + thread.wait_to_finish(); if (source_voice) { source_voice->Stop(0); @@ -191,13 +187,9 @@ void AudioDriverXAudio2::finish() { } mastering_voice->DestroyVoice(); - - memdelete(thread); - thread = NULL; } AudioDriverXAudio2::AudioDriverXAudio2() : - thread(NULL), current_buffer(0) { wave_format = { 0 }; for (int i = 0; i < AUDIO_BUFFERS; i++) { diff --git a/drivers/xaudio2/audio_driver_xaudio2.h b/drivers/xaudio2/audio_driver_xaudio2.h index 6319d462b9a..0b5a9dca08a 100644 --- a/drivers/xaudio2/audio_driver_xaudio2.h +++ b/drivers/xaudio2/audio_driver_xaudio2.h @@ -64,7 +64,7 @@ class AudioDriverXAudio2 : public AudioDriver { void STDMETHODCALLTYPE OnVoiceError(void *pBufferContext, HRESULT Error) {} }; - Thread *thread; + Thread thread; Mutex mutex; int32_t *samples_in; diff --git a/editor/audio_stream_preview.cpp b/editor/audio_stream_preview.cpp index ffd2336a640..9ecbd415f69 100644 --- a/editor/audio_stream_preview.cpp +++ b/editor/audio_stream_preview.cpp @@ -199,8 +199,10 @@ Ref AudioStreamPreviewGenerator::generate_preview(const Ref< preview->preview->preview = maxmin; 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; } @@ -220,7 +222,8 @@ void AudioStreamPreviewGenerator::_notification(int p_what) { for (Map::Element *E = previews.front(); E; E = E->next()) { if (!E->get().generating) { 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; } if (!ObjectDB::get_instance(E->key())) { //no longer in use, get rid of preview diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp index 0bc53d6e7ce..764365f45d2 100644 --- a/editor/editor_file_system.cpp +++ b/editor/editor_file_system.cpp @@ -609,7 +609,7 @@ void EditorFileSystem::scan() { if (false /*&& bool(Globals::get_singleton()->get("debug/disable_scan"))*/) return; - if (scanning || scanning_changes || thread) + if (scanning || scanning_changes || thread.is_started()) return; _update_extensions(); @@ -632,13 +632,13 @@ void EditorFileSystem::scan() { first_scan = false; } else { - ERR_FAIL_COND(thread); + ERR_FAIL_COND(thread.is_started()); set_process(true); Thread::Settings s; scanning = true; scan_total = 0; s.priority = Thread::PRIORITY_LOW; - thread = Thread::create(_thread_func, this, s); + thread.start(_thread_func, this, s); //tree->hide(); //progress->show(); } @@ -1067,7 +1067,7 @@ void EditorFileSystem::get_changed_sources(List *r_changed) { void EditorFileSystem::scan_changes() { 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; set_process(true); return; @@ -1097,12 +1097,12 @@ void EditorFileSystem::scan_changes() { emit_signal("sources_changed", sources_changed.size() > 0); } else { - ERR_FAIL_COND(thread_sources); + ERR_FAIL_COND(thread_sources.is_started()); set_process(true); scan_total = 0; Thread::Settings s; 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; 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_scan = true; while (scanning) { 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..."); set_process(false); } @@ -1151,9 +1148,7 @@ void EditorFileSystem::_notification(int p_what) { set_process(false); - Thread::wait_to_finish(thread_sources); - memdelete(thread_sources); - thread_sources = NULL; + thread_sources.wait_to_finish(); if (_update_scan_actions()) emit_signal("filesystem_changed"); emit_signal("sources_changed", sources_changed.size() > 0); @@ -1168,9 +1163,7 @@ void EditorFileSystem::_notification(int p_what) { memdelete(filesystem); filesystem = new_filesystem; new_filesystem = NULL; - Thread::wait_to_finish(thread); - memdelete(thread); - thread = NULL; + thread.wait_to_finish(); _update_scan_actions(); emit_signal("filesystem_changed"); emit_signal("sources_changed", sources_changed.size() > 0); @@ -2135,11 +2128,9 @@ EditorFileSystem::EditorFileSystem() { filesystem = memnew(EditorFileSystemDirectory); //like, empty filesystem->parent = NULL; - thread = NULL; scanning = false; importing = false; use_threads = true; - thread_sources = NULL; new_filesystem = NULL; abort_scan = false; diff --git a/editor/editor_file_system.h b/editor/editor_file_system.h index 5d10d306a9f..1e39f330c01 100644 --- a/editor/editor_file_system.h +++ b/editor/editor_file_system.h @@ -136,7 +136,7 @@ class EditorFileSystem : public Node { }; bool use_threads; - Thread *thread; + Thread thread; static void _thread_func(void *_userdata); EditorFileSystemDirectory *new_filesystem; @@ -200,7 +200,7 @@ class EditorFileSystem : public Node { 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_done; diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 75b4c343061..1d281b17d68 100644 --- a/editor/editor_node.cpp +++ b/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; - 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) { 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); } - 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)); if (p_close_on_errors && eta.exitcode != 0) { diff --git a/editor/editor_node.h b/editor/editor_node.h index f175573451d..7d8768c3658 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -106,7 +106,7 @@ public: String path; List args; String output; - Thread *execute_output_thread; + Thread execute_output_thread; Mutex execute_output_mutex; int exitcode; volatile bool done; diff --git a/editor/editor_resource_preview.cpp b/editor/editor_resource_preview.cpp index acc96a57a40..303b4d16da4 100644 --- a/editor/editor_resource_preview.cpp +++ b/editor/editor_resource_preview.cpp @@ -456,26 +456,23 @@ void EditorResourcePreview::check_for_invalidation(const String &p_path) { } 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() { - if (thread) { + if (thread.is_started()) { exit = true; preview_sem.post(); while (!exited) { OS::get_singleton()->delay_usec(10000); 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() { - thread = NULL; singleton = this; order = 0; exit = false; diff --git a/editor/editor_resource_preview.h b/editor/editor_resource_preview.h index 4fd796e1be9..089158d2276 100644 --- a/editor/editor_resource_preview.h +++ b/editor/editor_resource_preview.h @@ -72,7 +72,7 @@ class EditorResourcePreview : public Node { Mutex preview_mutex; Semaphore preview_sem; - Thread *thread; + Thread thread; volatile bool exit; volatile bool exited; diff --git a/editor/fileserver/editor_file_server.cpp b/editor/fileserver/editor_file_server.cpp index ef1f9e4e627..4e723dd1ddf 100644 --- a/editor/fileserver/editor_file_server.cpp +++ b/editor/fileserver/editor_file_server.cpp @@ -43,7 +43,7 @@ void EditorFileServer::_close_client(ClientData *cd) { cd->connection->disconnect_from_host(); cd->efs->wait_mutex.lock(); - cd->efs->to_wait.insert(cd->thread); + cd->efs->to_wait.insert(&cd->thread); cd->efs->wait_mutex.unlock(); while (cd->files.size()) { memdelete(cd->files.front()->get()); @@ -291,7 +291,7 @@ void EditorFileServer::_thread_start(void *s) { cd->connection = self->server->take_connection(); cd->efs = self; 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(); self->to_wait.erase(w); self->wait_mutex.unlock(); - Thread::wait_to_finish(w); - memdelete(w); + w->wait_to_finish(); self->wait_mutex.lock(); } self->wait_mutex.unlock(); @@ -334,7 +333,7 @@ EditorFileServer::EditorFileServer() { quit = false; active = false; 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/password", ""); @@ -343,6 +342,5 @@ EditorFileServer::EditorFileServer() { EditorFileServer::~EditorFileServer() { quit = true; - Thread::wait_to_finish(thread); - memdelete(thread); + thread.wait_to_finish(); } diff --git a/editor/fileserver/editor_file_server.h b/editor/fileserver/editor_file_server.h index efd86168ac9..1ba7803fab9 100644 --- a/editor/fileserver/editor_file_server.h +++ b/editor/fileserver/editor_file_server.h @@ -49,7 +49,7 @@ class EditorFileServer : public Object { struct ClientData { - Thread *thread; + Thread thread; Ref connection; Map files; EditorFileServer *efs; @@ -63,7 +63,7 @@ class EditorFileServer : public Object { static void _subthread_start(void *s); Mutex wait_mutex; - Thread *thread; + Thread thread; static void _thread_start(void *); bool quit; Command cmd; diff --git a/main/main.cpp b/main/main.cpp index 5d189d53d14..36e2e402b5f 100644 --- a/main/main.cpp +++ b/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"); - Thread::_main_thread_id = Thread::get_caller_id(); - globals = memnew(ProjectSettings); input_map = memnew(InputMap); @@ -1275,9 +1273,11 @@ Error Main::setup2(Thread::ID p_main_tid_override) { // Print engine name and version print_line(String(VERSION_NAME) + " v" + get_full_version_string() + " - " + String(VERSION_WEBSITE)); +#if !defined(NO_THREADS) 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); if (err != OK) { diff --git a/modules/cvtt/image_compress_cvtt.cpp b/modules/cvtt/image_compress_cvtt.cpp index 37620790a30..70424c58b69 100644 --- a/modules/cvtt/image_compress_cvtt.cpp +++ b/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(tasks.size()); 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); 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]); } } diff --git a/modules/gdnative/android/android_gdn.cpp b/modules/gdnative/android/android_gdn.cpp index aec2ea0cbfd..198e5302a1d 100644 --- a/modules/gdnative/android/android_gdn.cpp +++ b/modules/gdnative/android/android_gdn.cpp @@ -48,7 +48,7 @@ extern "C" { JNIEnv *GDAPI godot_android_get_env() { #ifdef __ANDROID__ - return ThreadAndroid::get_env(); + return get_jni_env(); #else return NULL; #endif diff --git a/modules/gdscript/language_server/gdscript_language_server.cpp b/modules/gdscript/language_server/gdscript_language_server.cpp index 81617acda27..a6b4593193c 100644 --- a/modules/gdscript/language_server/gdscript_language_server.cpp +++ b/modules/gdscript/language_server/gdscript_language_server.cpp @@ -36,7 +36,6 @@ #include "editor/editor_node.h" GDScriptLanguageServer::GDScriptLanguageServer() { - thread = NULL; thread_running = false; started = false; @@ -88,9 +87,8 @@ void GDScriptLanguageServer::start() { if (protocol.start(port, IP_Address("127.0.0.1")) == OK) { EditorNode::get_log()->add_message("--- GDScript language server started ---", EditorLog::MSG_TYPE_EDITOR); if (use_thread) { - ERR_FAIL_COND(thread != NULL); thread_running = true; - thread = Thread::create(GDScriptLanguageServer::thread_main, this); + thread.start(GDScriptLanguageServer::thread_main, this); } set_process_internal(!use_thread); started = true; @@ -99,11 +97,9 @@ void GDScriptLanguageServer::start() { void GDScriptLanguageServer::stop() { if (use_thread) { - ERR_FAIL_COND(NULL == thread); + ERR_FAIL_COND(!thread.is_started()); thread_running = false; - Thread::wait_to_finish(thread); - memdelete(thread); - thread = NULL; + thread.wait_to_finish(); } protocol.stop(); started = false; diff --git a/modules/gdscript/language_server/gdscript_language_server.h b/modules/gdscript/language_server/gdscript_language_server.h index 218f42199e5..7b7837a4636 100644 --- a/modules/gdscript/language_server/gdscript_language_server.h +++ b/modules/gdscript/language_server/gdscript_language_server.h @@ -40,7 +40,7 @@ class GDScriptLanguageServer : public EditorPlugin { GDScriptLanguageProtocol protocol; - Thread *thread; + Thread thread; bool thread_running; bool started; bool use_thread; diff --git a/modules/lightmapper_cpu/lightmapper_cpu.cpp b/modules/lightmapper_cpu/lightmapper_cpu.cpp index c08a74646e0..064e31f3611 100644 --- a/modules/lightmapper_cpu/lightmapper_cpu.cpp +++ b/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.thread_func = p_thread_func; 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; @@ -263,8 +264,7 @@ bool LightmapperCPU::_parallel_run(int p_count, const String &p_description, Bak progress = thread_progress; } thread_cancelled = cancelled; - Thread::wait_to_finish(runner_thread); - memdelete(runner_thread); + runner_thread.wait_to_finish(); #endif thread_cancelled = false; diff --git a/modules/mono/mono_gd/support/android_support.cpp b/modules/mono/mono_gd/support/android_support.cpp index 8858dd0fa99..5831dc80032 100755 --- a/modules/mono/mono_gd/support/android_support.cpp +++ b/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 determine_app_native_lib_dir() { - JNIEnv *env = ThreadAndroid::get_env(); + JNIEnv *env = get_jni_env(); ScopedLocalRef activityThreadClass(env, env->FindClass("android/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 if (build_version_sdk_int == 0) { - JNIEnv *env = ThreadAndroid::get_env(); + JNIEnv *env = get_jni_env(); jclass versionClass = env->FindClass("android/os/Build$VERSION"); ERR_FAIL_NULL_V(versionClass, 0); @@ -281,7 +281,7 @@ MonoBoolean _gd_mono_init_cert_store() { // return false; // } - JNIEnv *env = ThreadAndroid::get_env(); + JNIEnv *env = get_jni_env(); ScopedLocalRef keyStoreClass(env, env->FindClass("java/security/KeyStore")); @@ -322,7 +322,7 @@ MonoArray *_gd_mono_android_cert_store_lookup(MonoString *p_alias) { return NULL; } - JNIEnv *env = ThreadAndroid::get_env(); + JNIEnv *env = get_jni_env(); ScopedLocalRef js_alias(env, env->NewStringUTF(alias_utf8)); mono_free(alias_utf8); @@ -380,7 +380,7 @@ void cleanup() { if (godot_dl_handle) gd_mono_android_dlclose(godot_dl_handle, NULL); - JNIEnv *env = ThreadAndroid::get_env(); + JNIEnv *env = get_jni_env(); if (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; - JNIEnv *env = ThreadAndroid::get_env(); + JNIEnv *env = get_jni_env(); jclass networkInterfaceClass = env->FindClass("java/net/NetworkInterface"); 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; - JNIEnv *env = ThreadAndroid::get_env(); + JNIEnv *env = get_jni_env(); jclass networkInterfaceClass = env->FindClass("java/net/NetworkInterface"); 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); #endif - JNIEnv *env = ThreadAndroid::get_env(); + JNIEnv *env = get_jni_env(); GodotJavaWrapper *godot_java = ((OS_Android *)OS::get_singleton())->get_godot_java(); jobject activity = godot_java->get_activity(); @@ -649,7 +649,7 @@ GD_PINVOKE_EXPORT const char *_monodroid_timezone_get_default_id() { // // TimeZone.getDefault().getID() - JNIEnv *env = ThreadAndroid::get_env(); + JNIEnv *env = get_jni_env(); ScopedLocalRef timeZoneClass(env, env->FindClass("java/util/TimeZone")); ERR_FAIL_NULL_V(timeZoneClass, NULL); diff --git a/modules/opensimplex/noise_texture.cpp b/modules/opensimplex/noise_texture.cpp index 00caa43caaf..e6de7a4d31b 100644 --- a/modules/opensimplex/noise_texture.cpp +++ b/modules/opensimplex/noise_texture.cpp @@ -34,7 +34,6 @@ NoiseTexture::NoiseTexture() { update_queued = false; - noise_thread = NULL; regen_queued = false; first_time = true; @@ -53,10 +52,7 @@ NoiseTexture::NoiseTexture() { NoiseTexture::~NoiseTexture() { 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() { @@ -110,11 +106,9 @@ void NoiseTexture::_set_texture_data(const Ref &p_image) { void NoiseTexture::_thread_done(const Ref &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) { - noise_thread = Thread::create(_thread_function, this); + noise_thread.start(_thread_function, this); regen_queued = false; } } @@ -168,8 +162,8 @@ void NoiseTexture::_update_texture() { #endif 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; } else { regen_queued = true; diff --git a/modules/opensimplex/noise_texture.h b/modules/opensimplex/noise_texture.h index e83f55653ee..6fa8c12d640 100644 --- a/modules/opensimplex/noise_texture.h +++ b/modules/opensimplex/noise_texture.h @@ -45,7 +45,7 @@ class NoiseTexture : public Texture { private: Ref data; - Thread *noise_thread; + Thread noise_thread; bool first_time; bool update_queued; diff --git a/modules/theora/video_stream_theora.cpp b/modules/theora/video_stream_theora.cpp index 9899c6efcce..631105613f5 100644 --- a/modules/theora/video_stream_theora.cpp +++ b/modules/theora/video_stream_theora.cpp @@ -142,9 +142,7 @@ void VideoStreamPlaybackTheora::clear() { #ifdef THEORA_USE_THREAD_STREAMING thread_exit = true; thread_sem.post(); //just in case - Thread::wait_to_finish(thread); - memdelete(thread); - thread = NULL; + thread.wait_to_finish(); ring_buffer.clear(); #endif @@ -184,7 +182,7 @@ void VideoStreamPlaybackTheora::set_file(const String &p_file) { int read = file->get_buffer(read_buffer.ptr(), to_read); ring_buffer.write(read_buffer.ptr(), read); - thread = Thread::create(_streaming_thread, this); + thread.start(_streaming_thread, this); #endif @@ -693,7 +691,6 @@ VideoStreamPlaybackTheora::VideoStreamPlaybackTheora() { int rb_power = nearest_shift(RB_SIZE_KB * 1024); ring_buffer.resize(rb_power); read_buffer.resize(RB_SIZE_KB * 1024); - thread = NULL; thread_exit = false; thread_eof = false; diff --git a/modules/theora/video_stream_theora.h b/modules/theora/video_stream_theora.h index b86e8547aab..6f651feb9a1 100644 --- a/modules/theora/video_stream_theora.h +++ b/modules/theora/video_stream_theora.h @@ -113,7 +113,7 @@ class VideoStreamPlaybackTheora : public VideoStreamPlayback { Vector read_buffer; bool thread_eof; Semaphore thread_sem; - Thread *thread; + Thread thread; volatile bool thread_exit; static void _streaming_thread(void *ud); diff --git a/platform/android/api/jni_singleton.h b/platform/android/api/jni_singleton.h index 0cbb2d287a1..122d7b6522f 100644 --- a/platform/android/api/jni_singleton.h +++ b/platform/android/api/jni_singleton.h @@ -87,7 +87,7 @@ public: v = (jvalue *)alloca(sizeof(jvalue) * p_argcount); } - JNIEnv *env = ThreadAndroid::get_env(); + JNIEnv *env = get_jni_env(); int res = env->PushLocalFrame(16); diff --git a/platform/android/audio_driver_jandroid.cpp b/platform/android/audio_driver_jandroid.cpp index 1538c693c1b..fa36acdc04b 100644 --- a/platform/android/audio_driver_jandroid.cpp +++ b/platform/android/audio_driver_jandroid.cpp @@ -74,7 +74,7 @@ Error AudioDriverAndroid::init() { // __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 latency = GLOBAL_GET("audio/output_latency"); @@ -101,7 +101,7 @@ void AudioDriverAndroid::start() { void AudioDriverAndroid::setup(jobject p_io) { - JNIEnv *env = ThreadAndroid::get_env(); + JNIEnv *env = get_jni_env(); io = p_io; jclass c = env->GetObjectClass(io); @@ -176,7 +176,7 @@ void AudioDriverAndroid::unlock() { void AudioDriverAndroid::finish() { - JNIEnv *env = ThreadAndroid::get_env(); + JNIEnv *env = get_jni_env(); env->CallVoidMethod(io, _quit); if (audioBuffer) { @@ -190,7 +190,7 @@ void AudioDriverAndroid::finish() { void AudioDriverAndroid::set_pause(bool p_pause) { - JNIEnv *env = ThreadAndroid::get_env(); + JNIEnv *env = get_jni_env(); env->CallVoidMethod(io, _pause, p_pause); } diff --git a/platform/android/dir_access_jandroid.cpp b/platform/android/dir_access_jandroid.cpp index cf19b6452ba..7c0ddb48e7f 100644 --- a/platform/android/dir_access_jandroid.cpp +++ b/platform/android/dir_access_jandroid.cpp @@ -49,7 +49,7 @@ DirAccess *DirAccessJAndroid::create_fs() { Error DirAccessJAndroid::list_dir_begin() { list_dir_end(); - JNIEnv *env = ThreadAndroid::get_env(); + JNIEnv *env = get_jni_env(); jstring js = env->NewStringUTF(current_dir.utf8().get_data()); int res = env->CallIntMethod(io, _dir_open, js); @@ -65,7 +65,7 @@ String DirAccessJAndroid::get_next() { 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); if (!str) return ""; @@ -77,7 +77,7 @@ String DirAccessJAndroid::get_next() { bool DirAccessJAndroid::current_is_dir() const { - JNIEnv *env = ThreadAndroid::get_env(); + JNIEnv *env = get_jni_env(); return env->CallBooleanMethod(io, _dir_is_dir, id); } @@ -92,7 +92,7 @@ void DirAccessJAndroid::list_dir_end() { if (id == 0) return; - JNIEnv *env = ThreadAndroid::get_env(); + JNIEnv *env = get_jni_env(); env->CallVoidMethod(io, _dir_close, id); id = 0; } @@ -109,7 +109,7 @@ String DirAccessJAndroid::get_drive(int p_drive) { 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 == "")) return OK; @@ -166,7 +166,7 @@ bool DirAccessJAndroid::file_exists(String p_file) { bool DirAccessJAndroid::dir_exists(String p_dir) { - JNIEnv *env = ThreadAndroid::get_env(); + JNIEnv *env = get_jni_env(); String sd; @@ -225,7 +225,7 @@ size_t DirAccessJAndroid::get_space_left() { void DirAccessJAndroid::setup(jobject p_io) { - JNIEnv *env = ThreadAndroid::get_env(); + JNIEnv *env = get_jni_env(); io = p_io; jclass c = env->GetObjectClass(io); diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp index 7d976b1d5aa..9001dd2e8a2 100644 --- a/platform/android/export/export.cpp +++ b/platform/android/export/export.cpp @@ -272,7 +272,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { Vector devices; volatile bool devices_changed; Mutex device_lock; - Thread *check_for_changes_thread; + Thread check_for_changes_thread; volatile bool quit_request; static void _check_for_changes_poll_thread(void *ud) { @@ -3284,13 +3284,12 @@ public: plugins_changed = true; 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() { quit_request = true; - Thread::wait_to_finish(check_for_changes_thread); - memdelete(check_for_changes_thread); + check_for_changes_thread.wait_to_finish(); } }; diff --git a/platform/android/java_class_wrapper.cpp b/platform/android/java_class_wrapper.cpp index fbdd92a34e0..2a071dcf48d 100644 --- a/platform/android/java_class_wrapper.cpp +++ b/platform/android/java_class_wrapper.cpp @@ -38,7 +38,7 @@ bool JavaClass::_call_method(JavaObject *p_instance, const StringName &p_method, if (!M) return false; - JNIEnv *env = ThreadAndroid::get_env(); + JNIEnv *env = get_jni_env(); MethodInfo *method = NULL; for (List::Element *E = M->get().front(); E; E = E->next()) { @@ -1048,7 +1048,7 @@ Ref JavaClassWrapper::wrap(const String &p_class) { if (class_cache.has(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()); ERR_FAIL_COND_V(!bclass, Ref()); @@ -1242,7 +1242,7 @@ JavaClassWrapper::JavaClassWrapper(jobject p_activity) { singleton = this; - JNIEnv *env = ThreadAndroid::get_env(); + JNIEnv *env = get_jni_env(); jclass activityClass = env->FindClass("android/app/Activity"); jmethodID getClassLoader = env->GetMethodID(activityClass, "getClassLoader", "()Ljava/lang/ClassLoader;"); diff --git a/platform/android/java_godot_io_wrapper.cpp b/platform/android/java_godot_io_wrapper.cpp index 1ad70bc6cca..d773c87af13 100644 --- a/platform/android/java_godot_io_wrapper.cpp +++ b/platform/android/java_godot_io_wrapper.cpp @@ -76,7 +76,7 @@ jobject GodotIOJavaWrapper::get_instance() { Error GodotIOJavaWrapper::open_uri(const String &p_uri) { if (_open_URI) { - JNIEnv *env = ThreadAndroid::get_env(); + JNIEnv *env = get_jni_env(); jstring jStr = env->NewStringUTF(p_uri.utf8().get_data()); return env->CallIntMethod(godot_io_instance, _open_URI, jStr) ? ERR_CANT_OPEN : OK; } else { @@ -86,7 +86,7 @@ Error GodotIOJavaWrapper::open_uri(const String &p_uri) { String GodotIOJavaWrapper::get_user_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); return jstring_to_string(s, env); } else { @@ -96,7 +96,7 @@ String GodotIOJavaWrapper::get_user_data_dir() { String GodotIOJavaWrapper::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); return jstring_to_string(s, env); } else { @@ -106,7 +106,7 @@ String GodotIOJavaWrapper::get_locale() { String GodotIOJavaWrapper::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); return jstring_to_string(s, env); } else { @@ -116,7 +116,7 @@ String GodotIOJavaWrapper::get_model() { int GodotIOJavaWrapper::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); } else { return 160; @@ -125,7 +125,7 @@ int GodotIOJavaWrapper::get_screen_dpi() { void GodotIOJavaWrapper::get_window_safe_area(int (&p_rect_xywh)[4]) { 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); ERR_FAIL_COND(env->GetArrayLength(returnArray) != 4); 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() { 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); return jstring_to_string(s, env); } 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) { if (_show_keyboard) { - JNIEnv *env = ThreadAndroid::get_env(); + JNIEnv *env = get_jni_env(); 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); } @@ -160,21 +160,21 @@ void GodotIOJavaWrapper::show_vk(const String &p_existing, bool p_multiline, int void GodotIOJavaWrapper::hide_vk() { if (_hide_keyboard) { - JNIEnv *env = ThreadAndroid::get_env(); + JNIEnv *env = get_jni_env(); env->CallVoidMethod(godot_io_instance, _hide_keyboard); } } void GodotIOJavaWrapper::set_screen_orientation(int p_orient) { if (_set_screen_orientation) { - JNIEnv *env = ThreadAndroid::get_env(); + JNIEnv *env = get_jni_env(); env->CallVoidMethod(godot_io_instance, _set_screen_orientation, p_orient); } } int GodotIOJavaWrapper::get_screen_orientation() const { if (_get_screen_orientation) { - JNIEnv *env = ThreadAndroid::get_env(); + JNIEnv *env = get_jni_env(); return env->CallIntMethod(godot_io_instance, _get_screen_orientation); } else { return 0; @@ -183,7 +183,7 @@ int GodotIOJavaWrapper::get_screen_orientation() const { String GodotIOJavaWrapper::get_system_dir(int p_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); return jstring_to_string(s, env); } else { @@ -197,7 +197,7 @@ void GodotIOJavaWrapper::play_video(const String &p_path) { bool GodotIOJavaWrapper::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); } else { return false; @@ -206,14 +206,14 @@ bool GodotIOJavaWrapper::is_video_playing() { void GodotIOJavaWrapper::pause_video() { if (_pause_video) { - JNIEnv *env = ThreadAndroid::get_env(); + JNIEnv *env = get_jni_env(); env->CallVoidMethod(godot_io_instance, _pause_video); } } void GodotIOJavaWrapper::stop_video() { if (_stop_video) { - JNIEnv *env = ThreadAndroid::get_env(); + JNIEnv *env = get_jni_env(); env->CallVoidMethod(godot_io_instance, _stop_video); } } diff --git a/platform/android/java_godot_lib_jni.cpp b/platform/android/java_godot_lib_jni.cpp index 4e8c9f568b0..cd3e2c1cbdd 100644 --- a/platform/android/java_godot_lib_jni.cpp +++ b/platform/android/java_godot_lib_jni.cpp @@ -84,7 +84,7 @@ static void _initialize_java_modules() { // TODO create wrapper for class loader - JNIEnv *env = ThreadAndroid::get_env(); + JNIEnv *env = get_jni_env(); jclass classLoader = env->FindClass("java/lang/ClassLoader"); 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_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); @@ -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) { - ThreadAndroid::setup_thread(); + setup_android_thread(); const char **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) { - ThreadAndroid::setup_thread(); + setup_android_thread(); AudioDriverAndroid::thread_func(env); } diff --git a/platform/android/java_godot_wrapper.cpp b/platform/android/java_godot_wrapper.cpp index 8e440eb2b2b..a5168b86466 100644 --- a/platform/android/java_godot_wrapper.cpp +++ b/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) { if (godot_class) { 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); 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() { if (_get_class_loader) { - JNIEnv *env = ThreadAndroid::get_env(); + JNIEnv *env = get_jni_env(); return env->CallObjectMethod(activity, _get_class_loader); } else { return NULL; @@ -119,7 +119,7 @@ void GodotJavaWrapper::gfx_init(bool gl2) { void GodotJavaWrapper::on_video_init(JNIEnv *p_env) { if (_on_video_init) if (p_env == NULL) - p_env = ThreadAndroid::get_env(); + p_env = get_jni_env(); 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) { if (_on_godot_main_loop_started) { if (p_env == NULL) { - p_env = ThreadAndroid::get_env(); + p_env = get_jni_env(); } } 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) { if (_restart) if (p_env == NULL) - p_env = ThreadAndroid::get_env(); + p_env = get_jni_env(); p_env->CallVoidMethod(godot_instance, _restart); } @@ -144,21 +144,21 @@ void GodotJavaWrapper::restart(JNIEnv *p_env) { void GodotJavaWrapper::force_quit(JNIEnv *p_env) { if (_finish) if (p_env == NULL) - p_env = ThreadAndroid::get_env(); + p_env = get_jni_env(); p_env->CallVoidMethod(godot_instance, _finish); } void GodotJavaWrapper::set_keep_screen_on(bool p_enabled) { 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); } } void GodotJavaWrapper::alert(const String &p_message, const String &p_title) { if (_alert) { - JNIEnv *env = ThreadAndroid::get_env(); + JNIEnv *env = get_jni_env(); jstring jStrMessage = env->NewStringUTF(p_message.utf8().get_data()); jstring jStrTitle = env->NewStringUTF(p_title.utf8().get_data()); 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() { - JNIEnv *env = ThreadAndroid::get_env(); + JNIEnv *env = get_jni_env(); if (_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() { if (_get_clipboard) { - JNIEnv *env = ThreadAndroid::get_env(); + JNIEnv *env = get_jni_env(); jstring s = (jstring)env->CallObjectMethod(godot_instance, _get_clipboard); return jstring_to_string(s, env); } else { @@ -190,7 +190,7 @@ String GodotJavaWrapper::get_clipboard() { String GodotJavaWrapper::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); return jstring_to_string(fallback_mapping, env); } else { @@ -204,7 +204,7 @@ bool GodotJavaWrapper::has_set_clipboard() { void GodotJavaWrapper::set_clipboard(const String &p_text) { if (_set_clipboard) { - JNIEnv *env = ThreadAndroid::get_env(); + JNIEnv *env = get_jni_env(); jstring jStr = env->NewStringUTF(p_text.utf8().get_data()); 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) { if (_request_permission) { - JNIEnv *env = ThreadAndroid::get_env(); + JNIEnv *env = get_jni_env(); jstring jStrName = env->NewStringUTF(p_name.utf8().get_data()); return env->CallBooleanMethod(godot_instance, _request_permission, jStrName); } else { @@ -222,7 +222,7 @@ bool GodotJavaWrapper::request_permission(const String &p_name) { bool GodotJavaWrapper::request_permissions() { if (_request_permissions) { - JNIEnv *env = ThreadAndroid::get_env(); + JNIEnv *env = get_jni_env(); return env->CallBooleanMethod(godot_instance, _request_permissions); } else { return false; @@ -232,7 +232,7 @@ bool GodotJavaWrapper::request_permissions() { Vector GodotJavaWrapper::get_granted_permissions() const { Vector permissions_list; if (_get_granted_permissions) { - JNIEnv *env = ThreadAndroid::get_env(); + JNIEnv *env = get_jni_env(); jobject permissions_object = env->CallObjectMethod(godot_instance, _get_granted_permissions); jobjectArray *arr = reinterpret_cast(&permissions_object); @@ -250,14 +250,14 @@ Vector GodotJavaWrapper::get_granted_permissions() const { void GodotJavaWrapper::init_input_devices() { if (_init_input_devices) { - JNIEnv *env = ThreadAndroid::get_env(); + JNIEnv *env = get_jni_env(); env->CallVoidMethod(godot_instance, _init_input_devices); } } jobject GodotJavaWrapper::get_surface() { if (_get_surface) { - JNIEnv *env = ThreadAndroid::get_env(); + JNIEnv *env = get_jni_env(); return env->CallObjectMethod(godot_instance, _get_surface); } else { return NULL; @@ -266,7 +266,7 @@ jobject GodotJavaWrapper::get_surface() { bool GodotJavaWrapper::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); } else { return false; @@ -275,7 +275,7 @@ bool GodotJavaWrapper::is_activity_resumed() { void GodotJavaWrapper::vibrate(int p_duration_ms) { if (_vibrate) { - JNIEnv *env = ThreadAndroid::get_env(); + JNIEnv *env = get_jni_env(); env->CallVoidMethod(godot_instance, _vibrate, p_duration_ms); } } diff --git a/platform/android/net_socket_android.cpp b/platform/android/net_socket_android.cpp index 2dc9431cf24..067135dd6a1 100644 --- a/platform/android/net_socket_android.cpp +++ b/platform/android/net_socket_android.cpp @@ -39,7 +39,7 @@ jmethodID NetSocketAndroid::_multicast_lock_release = 0; void NetSocketAndroid::setup(jobject p_net_utils) { - JNIEnv *env = ThreadAndroid::get_env(); + JNIEnv *env = get_jni_env(); net_utils = env->NewGlobalRef(p_net_utils); @@ -52,14 +52,14 @@ void NetSocketAndroid::setup(jobject p_net_utils) { void NetSocketAndroid::multicast_lock_acquire() { if (_multicast_lock_acquire) { - JNIEnv *env = ThreadAndroid::get_env(); + JNIEnv *env = get_jni_env(); env->CallVoidMethod(net_utils, _multicast_lock_acquire); } } void NetSocketAndroid::multicast_lock_release() { if (_multicast_lock_release) { - JNIEnv *env = ThreadAndroid::get_env(); + JNIEnv *env = get_jni_env(); env->CallVoidMethod(net_utils, _multicast_lock_release); } } diff --git a/platform/android/string_android.h b/platform/android/string_android.h index a220d354f11..d845e2f8a40 100644 --- a/platform/android/string_android.h +++ b/platform/android/string_android.h @@ -37,14 +37,14 @@ /** * Converts JNI jstring to Godot String. * @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. */ static inline String jstring_to_string(jstring source, JNIEnv *env = NULL) { String result; if (source) { if (!env) { - env = ThreadAndroid::get_env(); + env = get_jni_env(); } const char *const source_utf8 = env->GetStringUTFChars(source, NULL); if (source_utf8) { diff --git a/platform/android/thread_jandroid.cpp b/platform/android/thread_jandroid.cpp index ab370e8317e..afcc7294f29 100644 --- a/platform/android/thread_jandroid.cpp +++ b/platform/android/thread_jandroid.cpp @@ -30,127 +30,29 @@ #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(p_value)); +static JavaVM *java_vm = nullptr; +static thread_local JNIEnv *env = nullptr; + +static void init_thread() { + java_vm->AttachCurrentThread(&env, nullptr); } -static pthread_key_t _create_thread_id_key() { - pthread_key_t key; - pthread_key_create(&key, &_thread_id_key_destr_callback); - return key; +static void term_thread() { + java_vm->DetachCurrentThread(); } -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; +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); } -Thread *ThreadAndroid::create_thread_jandroid() { - - return memnew(ThreadAndroid); +void setup_android_thread() { + init_thread(); } -void *ThreadAndroid::thread_callback(void *userdata) { - - ThreadAndroid *t = reinterpret_cast(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; -} - -Thread::ID ThreadAndroid::get_thread_id_func_jandroid() { - - void *value = pthread_getspecific(thread_id_key); - - if (value) - return *static_cast(value); - - ID new_id = atomic_increment(&next_thread_id); - pthread_setspecific(thread_id_key, (void *)memnew(ID(new_id))); - return new_id; -} - -void ThreadAndroid::wait_to_finish_func_jandroid(Thread *p_thread) { - - ThreadAndroid *tp = static_cast(p_thread); - ERR_FAIL_COND(!tp); - ERR_FAIL_COND(tp->pthread == 0); - - pthread_join(tp->pthread, NULL); - tp->pthread = 0; -} - -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 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(); -} - -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; } - -ThreadAndroid::ThreadAndroid() { - - pthread = 0; -} - -ThreadAndroid::~ThreadAndroid() { -} diff --git a/platform/android/thread_jandroid.h b/platform/android/thread_jandroid.h index 87152de7a3b..ff13ae911ff 100644 --- a/platform/android/thread_jandroid.h +++ b/platform/android/thread_jandroid.h @@ -28,47 +28,14 @@ /* 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 -#include -#include -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 diff --git a/platform/iphone/export/export.cpp b/platform/iphone/export/export.cpp index 7e3bc273bfe..ceb296f5480 100644 --- a/platform/iphone/export/export.cpp +++ b/platform/iphone/export/export.cpp @@ -56,7 +56,7 @@ class EditorExportPlatformIOS : public EditorExportPlatform { // Plugins volatile bool plugins_changed; - Thread *check_for_changes_thread; + Thread check_for_changes_thread; volatile bool quit_request; Mutex plugins_lock; Vector plugins; @@ -1839,13 +1839,12 @@ EditorExportPlatformIOS::EditorExportPlatformIOS() { plugins_changed = true; 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() { 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() { diff --git a/platform/javascript/audio_driver_javascript.cpp b/platform/javascript/audio_driver_javascript.cpp index e59815f4342..c65d9425e1d 100644 --- a/platform/javascript/audio_driver_javascript.cpp +++ b/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) { 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() { @@ -280,8 +280,6 @@ void AudioDriverJavaScript::WorkletNode::unlock() { void AudioDriverJavaScript::WorkletNode::finish() { quit = true; // Ask thread to quit. - Thread::wait_to_finish(thread); - memdelete(thread); - thread = nullptr; + thread.wait_to_finish(); } #endif diff --git a/platform/javascript/audio_driver_javascript.h b/platform/javascript/audio_driver_javascript.h index d55ec261a46..393693640f8 100644 --- a/platform/javascript/audio_driver_javascript.h +++ b/platform/javascript/audio_driver_javascript.h @@ -59,7 +59,7 @@ public: STATE_MAX, }; Mutex mutex; - Thread *thread = nullptr; + Thread thread; bool quit = false; int32_t state[STATE_MAX] = { 0 }; diff --git a/platform/javascript/export/export.cpp b/platform/javascript/export/export.cpp index 6d2aa1aeb15..4fd59b7bec4 100644 --- a/platform/javascript/export/export.cpp +++ b/platform/javascript/export/export.cpp @@ -213,7 +213,7 @@ class EditorExportPlatformJavaScript : public EditorExportPlatform { Ref server; bool server_quit = false; Mutex server_lock; - Thread *server_thread = NULL; + Thread server_thread; enum ExportMode { EXPORT_MODE_NORMAL = 0, @@ -696,7 +696,7 @@ void EditorExportPlatformJavaScript::_server_thread_poll(void *data) { EditorExportPlatformJavaScript::EditorExportPlatformJavaScript() { server.instance(); - server_thread = Thread::create(_server_thread_poll, this); + server_thread.start(_server_thread_poll, this); Ref img = memnew(Image(_javascript_logo)); logo.instance(); @@ -716,8 +716,7 @@ EditorExportPlatformJavaScript::EditorExportPlatformJavaScript() { EditorExportPlatformJavaScript::~EditorExportPlatformJavaScript() { server->stop(); server_quit = true; - Thread::wait_to_finish(server_thread); - memdelete(server_thread); + server_thread.wait_to_finish(); } void register_javascript_exporter() { diff --git a/platform/uwp/app.h b/platform/uwp/app.h index 4a41df024ba..31d8c18d3fb 100644 --- a/platform/uwp/app.h +++ b/platform/uwp/app.h @@ -78,9 +78,9 @@ namespace GodotUWP 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); - Windows::System::Threading::Core::SignalNotifier^ mouseChangedNotifier; + Windows::System::Thread ing::Core::SignalNotifier^ mouseChangedNotifier; 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 OnKeyDown(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::KeyEventArgs^ args); diff --git a/platform/uwp/os_uwp.cpp b/platform/uwp/os_uwp.cpp index fa739593259..6e9cb4bab48 100644 --- a/platform/uwp/os_uwp.cpp +++ b/platform/uwp/os_uwp.cpp @@ -45,7 +45,6 @@ #include "servers/audio_server.h" #include "servers/visual/visual_server_raster.h" #include "servers/visual/visual_server_wrap_mt.h" -#include "thread_uwp.h" #include #include @@ -137,8 +136,6 @@ void OS_UWP::initialize_core() { //RedirectIOToConsole(); - ThreadUWP::make_default(); - FileAccess::make_default(FileAccess::ACCESS_RESOURCES); FileAccess::make_default(FileAccess::ACCESS_USERDATA); FileAccess::make_default(FileAccess::ACCESS_FILESYSTEM); diff --git a/platform/uwp/thread_uwp.cpp b/platform/uwp/thread_uwp.cpp deleted file mode 100644 index 105adf6e77c..00000000000 --- a/platform/uwp/thread_uwp.cpp +++ /dev/null @@ -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::this_thread::get_id()); -}; - -void ThreadUWP::wait_to_finish_func_uwp(Thread *p_thread) { - - ThreadUWP *tp = static_cast(p_thread); - tp->thread.join(); -}; - -Thread::ID ThreadUWP::get_id() const { - - return std::hash()(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(){ - -}; diff --git a/platform/uwp/thread_uwp.h b/platform/uwp/thread_uwp.h deleted file mode 100644 index c72a080302f..00000000000 --- a/platform/uwp/thread_uwp.h +++ /dev/null @@ -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 - -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 diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index 6c41190c04b..a49a41ce620 100755 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -40,7 +40,6 @@ #include "drivers/gles3/rasterizer_gles3.h" #include "drivers/windows/dir_access_windows.h" #include "drivers/windows/file_access_windows.h" -#include "drivers/windows/thread_windows.h" #include "joypad_windows.h" #include "lang_table.h" #include "main/main.h" @@ -224,8 +223,6 @@ void OS_Windows::initialize_core() { minimized = false; borderless = false; - ThreadWindows::make_default(); - FileAccess::make_default(FileAccess::ACCESS_RESOURCES); FileAccess::make_default(FileAccess::ACCESS_USERDATA); FileAccess::make_default(FileAccess::ACCESS_FILESYSTEM); diff --git a/platform/x11/joypad_linux.cpp b/platform/x11/joypad_linux.cpp index e1490453db6..6e3c1101d17 100644 --- a/platform/x11/joypad_linux.cpp +++ b/platform/x11/joypad_linux.cpp @@ -94,13 +94,12 @@ JoypadLinux::JoypadLinux(InputDefault *in) { #endif exit_monitor = false; input = in; - joy_thread = Thread::create(joy_thread_func, this); + joy_thread.start(joy_thread_func, this); } JoypadLinux::~JoypadLinux() { exit_monitor = true; - Thread::wait_to_finish(joy_thread); - memdelete(joy_thread); + joy_thread.wait_to_finish(); close_joypad(); } diff --git a/platform/x11/joypad_linux.h b/platform/x11/joypad_linux.h index 9be66167fe5..21374d1b825 100644 --- a/platform/x11/joypad_linux.h +++ b/platform/x11/joypad_linux.h @@ -76,7 +76,7 @@ private: #endif bool exit_monitor; Mutex joy_mutex; - Thread *joy_thread; + Thread joy_thread; InputDefault *input; Joypad joypads[JOYPADS_MAX]; Vector attached_devices; diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp index 4b31a8fcc9a..46cf4249ada 100644 --- a/platform/x11/os_x11.cpp +++ b/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(); @@ -815,9 +815,7 @@ String OS_X11::get_unique_id() const { void OS_X11::finalize() { events_thread_done = true; - Thread::wait_to_finish(events_thread); - memdelete(events_thread); - events_thread = NULL; + events_thread.wait_to_finish(); if (main_loop) memdelete(main_loop); diff --git a/platform/x11/os_x11.h b/platform/x11/os_x11.h index 48bf1cedc6b..00ff81c21c2 100644 --- a/platform/x11/os_x11.h +++ b/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; mutable Mutex events_mutex; - Thread *events_thread = nullptr; + Thread events_thread; bool events_thread_done = false; LocalVector polled_events; static void _poll_events_thread(void *ud); diff --git a/scene/main/http_request.cpp b/scene/main/http_request.cpp index c8b19e6fd82..84aee07105f 100644 --- a/scene/main/http_request.cpp +++ b/scene/main/http_request.cpp @@ -113,7 +113,7 @@ Error HTTPRequest::request(const String &p_url, const Vector &p_custom_h thread_done = false; thread_request_quit = false; client->set_blocking_mode(true); - thread = Thread::create(_thread_func, this); + thread.start(_thread_func, this); } else { client->set_blocking_mode(false); err = _request(); @@ -160,9 +160,7 @@ void HTTPRequest::cancel_request() { set_process_internal(false); } else { thread_request_quit = true; - Thread::wait_to_finish(thread); - memdelete(thread); - thread = NULL; + thread.wait_to_finish(); } if (file) { @@ -568,8 +566,6 @@ void HTTPRequest::_bind_methods() { HTTPRequest::HTTPRequest() { - thread = NULL; - port = 80; redirections = 0; max_redirects = 8; diff --git a/scene/main/http_request.h b/scene/main/http_request.h index 552e303c068..0a4bd01d454 100644 --- a/scene/main/http_request.h +++ b/scene/main/http_request.h @@ -106,7 +106,7 @@ private: volatile bool thread_done; 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); static void _thread_func(void *p_userdata); diff --git a/scene/resources/sky.cpp b/scene/resources/sky.cpp index 5bd96bac0e6..0db92f21325 100644 --- a/scene/resources/sky.cpp +++ b/scene/resources/sky.cpp @@ -410,8 +410,8 @@ void ProceduralSky::_update_sky() { #endif 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; } else { regen_queued = true; @@ -440,11 +440,9 @@ void ProceduralSky::_thread_done(const Ref &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_set_data(texture, panorama); _radiance_changed(); - Thread::wait_to_finish(sky_thread); - memdelete(sky_thread); - sky_thread = NULL; + sky_thread.wait_to_finish(); if (regen_queued) { - sky_thread = Thread::create(_thread_function, this); + sky_thread.start(_thread_function, this); regen_queued = false; } } @@ -572,7 +570,6 @@ ProceduralSky::ProceduralSky(bool p_desaturate) { sun_energy = 1; texture_size = TEXTURE_SIZE_1024; - sky_thread = NULL; regen_queued = false; first_time = true; @@ -581,10 +578,8 @@ ProceduralSky::ProceduralSky(bool p_desaturate) { 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(texture); diff --git a/scene/resources/sky.h b/scene/resources/sky.h index 503b23976f1..5b5e6c70176 100644 --- a/scene/resources/sky.h +++ b/scene/resources/sky.h @@ -99,7 +99,7 @@ public: }; private: - Thread *sky_thread; + Thread sky_thread; Color sky_top_color; Color sky_horizon_color; float sky_curve; diff --git a/servers/audio/audio_driver_dummy.cpp b/servers/audio/audio_driver_dummy.cpp index ef111eaa60a..6afe67790eb 100644 --- a/servers/audio/audio_driver_dummy.cpp +++ b/servers/audio/audio_driver_dummy.cpp @@ -49,7 +49,7 @@ Error AudioDriverDummy::init() { samples_in = memnew_arr(int32_t, buffer_frames * channels); - thread = Thread::create(AudioDriverDummy::thread_func, this); + thread.start(AudioDriverDummy::thread_func, this); return OK; }; @@ -94,37 +94,26 @@ AudioDriver::SpeakerMode AudioDriverDummy::get_speaker_mode() const { void AudioDriverDummy::lock() { - if (!thread) - return; mutex.lock(); }; void AudioDriverDummy::unlock() { - if (!thread) - return; mutex.unlock(); }; void AudioDriverDummy::finish() { - if (!thread) - return; - exit_thread = true; - Thread::wait_to_finish(thread); + thread.wait_to_finish(); if (samples_in) { memdelete_arr(samples_in); }; - - memdelete(thread); - thread = NULL; }; -AudioDriverDummy::AudioDriverDummy() { +AudioDriverDummy::AudioDriverDummy(){ - thread = NULL; }; AudioDriverDummy::~AudioDriverDummy(){ diff --git a/servers/audio/audio_driver_dummy.h b/servers/audio/audio_driver_dummy.h index d7610e62f40..d46e9185fce 100644 --- a/servers/audio/audio_driver_dummy.h +++ b/servers/audio/audio_driver_dummy.h @@ -38,7 +38,7 @@ class AudioDriverDummy : public AudioDriver { - Thread *thread; + Thread thread; Mutex mutex; int32_t *samples_in; diff --git a/servers/audio/effects/audio_effect_record.cpp b/servers/audio/effects/audio_effect_record.cpp index 22392ec02ba..6485c57e141 100644 --- a/servers/audio/effects/audio_effect_record.cpp +++ b/servers/audio/effects/audio_effect_record.cpp @@ -119,7 +119,7 @@ void AudioEffectRecordInstance::init() { #ifdef NO_THREADS AudioServer::get_singleton()->add_update_callback(&AudioEffectRecordInstance::_update, this); #else - io_thread = Thread::create(_thread_callback, this); + io_thread.start(_thread_callback, this); #endif } @@ -129,7 +129,7 @@ void AudioEffectRecordInstance::finish() { AudioServer::get_singleton()->remove_update_callback(&AudioEffectRecordInstance::_update, this); #else if (thread_active) { - Thread::wait_to_finish(io_thread); + io_thread.wait_to_finish(); } #endif } diff --git a/servers/audio/effects/audio_effect_record.h b/servers/audio/effects/audio_effect_record.h index 7fc046440e3..481f89dfdd0 100644 --- a/servers/audio/effects/audio_effect_record.h +++ b/servers/audio/effects/audio_effect_record.h @@ -48,7 +48,7 @@ class AudioEffectRecordInstance : public AudioEffectInstance { Ref base; bool is_recording; - Thread *io_thread; + Thread io_thread; bool thread_active; Vector ring_buffer; diff --git a/servers/physics_2d/physics_2d_server_wrap_mt.cpp b/servers/physics_2d/physics_2d_server_wrap_mt.cpp index 9710d383887..046c3acd49c 100644 --- a/servers/physics_2d/physics_2d_server_wrap_mt.cpp +++ b/servers/physics_2d/physics_2d_server_wrap_mt.cpp @@ -109,9 +109,7 @@ void Physics2DServerWrapMT::init() { if (create_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) { OS::get_singleton()->delay_usec(1000); } @@ -123,13 +121,10 @@ void Physics2DServerWrapMT::init() { void Physics2DServerWrapMT::finish() { - if (thread) { + if (create_thread) { command_queue.push(this, &Physics2DServerWrapMT::thread_exit); - Thread::wait_to_finish(thread); - memdelete(thread); - - thread = NULL; + thread.wait_to_finish(); } else { physics_2d_server->finish(); } @@ -153,7 +148,6 @@ Physics2DServerWrapMT::Physics2DServerWrapMT(Physics2DServer *p_contained, bool physics_2d_server = p_contained; create_thread = p_create_thread; - thread = NULL; step_pending = 0; step_thread_up = false; diff --git a/servers/physics_2d/physics_2d_server_wrap_mt.h b/servers/physics_2d/physics_2d_server_wrap_mt.h index ed47756e4fc..0c9e560a504 100644 --- a/servers/physics_2d/physics_2d_server_wrap_mt.h +++ b/servers/physics_2d/physics_2d_server_wrap_mt.h @@ -54,7 +54,7 @@ class Physics2DServerWrapMT : public Physics2DServer { Thread::ID server_thread; Thread::ID main_thread; volatile bool exit; - Thread *thread; + Thread thread; volatile bool step_thread_up; bool create_thread; diff --git a/servers/visual/visual_server_scene.cpp b/servers/visual/visual_server_scene.cpp index 8b7264c74eb..fc1ca35aba8 100644 --- a/servers/visual/visual_server_scene.cpp +++ b/servers/visual/visual_server_scene.cpp @@ -3682,10 +3682,8 @@ VisualServerScene *VisualServerScene::singleton = NULL; 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; -#endif render_pass = 1; singleton = this; @@ -3694,10 +3692,7 @@ VisualServerScene::VisualServerScene() { VisualServerScene::~VisualServerScene() { -#ifndef NO_THREADS probe_bake_thread_exit = true; probe_bake_sem.post(); - Thread::wait_to_finish(probe_bake_thread); - memdelete(probe_bake_thread); -#endif + probe_bake_thread.wait_to_finish(); } diff --git a/servers/visual/visual_server_scene.h b/servers/visual/visual_server_scene.h index 7c2d6916de0..b5977c82a68 100644 --- a/servers/visual/visual_server_scene.h +++ b/servers/visual/visual_server_scene.h @@ -592,7 +592,7 @@ public: static void _gi_probe_bake_threads(void *); volatile bool probe_bake_thread_exit; - Thread *probe_bake_thread; + Thread probe_bake_thread; Semaphore probe_bake_sem; Mutex probe_bake_mutex; List probe_bake_list; diff --git a/servers/visual/visual_server_wrap_mt.cpp b/servers/visual/visual_server_wrap_mt.cpp index 5e6b45e020e..64288ad1565 100644 --- a/servers/visual/visual_server_wrap_mt.cpp +++ b/servers/visual/visual_server_wrap_mt.cpp @@ -110,7 +110,7 @@ void VisualServerWrapMT::init() { print_verbose("VisualServerWrapMT: Creating render thread"); OS::get_singleton()->release_rendering_thread(); if (create_thread) { - thread = Thread::create(_thread_callback, this); + thread.start(_thread_callback, this); print_verbose("VisualServerWrapMT: Starting render thread"); } while (!draw_thread_up) { @@ -125,13 +125,10 @@ void VisualServerWrapMT::init() { void VisualServerWrapMT::finish() { - if (thread) { + if (create_thread) { command_queue.push(this, &VisualServerWrapMT::thread_exit); - Thread::wait_to_finish(thread); - memdelete(thread); - - thread = NULL; + thread.wait_to_finish(); } else { visual_server->finish(); } @@ -177,7 +174,6 @@ VisualServerWrapMT::VisualServerWrapMT(VisualServer *p_contained, bool p_create_ visual_server = p_contained; create_thread = p_create_thread; - thread = NULL; draw_pending = 0; draw_thread_up = false; pool_max_size = GLOBAL_GET("memory/limits/multithreaded_server/rid_pool_prealloc"); diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h index 2366658c238..1b620c509ce 100644 --- a/servers/visual/visual_server_wrap_mt.h +++ b/servers/visual/visual_server_wrap_mt.h @@ -47,7 +47,7 @@ class VisualServerWrapMT : public VisualServer { Thread::ID server_thread; volatile bool exit; - Thread *thread; + Thread thread; volatile bool draw_thread_up; bool create_thread;